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 (assembly->image, info, ignoreCase, &type_resolve);
1370 if (!info->assembly.name && !type) /* try mscorlib */
1371 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1373 if (assembly && !type && type_resolve) {
1374 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1375 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1381 return mono_type_get_object_checked (mono_domain_get (), type, error);
1384 ICALL_EXPORT MonoReflectionType*
1385 ves_icall_System_Type_internal_from_name (MonoString *name,
1386 MonoBoolean throwOnError,
1387 MonoBoolean ignoreCase)
1390 char *str = mono_string_to_utf8 (name);
1391 MonoTypeNameParse info;
1392 MonoReflectionType *type;
1395 parsedOk = mono_reflection_parse_type (str, &info);
1397 /* mono_reflection_parse_type() mangles the string */
1399 mono_reflection_free_type_info (&info);
1402 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1407 type = type_from_parsed_name (&info, ignoreCase, &error);
1409 mono_reflection_free_type_info (&info);
1412 if (!mono_error_ok (&error)) {
1414 mono_error_set_pending_exception (&error);
1416 mono_error_cleanup (&error);
1421 MonoException *e = NULL;
1424 e = mono_get_exception_type_load (name, NULL);
1426 mono_loader_clear_error ();
1428 mono_set_pending_exception (e);
1437 ICALL_EXPORT MonoReflectionType*
1438 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1441 MonoReflectionType *ret;
1442 MonoDomain *domain = mono_domain_get ();
1444 ret = mono_type_get_object_checked (domain, handle, &error);
1445 mono_error_raise_exception (&error);
1450 /* System.TypeCode */
1469 TYPECODE_STRING = 18
1472 ICALL_EXPORT guint32
1473 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1475 int t = type->type->type;
1477 if (type->type->byref)
1478 return TYPECODE_OBJECT;
1482 case MONO_TYPE_VOID:
1483 return TYPECODE_OBJECT;
1484 case MONO_TYPE_BOOLEAN:
1485 return TYPECODE_BOOLEAN;
1487 return TYPECODE_BYTE;
1489 return TYPECODE_SBYTE;
1491 return TYPECODE_UINT16;
1493 return TYPECODE_INT16;
1494 case MONO_TYPE_CHAR:
1495 return TYPECODE_CHAR;
1499 return TYPECODE_OBJECT;
1501 return TYPECODE_UINT32;
1503 return TYPECODE_INT32;
1505 return TYPECODE_UINT64;
1507 return TYPECODE_INT64;
1509 return TYPECODE_SINGLE;
1511 return TYPECODE_DOUBLE;
1512 case MONO_TYPE_VALUETYPE: {
1513 MonoClass *klass = type->type->data.klass;
1515 if (klass->enumtype) {
1516 t = mono_class_enum_basetype (klass)->type;
1518 } else if (mono_is_corlib_image (klass->image)) {
1519 if (strcmp (klass->name_space, "System") == 0) {
1520 if (strcmp (klass->name, "Decimal") == 0)
1521 return TYPECODE_DECIMAL;
1522 else if (strcmp (klass->name, "DateTime") == 0)
1523 return TYPECODE_DATETIME;
1526 return TYPECODE_OBJECT;
1528 case MONO_TYPE_STRING:
1529 return TYPECODE_STRING;
1530 case MONO_TYPE_SZARRAY:
1531 case MONO_TYPE_ARRAY:
1532 case MONO_TYPE_OBJECT:
1534 case MONO_TYPE_MVAR:
1535 case MONO_TYPE_TYPEDBYREF:
1536 return TYPECODE_OBJECT;
1537 case MONO_TYPE_CLASS:
1539 MonoClass *klass = type->type->data.klass;
1540 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1541 if (strcmp (klass->name, "DBNull") == 0)
1542 return TYPECODE_DBNULL;
1545 return TYPECODE_OBJECT;
1546 case MONO_TYPE_GENERICINST:
1547 return TYPECODE_OBJECT;
1549 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1555 mono_type_is_primitive (MonoType *type)
1557 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1558 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1562 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1564 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1565 return mono_class_enum_basetype (type->data.klass);
1566 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1567 return mono_class_enum_basetype (type->data.generic_class->container_class);
1571 ICALL_EXPORT guint32
1572 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1577 g_assert (type != NULL);
1579 klass = mono_class_from_mono_type (type->type);
1580 klassc = mono_class_from_mono_type (c->type);
1582 if (type->type->byref ^ c->type->byref)
1585 if (type->type->byref) {
1586 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1587 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1589 klass = mono_class_from_mono_type (t);
1590 klassc = mono_class_from_mono_type (ot);
1592 if (mono_type_is_primitive (t)) {
1593 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1594 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1595 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1596 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1597 return t->type == ot->type;
1599 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1602 if (klass->valuetype)
1603 return klass == klassc;
1604 return klass->valuetype == klassc->valuetype;
1607 return mono_class_is_assignable_from (klass, klassc);
1610 ICALL_EXPORT guint32
1611 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1614 MonoClass *klass = mono_class_from_mono_type (type->type);
1615 mono_class_init_checked (klass, &error);
1616 mono_error_raise_exception (&error);
1617 return mono_object_isinst (obj, klass) != NULL;
1620 ICALL_EXPORT guint32
1621 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1623 MonoClass *klass = mono_class_from_mono_type (type->type);
1624 return klass->flags;
1627 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1628 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1631 MonoClass *klass = field->field->parent;
1632 MonoMarshalType *info;
1636 if (klass->generic_container ||
1637 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1640 ftype = mono_field_get_type (field->field);
1641 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1644 info = mono_marshal_load_type_info (klass);
1646 for (i = 0; i < info->num_fields; ++i) {
1647 if (info->fields [i].field == field->field) {
1648 if (!info->fields [i].mspec)
1651 MonoReflectionMarshalAsAttribute* obj;
1652 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1653 if (!mono_error_ok (&error))
1654 mono_error_set_pending_exception (&error);
1663 ICALL_EXPORT MonoReflectionField*
1664 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1667 gboolean found = FALSE;
1674 klass = handle->parent;
1676 klass = mono_class_from_mono_type (type);
1678 /* Check that the field belongs to the class */
1679 for (k = klass; k; k = k->parent) {
1680 if (k == handle->parent) {
1687 /* The managed code will throw the exception */
1691 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1692 mono_error_raise_exception (&error);
1696 ICALL_EXPORT MonoArray*
1697 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1700 MonoType *type = mono_field_get_type_checked (field->field, &error);
1703 if (!mono_error_ok (&error)) {
1704 mono_error_set_pending_exception (&error);
1708 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1709 mono_error_raise_exception (&error);
1714 vell_icall_get_method_attributes (MonoMethod *method)
1716 return method->flags;
1720 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1723 MonoReflectionType *rt;
1724 MonoDomain *domain = mono_domain_get ();
1725 MonoMethodSignature* sig;
1727 sig = mono_method_signature_checked (method, &error);
1728 if (!mono_error_ok (&error)) {
1729 mono_error_set_pending_exception (&error);
1733 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1734 if (!mono_error_ok (&error)) {
1735 mono_error_set_pending_exception (&error);
1739 MONO_STRUCT_SETREF (info, parent, rt);
1741 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1742 if (!mono_error_ok (&error)) {
1743 mono_error_set_pending_exception (&error);
1747 MONO_STRUCT_SETREF (info, ret, rt);
1749 info->attrs = method->flags;
1750 info->implattrs = method->iflags;
1751 if (sig->call_convention == MONO_CALL_DEFAULT)
1752 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1754 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1759 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1762 ICALL_EXPORT MonoArray*
1763 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1766 MonoDomain *domain = mono_domain_get ();
1768 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1769 mono_error_set_pending_exception (&error);
1773 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1774 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1777 MonoDomain *domain = mono_domain_get ();
1778 MonoReflectionMarshalAsAttribute* res = NULL;
1779 MonoMarshalSpec **mspecs;
1782 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1783 mono_method_get_marshal_info (method, mspecs);
1786 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1787 if (!mono_error_ok (&error)) {
1788 mono_error_set_pending_exception (&error);
1793 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1795 mono_metadata_free_marshal_spec (mspecs [i]);
1802 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1804 MonoClass *parent = field->field->parent;
1805 if (!parent->size_inited)
1806 mono_class_init (parent);
1807 mono_class_setup_fields_locking (parent);
1809 return field->field->offset - sizeof (MonoObject);
1812 ICALL_EXPORT MonoReflectionType*
1813 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1816 MonoReflectionType *ret;
1819 parent = declaring? field->field->parent: field->klass;
1821 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1822 mono_error_raise_exception (&error);
1828 ICALL_EXPORT MonoObject *
1829 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1832 MonoClass *fklass = field->klass;
1833 MonoClassField *cf = field->field;
1834 MonoDomain *domain = mono_object_domain (field);
1836 if (fklass->image->assembly->ref_only) {
1837 mono_set_pending_exception (mono_get_exception_invalid_operation (
1838 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1842 if (mono_security_core_clr_enabled ())
1843 mono_security_core_clr_ensure_reflection_access_field (cf);
1845 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1846 mono_error_set_pending_exception (&error);
1851 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1854 MonoClassField *cf = field->field;
1858 if (field->klass->image->assembly->ref_only) {
1859 mono_set_pending_exception (mono_get_exception_invalid_operation (
1860 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1864 if (mono_security_core_clr_enabled ())
1865 mono_security_core_clr_ensure_reflection_access_field (cf);
1867 type = mono_field_get_type_checked (cf, &error);
1868 if (!mono_error_ok (&error)) {
1869 mono_error_set_pending_exception (&error);
1873 v = (gchar *) value;
1875 switch (type->type) {
1878 case MONO_TYPE_BOOLEAN:
1881 case MONO_TYPE_CHAR:
1890 case MONO_TYPE_VALUETYPE:
1893 v += sizeof (MonoObject);
1895 case MONO_TYPE_STRING:
1896 case MONO_TYPE_OBJECT:
1897 case MONO_TYPE_CLASS:
1898 case MONO_TYPE_ARRAY:
1899 case MONO_TYPE_SZARRAY:
1902 case MONO_TYPE_GENERICINST: {
1903 MonoGenericClass *gclass = type->data.generic_class;
1904 g_assert (!gclass->context.class_inst->is_open);
1906 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1907 MonoClass *nklass = mono_class_from_mono_type (type);
1908 MonoObject *nullable;
1911 * Convert the boxed vtype into a Nullable structure.
1912 * This is complicated by the fact that Nullables have
1913 * a variable structure.
1915 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1916 if (!mono_error_ok (&error)) {
1917 mono_error_set_pending_exception (&error);
1921 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1923 v = (gchar *)mono_object_unbox (nullable);
1926 if (gclass->container_class->valuetype && (v != NULL))
1927 v += sizeof (MonoObject);
1931 g_error ("type 0x%x not handled in "
1932 "ves_icall_FieldInfo_SetValueInternal", type->type);
1937 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1938 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1939 if (!is_ok (&error)) {
1940 mono_error_set_pending_exception (&error);
1943 if (!vtable->initialized) {
1944 if (!mono_runtime_class_init_full (vtable, &error)) {
1945 mono_error_set_pending_exception (&error);
1949 mono_field_static_set_value (vtable, cf, v);
1951 mono_field_set_value (obj, cf, v);
1956 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1965 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1966 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1970 if (MONO_TYPE_IS_REFERENCE (f->type))
1971 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1973 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1976 ICALL_EXPORT MonoObject *
1977 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1979 MonoObject *o = NULL;
1980 MonoClassField *field = rfield->field;
1982 MonoDomain *domain = mono_object_domain (rfield);
1984 MonoTypeEnum def_type;
1985 const char *def_value;
1989 mono_class_init (field->parent);
1991 t = mono_field_get_type_checked (field, &error);
1992 if (!mono_error_ok (&error)) {
1993 mono_error_set_pending_exception (&error);
1997 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1998 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2002 if (image_is_dynamic (field->parent->image)) {
2003 MonoClass *klass = field->parent;
2004 int fidx = field - klass->fields;
2006 g_assert (fidx >= 0 && fidx < klass->field.count);
2007 g_assert (klass->ext);
2008 g_assert (klass->ext->field_def_values);
2009 def_type = klass->ext->field_def_values [fidx].def_type;
2010 def_value = klass->ext->field_def_values [fidx].data;
2011 if (def_type == MONO_TYPE_END) {
2012 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2016 def_value = mono_class_get_field_default_value (field, &def_type);
2017 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2019 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2024 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2028 case MONO_TYPE_BOOLEAN:
2031 case MONO_TYPE_CHAR:
2039 case MONO_TYPE_R8: {
2042 /* boxed value type */
2043 t = g_new0 (MonoType, 1);
2045 klass = mono_class_from_mono_type (t);
2047 o = mono_object_new_checked (domain, klass, &error);
2048 if (!mono_error_ok (&error)) {
2049 mono_error_set_pending_exception (&error);
2052 v = ((gchar *) o) + sizeof (MonoObject);
2053 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2056 case MONO_TYPE_STRING:
2057 case MONO_TYPE_CLASS:
2058 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2061 g_assert_not_reached ();
2067 ICALL_EXPORT MonoReflectionType*
2068 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2071 MonoReflectionType *ret;
2074 type = mono_field_get_type_checked (ref_field->field, &error);
2075 if (!mono_error_ok (&error)) {
2076 mono_error_set_pending_exception (&error);
2080 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2081 if (!mono_error_ok (&error)) {
2082 mono_error_set_pending_exception (&error);
2089 /* From MonoProperty.cs */
2091 PInfo_Attributes = 1,
2092 PInfo_GetMethod = 1 << 1,
2093 PInfo_SetMethod = 1 << 2,
2094 PInfo_ReflectedType = 1 << 3,
2095 PInfo_DeclaringType = 1 << 4,
2100 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2103 MonoReflectionType *rt;
2104 MonoReflectionMethod *rm;
2105 MonoDomain *domain = mono_object_domain (property);
2106 const MonoProperty *pproperty = property->property;
2108 if ((req_info & PInfo_ReflectedType) != 0) {
2109 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2110 mono_error_raise_exception (&error);
2112 MONO_STRUCT_SETREF (info, parent, rt);
2114 if ((req_info & PInfo_DeclaringType) != 0) {
2115 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2116 mono_error_raise_exception (&error);
2118 MONO_STRUCT_SETREF (info, declaring_type, rt);
2121 if ((req_info & PInfo_Name) != 0)
2122 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2124 if ((req_info & PInfo_Attributes) != 0)
2125 info->attrs = pproperty->attrs;
2127 if ((req_info & PInfo_GetMethod) != 0) {
2128 if (pproperty->get &&
2129 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2130 pproperty->get->klass == property->klass)) {
2131 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2132 mono_error_raise_exception (&error);
2137 MONO_STRUCT_SETREF (info, get, rm);
2139 if ((req_info & PInfo_SetMethod) != 0) {
2140 if (pproperty->set &&
2141 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2142 pproperty->set->klass == property->klass)) {
2143 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2144 mono_error_raise_exception (&error);
2149 MONO_STRUCT_SETREF (info, set, rm);
2152 * There may be other methods defined for properties, though, it seems they are not exposed
2153 * in the reflection API
2158 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2161 MonoReflectionType *rt;
2162 MonoReflectionMethod *rm;
2163 MonoDomain *domain = mono_object_domain (event);
2165 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2166 mono_error_raise_exception (&error);
2168 MONO_STRUCT_SETREF (info, reflected_type, rt);
2170 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2171 mono_error_raise_exception (&error);
2173 MONO_STRUCT_SETREF (info, declaring_type, rt);
2175 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2176 info->attrs = event->event->attrs;
2178 if (event->event->add) {
2179 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2180 mono_error_raise_exception (&error);
2185 MONO_STRUCT_SETREF (info, add_method, rm);
2187 if (event->event->remove) {
2188 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2189 mono_error_raise_exception (&error);
2194 MONO_STRUCT_SETREF (info, remove_method, rm);
2196 if (event->event->raise) {
2197 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2198 mono_error_raise_exception (&error);
2203 MONO_STRUCT_SETREF (info, raise_method, rm);
2205 #ifndef MONO_SMALL_CONFIG
2206 if (event->event->other) {
2208 while (event->event->other [n])
2210 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2212 for (i = 0; i < n; i++) {
2213 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2214 mono_error_raise_exception (&error);
2215 mono_array_setref (info->other_methods, i, rm);
2222 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2227 mono_class_setup_interfaces (klass, error);
2228 if (!mono_error_ok (error))
2231 for (i = 0; i < klass->interface_count; i++) {
2232 ic = klass->interfaces [i];
2233 g_hash_table_insert (ifaces, ic, ic);
2235 collect_interfaces (ic, ifaces, error);
2236 if (!mono_error_ok (error))
2242 MonoArray *iface_array;
2243 MonoGenericContext *context;
2247 } FillIfaceArrayData;
2250 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2252 MonoReflectionType *rt;
2253 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2254 MonoClass *ic = (MonoClass *)key;
2255 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2257 if (!mono_error_ok (data->error))
2260 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2261 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2262 if (!mono_error_ok (data->error))
2266 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2267 if (!mono_error_ok (data->error))
2270 mono_array_setref (data->iface_array, data->next_idx++, rt);
2273 mono_metadata_free_type (inflated);
2277 get_interfaces_hash (gconstpointer v1)
2279 MonoClass *k = (MonoClass*)v1;
2281 return k->type_token;
2284 ICALL_EXPORT MonoArray*
2285 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2288 MonoClass *klass = mono_class_from_mono_type (type->type);
2290 FillIfaceArrayData data = { 0 };
2293 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2295 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2296 data.context = mono_class_get_context (klass);
2297 klass = klass->generic_class->container_class;
2300 for (parent = klass; parent; parent = parent->parent) {
2301 mono_class_setup_interfaces (parent, &error);
2302 if (!mono_error_ok (&error))
2304 collect_interfaces (parent, iface_hash, &error);
2305 if (!mono_error_ok (&error))
2309 data.error = &error;
2310 data.domain = mono_object_domain (type);
2312 len = g_hash_table_size (iface_hash);
2314 g_hash_table_destroy (iface_hash);
2315 if (!data.domain->empty_types)
2316 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2317 return data.domain->empty_types;
2320 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2321 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2322 if (!mono_error_ok (&error))
2325 g_hash_table_destroy (iface_hash);
2326 return data.iface_array;
2329 g_hash_table_destroy (iface_hash);
2330 mono_error_set_pending_exception (&error);
2335 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2337 gboolean variance_used;
2338 MonoClass *klass = mono_class_from_mono_type (type->type);
2339 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2340 MonoReflectionMethod *member;
2343 int i = 0, len, ioffset;
2347 mono_class_init_checked (klass, &error);
2348 mono_error_raise_exception (&error);
2349 mono_class_init_checked (iclass, &error);
2350 mono_error_raise_exception (&error);
2352 mono_class_setup_vtable (klass);
2354 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2358 len = mono_class_num_methods (iclass);
2359 domain = mono_object_domain (type);
2360 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2361 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2363 while ((method = mono_class_get_methods (iclass, &iter))) {
2364 member = mono_method_get_object_checked (domain, method, iclass, &error);
2365 mono_error_raise_exception (&error);
2366 mono_array_setref (*methods, i, member);
2367 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2368 mono_error_raise_exception (&error);
2369 mono_array_setref (*targets, i, member);
2376 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2379 MonoClass *klass = mono_class_from_mono_type (type->type);
2381 mono_class_init_checked (klass, &error);
2382 mono_error_raise_exception (&error);
2384 if (image_is_dynamic (klass->image)) {
2385 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2386 *packing = tb->packing_size;
2387 *size = tb->class_size;
2389 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2393 ICALL_EXPORT MonoReflectionType*
2394 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2397 MonoReflectionType *ret;
2400 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2401 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2402 mono_error_raise_exception (&error);
2407 klass = mono_class_from_mono_type (type->type);
2408 mono_class_init_checked (klass, &error);
2409 mono_error_raise_exception (&error);
2411 // GetElementType should only return a type for:
2412 // Array Pointer PassedByRef
2413 if (type->type->byref)
2414 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2415 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2416 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2417 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2418 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2422 mono_error_raise_exception (&error);
2427 ICALL_EXPORT MonoReflectionType*
2428 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2431 MonoReflectionType *ret;
2433 if (type->type->byref)
2436 MonoClass *klass = mono_class_from_mono_type (type->type);
2440 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2441 mono_error_raise_exception (&error);
2446 ICALL_EXPORT MonoBoolean
2447 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2449 return type->type->type == MONO_TYPE_PTR;
2452 ICALL_EXPORT MonoBoolean
2453 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2455 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)));
2458 ICALL_EXPORT MonoBoolean
2459 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2461 return type->type->byref;
2464 ICALL_EXPORT MonoBoolean
2465 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2468 MonoClass *klass = mono_class_from_mono_type (type->type);
2469 mono_class_init_checked (klass, &error);
2470 mono_error_raise_exception (&error);
2472 return mono_class_is_com_object (klass);
2475 ICALL_EXPORT guint32
2476 ves_icall_RuntimeTypeHandle_GetMetadataToken (MonoReflectionType *obj)
2478 return mono_reflection_get_token ((MonoObject*)obj);
2481 ICALL_EXPORT MonoReflectionModule*
2482 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2485 MonoReflectionModule *result = NULL;
2486 MonoClass *klass = mono_class_from_mono_type (type->type);
2487 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2488 if (!mono_error_ok (&error))
2489 mono_error_set_pending_exception (&error);
2493 ICALL_EXPORT MonoReflectionAssembly*
2494 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2497 MonoDomain *domain = mono_domain_get ();
2498 MonoClass *klass = mono_class_from_mono_type (type->type);
2499 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2501 mono_error_set_pending_exception (&error);
2505 ICALL_EXPORT MonoReflectionType*
2506 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2509 MonoReflectionType *ret;
2510 MonoDomain *domain = mono_domain_get ();
2513 if (type->type->byref)
2515 if (type->type->type == MONO_TYPE_VAR) {
2516 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2517 klass = param ? param->owner.klass : NULL;
2518 } else if (type->type->type == MONO_TYPE_MVAR) {
2519 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2520 klass = param ? param->owner.method->klass : NULL;
2522 klass = mono_class_from_mono_type (type->type)->nested_in;
2528 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2529 mono_error_raise_exception (&error);
2534 ICALL_EXPORT MonoString*
2535 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2537 MonoDomain *domain = mono_domain_get ();
2538 MonoClass *klass = mono_class_from_mono_type (type->type);
2540 if (type->type->byref) {
2541 char *n = g_strdup_printf ("%s&", klass->name);
2542 MonoString *res = mono_string_new (domain, n);
2548 return mono_string_new (domain, klass->name);
2552 ICALL_EXPORT MonoString*
2553 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2555 MonoDomain *domain = mono_domain_get ();
2556 MonoClass *klass = mono_class_from_mono_type (type->type);
2558 while (klass->nested_in)
2559 klass = klass->nested_in;
2561 if (klass->name_space [0] == '\0')
2564 return mono_string_new (domain, klass->name_space);
2568 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2572 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2573 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2577 klass = mono_class_from_mono_type (type->type);
2583 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2586 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2590 ICALL_EXPORT MonoArray*
2591 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2594 MonoReflectionType *rt;
2596 MonoClass *klass, *pklass;
2597 MonoDomain *domain = mono_object_domain (type);
2600 klass = mono_class_from_mono_type (type->type);
2602 if (klass->generic_container) {
2603 MonoGenericContainer *container = klass->generic_container;
2604 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2605 for (i = 0; i < container->type_argc; ++i) {
2606 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2608 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2609 mono_error_raise_exception (&error);
2611 mono_array_setref (res, i, rt);
2613 } else if (klass->generic_class) {
2614 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2615 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2616 for (i = 0; i < inst->type_argc; ++i) {
2617 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2618 mono_error_raise_exception (&error);
2620 mono_array_setref (res, i, rt);
2628 ICALL_EXPORT gboolean
2629 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2633 if (!IS_MONOTYPE (type))
2636 if (type->type->byref)
2639 klass = mono_class_from_mono_type (type->type);
2640 return klass->generic_container != NULL;
2643 ICALL_EXPORT MonoReflectionType*
2644 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2647 MonoReflectionType *ret;
2650 if (type->type->byref)
2653 klass = mono_class_from_mono_type (type->type);
2655 if (klass->generic_container) {
2656 return type; /* check this one */
2658 if (klass->generic_class) {
2659 MonoClass *generic_class = klass->generic_class->container_class;
2662 tb = mono_class_get_ref_info (generic_class);
2664 if (generic_class->wastypebuilder && tb)
2665 return (MonoReflectionType *)tb;
2667 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2668 mono_error_raise_exception (&error);
2676 ICALL_EXPORT MonoReflectionType*
2677 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2680 MonoReflectionType *ret;
2682 MonoType *geninst, **types;
2685 g_assert (IS_MONOTYPE (type));
2686 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2687 mono_error_raise_exception (&error);
2689 count = mono_array_length (type_array);
2690 types = g_new0 (MonoType *, count);
2692 for (i = 0; i < count; i++) {
2693 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2694 types [i] = t->type;
2697 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2702 klass = mono_class_from_mono_type (geninst);
2704 /*we might inflate to the GTD*/
2705 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2706 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2710 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2711 mono_error_raise_exception (&error);
2716 ICALL_EXPORT gboolean
2717 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2721 if (!IS_MONOTYPE (type))
2724 if (type->type->byref)
2727 klass = mono_class_from_mono_type (type->type);
2728 return klass->generic_class != NULL || klass->generic_container != NULL;
2732 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2734 if (!IS_MONOTYPE (type))
2737 if (is_generic_parameter (type->type))
2738 return mono_type_get_generic_param_num (type->type);
2742 ICALL_EXPORT GenericParameterAttributes
2743 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2745 g_assert (IS_MONOTYPE (type));
2746 g_assert (is_generic_parameter (type->type));
2747 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2750 ICALL_EXPORT MonoArray *
2751 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2754 MonoReflectionType *rt;
2755 MonoGenericParamInfo *param_info;
2761 g_assert (IS_MONOTYPE (type));
2763 domain = mono_object_domain (type);
2764 param_info = mono_generic_param_info (type->type->data.generic_param);
2765 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2768 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2769 for (i = 0; i < count; i++) {
2770 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2771 mono_error_raise_exception (&error);
2773 mono_array_setref (res, i, rt);
2780 ICALL_EXPORT MonoBoolean
2781 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2783 return is_generic_parameter (type->type);
2786 ICALL_EXPORT MonoBoolean
2787 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2789 return is_generic_parameter (tb->type.type);
2793 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2794 MonoReflectionType *t)
2796 enumtype->type = t->type;
2799 ICALL_EXPORT MonoReflectionMethod*
2800 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2801 MonoReflectionMethod* generic)
2808 MonoReflectionMethod *ret = NULL;
2810 domain = ((MonoObject *)type)->vtable->domain;
2812 klass = mono_class_from_mono_type (type->type);
2813 mono_class_init_checked (klass, &error);
2814 mono_error_raise_exception (&error);
2817 while ((method = mono_class_get_methods (klass, &iter))) {
2818 if (method->token == generic->method->token) {
2819 ret = mono_method_get_object_checked (domain, method, klass, &error);
2820 mono_error_raise_exception (&error);
2827 ICALL_EXPORT MonoReflectionMethod *
2828 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2831 MonoType *type = ref_type->type;
2833 MonoReflectionMethod *ret = NULL;
2835 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2836 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2839 if (type->type == MONO_TYPE_VAR)
2842 method = mono_type_get_generic_param_owner (type)->owner.method;
2845 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2846 if (!mono_error_ok (&error))
2847 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2851 ICALL_EXPORT MonoBoolean
2852 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2854 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2858 ICALL_EXPORT MonoBoolean
2859 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2861 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2866 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2868 MonoDomain *domain = mono_domain_get ();
2869 MonoImage *image = method->method->klass->image;
2870 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2871 MonoTableInfo *tables = image->tables;
2872 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2873 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2874 guint32 im_cols [MONO_IMPLMAP_SIZE];
2875 guint32 scope_token;
2876 const char *import = NULL;
2877 const char *scope = NULL;
2879 if (image_is_dynamic (image)) {
2880 MonoReflectionMethodAux *method_aux =
2881 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2883 import = method_aux->dllentry;
2884 scope = method_aux->dll;
2887 if (!import || !scope) {
2888 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2893 if (piinfo->implmap_idx) {
2894 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2896 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2897 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2898 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2899 scope = mono_metadata_string_heap (image, scope_token);
2903 *flags = piinfo->piflags;
2904 *entry_point = mono_string_new (domain, import);
2905 *dll_name = mono_string_new (domain, scope);
2908 ICALL_EXPORT MonoReflectionMethod *
2909 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2911 MonoMethodInflated *imethod;
2913 MonoReflectionMethod *ret = NULL;
2916 if (method->method->is_generic)
2919 if (!method->method->is_inflated)
2922 imethod = (MonoMethodInflated *) method->method;
2924 result = imethod->declaring;
2925 /* Not a generic method. */
2926 if (!result->is_generic)
2929 if (image_is_dynamic (method->method->klass->image)) {
2930 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2931 MonoReflectionMethod *res;
2934 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2935 * the dynamic case as well ?
2937 mono_image_lock ((MonoImage*)image);
2938 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2939 mono_image_unlock ((MonoImage*)image);
2945 if (imethod->context.class_inst) {
2946 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2947 /*Generic methods gets the context of the GTD.*/
2948 if (mono_class_get_context (klass)) {
2949 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2950 if (!mono_error_ok (&error))
2955 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2957 if (!mono_error_ok (&error))
2958 mono_error_set_pending_exception (&error);
2962 ICALL_EXPORT gboolean
2963 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2965 return mono_method_signature (method->method)->generic_param_count != 0;
2968 ICALL_EXPORT gboolean
2969 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2971 return method->method->is_generic;
2974 ICALL_EXPORT MonoArray*
2975 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2978 MonoReflectionType *rt;
2983 domain = mono_object_domain (method);
2985 if (method->method->is_inflated) {
2986 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2989 count = inst->type_argc;
2990 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2992 for (i = 0; i < count; i++) {
2993 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2994 mono_error_raise_exception (&error);
2996 mono_array_setref (res, i, rt);
3003 count = mono_method_signature (method->method)->generic_param_count;
3004 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3006 for (i = 0; i < count; i++) {
3007 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3008 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3009 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3011 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3012 mono_error_raise_exception (&error);
3014 mono_array_setref (res, i, rt);
3020 ICALL_EXPORT MonoObject *
3021 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3025 * Invoke from reflection is supposed to always be a virtual call (the API
3026 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3027 * greater flexibility.
3029 MonoMethod *m = method->method;
3030 MonoMethodSignature *sig = mono_method_signature (m);
3033 void *obj = this_arg;
3037 if (mono_security_core_clr_enabled ())
3038 mono_security_core_clr_ensure_reflection_access_method (m);
3040 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3041 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3042 mono_error_cleanup (&error); /* FIXME does this make sense? */
3043 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3048 if (!mono_object_isinst (this_arg, m->klass)) {
3049 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3050 char *target_name = mono_type_get_full_name (m->klass);
3051 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3052 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3054 g_free (target_name);
3058 m = mono_object_get_virtual_method (this_arg, m);
3059 /* must pass the pointer to the value for valuetype methods */
3060 if (m->klass->valuetype)
3061 obj = mono_object_unbox (this_arg);
3062 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3063 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3068 if (sig->ret->byref) {
3069 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"));
3073 pcount = params? mono_array_length (params): 0;
3074 if (pcount != sig->param_count) {
3075 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3079 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3080 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."));
3084 image = m->klass->image;
3085 if (image->assembly->ref_only) {
3086 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."));
3090 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3091 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3095 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3099 intptr_t *lower_bounds;
3100 pcount = mono_array_length (params);
3101 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3102 /* Note: the synthetized array .ctors have int32 as argument type */
3103 for (i = 0; i < pcount; ++i)
3104 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3106 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3107 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3108 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3109 if (!mono_error_ok (&error)) {
3110 mono_error_set_pending_exception (&error);
3114 for (i = 0; i < mono_array_length (arr); ++i) {
3115 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3116 if (!mono_error_ok (&error)) {
3117 mono_error_set_pending_exception (&error);
3120 mono_array_setref_fast (arr, i, subarray);
3122 return (MonoObject*)arr;
3125 if (m->klass->rank == pcount) {
3126 /* Only lengths provided. */
3127 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3128 if (!mono_error_ok (&error)) {
3129 mono_error_set_pending_exception (&error);
3133 return (MonoObject*)arr;
3135 g_assert (pcount == (m->klass->rank * 2));
3136 /* The arguments are lower-bound-length pairs */
3137 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3139 for (i = 0; i < pcount / 2; ++i) {
3140 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3141 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3144 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3145 if (!mono_error_ok (&error)) {
3146 mono_error_set_pending_exception (&error);
3150 return (MonoObject*)arr;
3153 return mono_runtime_invoke_array (m, obj, params, NULL);
3156 #ifndef DISABLE_REMOTING
3157 ICALL_EXPORT MonoObject *
3158 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3160 MonoDomain *domain = mono_object_domain (method);
3161 MonoMethod *m = method->method;
3162 MonoMethodSignature *sig = mono_method_signature (m);
3163 MonoArray *out_args;
3165 int i, j, outarg_count = 0;
3167 if (m->klass == mono_defaults.object_class) {
3168 if (!strcmp (m->name, "FieldGetter")) {
3169 MonoClass *k = this_arg->vtable->klass;
3173 /* If this is a proxy, then it must be a CBO */
3174 if (k == mono_defaults.transparent_proxy_class) {
3175 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3176 this_arg = tp->rp->unwrapped_server;
3177 g_assert (this_arg);
3178 k = this_arg->vtable->klass;
3181 name = mono_array_get (params, MonoString *, 1);
3182 str = mono_string_to_utf8 (name);
3185 MonoClassField* field = mono_class_get_field_from_name (k, str);
3187 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3188 if (field_klass->valuetype)
3189 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3191 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3193 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3194 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3195 mono_array_setref (out_args, 0, result);
3203 g_assert_not_reached ();
3205 } else if (!strcmp (m->name, "FieldSetter")) {
3206 MonoClass *k = this_arg->vtable->klass;
3212 /* If this is a proxy, then it must be a CBO */
3213 if (k == mono_defaults.transparent_proxy_class) {
3214 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3215 this_arg = tp->rp->unwrapped_server;
3216 g_assert (this_arg);
3217 k = this_arg->vtable->klass;
3220 name = mono_array_get (params, MonoString *, 1);
3221 str = mono_string_to_utf8 (name);
3224 MonoClassField* field = mono_class_get_field_from_name (k, str);
3226 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3227 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3229 if (field_klass->valuetype) {
3230 size = mono_type_size (field->type, &align);
3231 g_assert (size == mono_class_value_size (field_klass, NULL));
3232 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3234 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3237 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3238 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3248 g_assert_not_reached ();
3253 for (i = 0; i < mono_array_length (params); i++) {
3254 if (sig->params [i]->byref)
3258 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3260 /* handle constructors only for objects already allocated */
3261 if (!strcmp (method->method->name, ".ctor"))
3262 g_assert (this_arg);
3264 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3265 g_assert (!method->method->klass->valuetype);
3266 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3268 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3269 if (sig->params [i]->byref) {
3271 arg = mono_array_get (params, gpointer, i);
3272 mono_array_setref (out_args, j, arg);
3277 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3284 read_enum_value (const char *mem, int type)
3287 case MONO_TYPE_BOOLEAN:
3289 return *(guint8*)mem;
3291 return *(gint8*)mem;
3292 case MONO_TYPE_CHAR:
3294 return read16 (mem);
3296 return (gint16) read16 (mem);
3298 return read32 (mem);
3300 return (gint32) read32 (mem);
3303 return read64 (mem);
3305 g_assert_not_reached ();
3311 write_enum_value (char *mem, int type, guint64 value)
3315 case MONO_TYPE_I1: {
3316 guint8 *p = (guint8*)mem;
3321 case MONO_TYPE_I2: {
3322 guint16 *p = (guint16 *)mem;
3327 case MONO_TYPE_I4: {
3328 guint32 *p = (guint32 *)mem;
3333 case MONO_TYPE_I8: {
3334 guint64 *p = (guint64 *)mem;
3339 g_assert_not_reached ();
3344 ICALL_EXPORT MonoObject *
3345 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3353 domain = mono_object_domain (enumType);
3354 enumc = mono_class_from_mono_type (enumType->type);
3356 mono_class_init_checked (enumc, &error);
3357 mono_error_raise_exception (&error);
3359 etype = mono_class_enum_basetype (enumc);
3361 res = mono_object_new_checked (domain, enumc, &error);
3362 mono_error_raise_exception (&error);
3363 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3368 ICALL_EXPORT MonoBoolean
3369 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3371 int size = mono_class_value_size (a->vtable->klass, NULL);
3372 guint64 a_val = 0, b_val = 0;
3374 memcpy (&a_val, mono_object_unbox (a), size);
3375 memcpy (&b_val, mono_object_unbox (b), size);
3377 return (a_val & b_val) == b_val;
3380 ICALL_EXPORT MonoObject *
3381 ves_icall_System_Enum_get_value (MonoObject *eobj)
3393 g_assert (eobj->vtable->klass->enumtype);
3395 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3396 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3397 mono_error_raise_exception (&error);
3398 dst = (char *)res + sizeof (MonoObject);
3399 src = (char *)eobj + sizeof (MonoObject);
3400 size = mono_class_value_size (enumc, NULL);
3402 memcpy (dst, src, size);
3407 ICALL_EXPORT MonoReflectionType *
3408 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3411 MonoReflectionType *ret;
3415 klass = mono_class_from_mono_type (type->type);
3416 mono_class_init_checked (klass, &error);
3417 mono_error_raise_exception (&error);
3419 etype = mono_class_enum_basetype (klass);
3421 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3425 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3426 mono_error_raise_exception (&error);
3432 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3434 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3435 gpointer odata = (char *)other + sizeof (MonoObject);
3436 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3437 g_assert (basetype);
3442 if (eobj->vtable->klass != other->vtable->klass)
3445 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3446 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3447 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3450 return me > other ? 1 : -1; \
3453 switch (basetype->type) {
3455 COMPARE_ENUM_VALUES (guint8);
3457 COMPARE_ENUM_VALUES (gint8);
3458 case MONO_TYPE_CHAR:
3460 COMPARE_ENUM_VALUES (guint16);
3462 COMPARE_ENUM_VALUES (gint16);
3464 COMPARE_ENUM_VALUES (guint32);
3466 COMPARE_ENUM_VALUES (gint32);
3468 COMPARE_ENUM_VALUES (guint64);
3470 COMPARE_ENUM_VALUES (gint64);
3474 #undef COMPARE_ENUM_VALUES
3475 /* indicates that the enum was of an unsupported unerlying type */
3480 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3482 gpointer data = (char *)eobj + sizeof (MonoObject);
3483 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3484 g_assert (basetype);
3486 switch (basetype->type) {
3487 case MONO_TYPE_I1: {
3488 gint8 value = *((gint8*)data);
3489 return ((int)value ^ (int)value << 8);
3492 return *((guint8*)data);
3493 case MONO_TYPE_CHAR:
3495 return *((guint16*)data);
3497 case MONO_TYPE_I2: {
3498 gint16 value = *((gint16*)data);
3499 return ((int)(guint16)value | (((int)value) << 16));
3502 return *((guint32*)data);
3504 return *((gint32*)data);
3506 case MONO_TYPE_I8: {
3507 gint64 value = *((gint64*)data);
3508 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3511 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3516 ICALL_EXPORT MonoBoolean
3517 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3520 MonoDomain *domain = mono_object_domain (type);
3521 MonoClass *enumc = mono_class_from_mono_type (type->type);
3522 guint j = 0, nvalues;
3524 MonoClassField *field;
3526 guint64 field_value, previous_value = 0;
3527 gboolean sorted = TRUE;
3529 mono_class_init_checked (enumc, &error);
3530 mono_error_raise_exception (&error);
3532 if (!enumc->enumtype) {
3533 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3537 base_type = mono_class_enum_basetype (enumc)->type;
3539 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3540 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3541 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3544 while ((field = mono_class_get_fields (enumc, &iter))) {
3546 MonoTypeEnum def_type;
3548 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3550 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3552 if (mono_field_is_deleted (field))
3554 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3556 p = mono_class_get_field_default_value (field, &def_type);
3557 /* len = */ mono_metadata_decode_blob_size (p, &p);
3559 field_value = read_enum_value (p, base_type);
3560 mono_array_set (*values, guint64, j, field_value);
3562 if (previous_value > field_value)
3565 previous_value = field_value;
3573 BFLAGS_IgnoreCase = 1,
3574 BFLAGS_DeclaredOnly = 2,
3575 BFLAGS_Instance = 4,
3577 BFLAGS_Public = 0x10,
3578 BFLAGS_NonPublic = 0x20,
3579 BFLAGS_FlattenHierarchy = 0x40,
3580 BFLAGS_InvokeMethod = 0x100,
3581 BFLAGS_CreateInstance = 0x200,
3582 BFLAGS_GetField = 0x400,
3583 BFLAGS_SetField = 0x800,
3584 BFLAGS_GetProperty = 0x1000,
3585 BFLAGS_SetProperty = 0x2000,
3586 BFLAGS_ExactBinding = 0x10000,
3587 BFLAGS_SuppressChangeType = 0x20000,
3588 BFLAGS_OptionalParamBinding = 0x40000
3591 ICALL_EXPORT MonoArray*
3592 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3596 MonoClass *startklass, *klass, *refklass;
3601 char *utf8_name = NULL;
3602 int (*compare_func) (const char *s1, const char *s2) = NULL;
3603 MonoClassField *field;
3604 MonoPtrArray tmp_array;
3606 domain = ((MonoObject *)type)->vtable->domain;
3607 if (type->type->byref)
3608 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3610 klass = startklass = mono_class_from_mono_type (type->type);
3611 refklass = mono_class_from_mono_type (reftype->type);
3613 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3616 if (mono_class_has_failure (klass)) {
3617 mono_ptr_array_destroy (tmp_array);
3618 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3623 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3624 guint32 flags = mono_field_get_flags (field);
3626 if (mono_field_is_deleted_with_flags (field, flags))
3628 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3629 if (bflags & BFLAGS_Public)
3631 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3632 if (bflags & BFLAGS_NonPublic) {
3639 if (flags & FIELD_ATTRIBUTE_STATIC) {
3640 if (bflags & BFLAGS_Static)
3641 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3644 if (bflags & BFLAGS_Instance)
3652 if (utf8_name == NULL) {
3653 utf8_name = mono_string_to_utf8 (name);
3654 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3657 if (compare_func (mono_field_get_name (field), utf8_name))
3661 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3662 if (!mono_error_ok (&error))
3664 mono_ptr_array_append (tmp_array, member);
3666 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3669 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3671 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3672 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3674 mono_ptr_array_destroy (tmp_array);
3676 if (utf8_name != NULL)
3681 mono_ptr_array_destroy (tmp_array);
3682 mono_error_raise_exception (&error);
3683 g_assert_not_reached ();
3687 method_nonpublic (MonoMethod* method, gboolean start_klass)
3689 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3690 case METHOD_ATTRIBUTE_ASSEM:
3691 return (start_klass || mono_defaults.generic_ilist_class);
3692 case METHOD_ATTRIBUTE_PRIVATE:
3694 case METHOD_ATTRIBUTE_PUBLIC:
3702 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3705 MonoClass *startklass;
3709 /*FIXME, use MonoBitSet*/
3710 guint32 method_slots_default [8];
3711 guint32 *method_slots = NULL;
3712 int (*compare_func) (const char *s1, const char *s2) = NULL;
3714 array = g_ptr_array_new ();
3719 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3721 /* An optimization for calls made from Delegate:CreateDelegate () */
3722 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3723 method = mono_get_delegate_invoke (klass);
3724 if (mono_loader_get_last_error ())
3727 g_ptr_array_add (array, method);
3731 mono_class_setup_methods (klass);
3732 mono_class_setup_vtable (klass);
3733 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3736 if (is_generic_parameter (&klass->byval_arg))
3737 nslots = mono_class_get_vtable_size (klass->parent);
3739 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3740 if (nslots >= sizeof (method_slots_default) * 8) {
3741 method_slots = g_new0 (guint32, nslots / 32 + 1);
3743 method_slots = method_slots_default;
3744 memset (method_slots, 0, sizeof (method_slots_default));
3747 mono_class_setup_methods (klass);
3748 mono_class_setup_vtable (klass);
3749 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3753 while ((method = mono_class_get_methods (klass, &iter))) {
3755 if (method->slot != -1) {
3756 g_assert (method->slot < nslots);
3757 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3759 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3760 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3763 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3765 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3766 if (bflags & BFLAGS_Public)
3768 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3774 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3775 if (bflags & BFLAGS_Static)
3776 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3779 if (bflags & BFLAGS_Instance)
3787 if (compare_func (name, method->name))
3792 g_ptr_array_add (array, method);
3794 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3796 if (method_slots != method_slots_default)
3797 g_free (method_slots);
3802 if (method_slots != method_slots_default)
3803 g_free (method_slots);
3804 g_ptr_array_free (array, TRUE);
3806 if (mono_class_has_failure (klass)) {
3807 *ex = mono_class_get_exception_for_failure (klass);
3809 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3810 mono_loader_clear_error ();
3815 ICALL_EXPORT MonoArray*
3816 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3818 static MonoClass *MethodInfo_array;
3822 MonoVTable *array_vtable;
3823 MonoException *ex = NULL;
3824 const char *mname = NULL;
3825 GPtrArray *method_array;
3826 MonoClass *klass, *refklass;
3829 mono_error_init (&error);
3831 if (!MethodInfo_array) {
3832 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3833 mono_memory_barrier ();
3834 MethodInfo_array = klass;
3837 klass = mono_class_from_mono_type (type->type);
3838 refklass = mono_class_from_mono_type (reftype->type);
3839 domain = ((MonoObject *)type)->vtable->domain;
3840 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3841 if (!is_ok (&error)) {
3842 mono_error_set_pending_exception (&error);
3845 if (type->type->byref) {
3846 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3847 mono_error_set_pending_exception (&error);
3853 mname = mono_string_to_utf8 (name);
3855 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3856 g_free ((char*)mname);
3858 mono_set_pending_exception (ex);
3862 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3863 if (!mono_error_ok (&error)) {
3864 mono_error_set_pending_exception (&error);
3868 for (i = 0; i < method_array->len; ++i) {
3869 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3870 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3871 if (!mono_error_ok (&error))
3873 mono_array_setref (res, i, rm);
3877 g_ptr_array_free (method_array, TRUE);
3878 if (!mono_error_ok (&error))
3879 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3883 ICALL_EXPORT MonoArray*
3884 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3887 MonoClass *startklass, *klass, *refklass;
3892 gpointer iter = NULL;
3893 MonoPtrArray tmp_array;
3896 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3898 domain = ((MonoObject *)type)->vtable->domain;
3899 if (type->type->byref)
3900 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3901 klass = startklass = mono_class_from_mono_type (type->type);
3902 refklass = mono_class_from_mono_type (reftype->type);
3904 mono_class_setup_methods (klass);
3905 if (mono_class_has_failure (klass)) {
3906 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3911 while ((method = mono_class_get_methods (klass, &iter))) {
3913 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3915 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3916 if (bflags & BFLAGS_Public)
3919 if (bflags & BFLAGS_NonPublic)
3925 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3926 if (bflags & BFLAGS_Static)
3927 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3930 if (bflags & BFLAGS_Instance)
3936 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3937 if (!mono_error_ok (&error)) {
3938 mono_error_set_pending_exception (&error);
3942 mono_ptr_array_append (tmp_array, member);
3945 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3947 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3948 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3950 mono_ptr_array_destroy (tmp_array);
3956 property_hash (gconstpointer data)
3958 MonoProperty *prop = (MonoProperty*)data;
3960 return g_str_hash (prop->name);
3964 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3966 if (method1->is_inflated)
3967 method1 = ((MonoMethodInflated*) method1)->declaring;
3968 if (method2->is_inflated)
3969 method2 = ((MonoMethodInflated*) method2)->declaring;
3971 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3975 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3977 // Properties are hide-by-name-and-signature
3978 if (!g_str_equal (prop1->name, prop2->name))
3981 /* If we see a property in a generic method, we want to
3982 compare the generic signatures, not the inflated signatures
3983 because we might conflate two properties that were
3987 public T this[T t] { getter { return t; } } // method 1
3988 public U this[U u] { getter { return u; } } // method 2
3991 If we see int Foo<int,int>::Item[int] we need to know if
3992 the indexer came from method 1 or from method 2, and we
3993 shouldn't conflate them. (Bugzilla 36283)
3995 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3998 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4005 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4010 return method_nonpublic (accessor, start_klass);
4013 ICALL_EXPORT MonoArray*
4014 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4018 MonoClass *startklass, *klass;
4024 gchar *propname = NULL;
4025 int (*compare_func) (const char *s1, const char *s2) = NULL;
4027 GHashTable *properties = NULL;
4028 MonoPtrArray tmp_array;
4030 mono_error_init (&error);
4032 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4034 domain = ((MonoObject *)type)->vtable->domain;
4035 if (type->type->byref)
4036 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4037 klass = startklass = mono_class_from_mono_type (type->type);
4040 propname = mono_string_to_utf8 (name);
4041 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4044 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4046 mono_class_setup_methods (klass);
4047 mono_class_setup_vtable (klass);
4048 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4052 while ((prop = mono_class_get_properties (klass, &iter))) {
4058 flags = method->flags;
4061 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4062 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4063 if (bflags & BFLAGS_Public)
4065 } else if (bflags & BFLAGS_NonPublic) {
4066 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4067 property_accessor_nonpublic(prop->set, startklass == klass)) {
4074 if (flags & METHOD_ATTRIBUTE_STATIC) {
4075 if (bflags & BFLAGS_Static)
4076 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4079 if (bflags & BFLAGS_Instance)
4088 if (compare_func (propname, prop->name))
4092 if (g_hash_table_lookup (properties, prop))
4095 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4098 mono_ptr_array_append (tmp_array, pr);
4100 g_hash_table_insert (properties, prop, prop);
4102 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4105 g_hash_table_destroy (properties);
4108 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4109 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4110 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4112 mono_ptr_array_destroy (tmp_array);
4119 if (mono_class_has_failure (klass)) {
4120 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4122 mono_error_set_from_loader_error (&error);
4123 mono_loader_clear_error ();
4128 g_hash_table_destroy (properties);
4131 mono_ptr_array_destroy (tmp_array);
4133 mono_error_set_pending_exception (&error);
4139 event_hash (gconstpointer data)
4141 MonoEvent *event = (MonoEvent*)data;
4143 return g_str_hash (event->name);
4147 event_equal (MonoEvent *event1, MonoEvent *event2)
4149 // Events are hide-by-name
4150 return g_str_equal (event1->name, event2->name);
4153 ICALL_EXPORT MonoArray*
4154 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4158 MonoClass *startklass, *klass;
4164 char *utf8_name = NULL;
4165 int (*compare_func) (const char *s1, const char *s2) = NULL;
4166 GHashTable *events = NULL;
4167 MonoPtrArray tmp_array;
4169 mono_error_init (&error);
4171 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4173 domain = mono_object_domain (type);
4174 if (type->type->byref)
4175 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4176 klass = startklass = mono_class_from_mono_type (type->type);
4178 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4180 mono_class_setup_methods (klass);
4181 mono_class_setup_vtable (klass);
4182 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4186 while ((event = mono_class_get_events (klass, &iter))) {
4188 method = event->add;
4190 method = event->remove;
4192 method = event->raise;
4194 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4195 if (bflags & BFLAGS_Public)
4197 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4198 if (bflags & BFLAGS_NonPublic)
4203 if (bflags & BFLAGS_NonPublic)
4209 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4210 if (bflags & BFLAGS_Static)
4211 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4214 if (bflags & BFLAGS_Instance)
4219 if (bflags & BFLAGS_Instance)
4225 if (utf8_name == NULL) {
4226 utf8_name = mono_string_to_utf8 (name);
4227 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4230 if (compare_func (event->name, utf8_name))
4234 if (g_hash_table_lookup (events, event))
4237 MonoReflectionEvent *ev_obj;
4238 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4241 mono_ptr_array_append (tmp_array, ev_obj);
4243 g_hash_table_insert (events, event, event);
4245 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4248 g_hash_table_destroy (events);
4250 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4252 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4253 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4255 mono_ptr_array_destroy (tmp_array);
4257 if (utf8_name != NULL)
4263 if (mono_class_has_failure (klass)) {
4264 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4266 mono_error_set_from_loader_error (&error);
4267 mono_loader_clear_error ();
4273 g_hash_table_destroy (events);
4274 if (utf8_name != NULL)
4277 mono_ptr_array_destroy (tmp_array);
4279 mono_error_set_pending_exception (&error);
4283 ICALL_EXPORT MonoArray*
4284 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4287 MonoReflectionType *rt;
4295 MonoPtrArray tmp_array;
4297 domain = ((MonoObject *)type)->vtable->domain;
4298 if (type->type->byref)
4299 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4300 klass = mono_class_from_mono_type (type->type);
4303 * If a nested type is generic, return its generic type definition.
4304 * Note that this means that the return value is essentially the set
4305 * of nested types of the generic type definition of @klass.
4307 * A note in MSDN claims that a generic type definition can have
4308 * nested types that aren't generic. In any case, the container of that
4309 * nested type would be the generic type definition.
4311 if (klass->generic_class)
4312 klass = klass->generic_class->container_class;
4314 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4316 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4318 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4319 if (bflags & BFLAGS_Public)
4322 if (bflags & BFLAGS_NonPublic)
4330 str = mono_string_to_utf8 (name);
4331 mono_identifier_unescape_type_name_chars (str);
4334 if (strcmp (nested->name, str))
4338 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4339 mono_error_raise_exception (&error);
4341 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4344 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4346 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4347 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4349 mono_ptr_array_destroy (tmp_array);
4357 ICALL_EXPORT MonoReflectionType*
4358 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4361 MonoReflectionType *ret;
4363 MonoType *type = NULL;
4364 MonoTypeNameParse info;
4365 gboolean type_resolve;
4367 /* On MS.NET, this does not fire a TypeResolve event */
4368 type_resolve = TRUE;
4369 str = mono_string_to_utf8 (name);
4370 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4371 if (!mono_reflection_parse_type (str, &info)) {
4373 mono_reflection_free_type_info (&info);
4375 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4378 /*g_print ("failed parse\n");*/
4382 if (info.assembly.name) {
4384 mono_reflection_free_type_info (&info);
4386 /* 1.0 and 2.0 throw different exceptions */
4387 if (mono_defaults.generic_ilist_class)
4388 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4390 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4396 if (module != NULL) {
4398 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4403 if (assembly_is_dynamic (assembly->assembly)) {
4404 /* Enumerate all modules */
4405 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4409 if (abuilder->modules) {
4410 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4411 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4412 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4418 if (!type && abuilder->loaded_modules) {
4419 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4420 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4421 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4428 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4430 mono_reflection_free_type_info (&info);
4432 MonoException *e = NULL;
4435 e = mono_get_exception_type_load (name, NULL);
4437 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4438 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4440 mono_loader_clear_error ();
4443 mono_set_pending_exception (e);
4445 } else if (mono_loader_get_last_error ()) {
4447 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4450 mono_loader_clear_error ();
4453 if (type->type == MONO_TYPE_CLASS) {
4454 MonoClass *klass = mono_type_get_class (type);
4456 /* need to report exceptions ? */
4457 if (throwOnError && mono_class_has_failure (klass)) {
4458 /* report SecurityException (or others) that occured when loading the assembly */
4459 MonoException *exc = mono_class_get_exception_for_failure (klass);
4460 mono_loader_clear_error ();
4461 mono_set_pending_exception (exc);
4466 /* g_print ("got it\n"); */
4467 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4468 mono_error_raise_exception (&error);
4474 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4477 gchar *shadow_ini_file;
4480 /* Check for shadow-copied assembly */
4481 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4482 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4484 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4485 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4491 g_free (shadow_ini_file);
4492 if (content != NULL) {
4495 *filename = content;
4502 ICALL_EXPORT MonoString *
4503 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4505 MonoDomain *domain = mono_object_domain (assembly);
4506 MonoAssembly *mass = assembly->assembly;
4507 MonoString *res = NULL;
4512 if (g_path_is_absolute (mass->image->name)) {
4513 absolute = g_strdup (mass->image->name);
4514 dirname = g_path_get_dirname (absolute);
4516 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4517 dirname = g_strdup (mass->basedir);
4520 replace_shadow_path (domain, dirname, &absolute);
4525 for (i = strlen (absolute) - 1; i >= 0; i--)
4526 if (absolute [i] == '\\')
4531 uri = g_filename_to_uri (absolute, NULL, NULL);
4533 const char *prepend = "file://";
4535 if (*absolute == '/' && *(absolute + 1) == '/') {
4538 prepend = "file:///";
4541 uri = g_strconcat (prepend, absolute, NULL);
4545 res = mono_string_new (domain, uri);
4552 ICALL_EXPORT MonoBoolean
4553 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4555 MonoAssembly *mass = assembly->assembly;
4557 return mass->in_gac;
4560 ICALL_EXPORT MonoReflectionAssembly*
4561 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4566 MonoImageOpenStatus status;
4567 MonoReflectionAssembly* result = NULL;
4569 name = mono_string_to_utf8 (mname);
4570 res = mono_assembly_load_with_partial_name (name, &status);
4576 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4578 mono_error_set_pending_exception (&error);
4582 ICALL_EXPORT MonoString *
4583 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4585 MonoDomain *domain = mono_object_domain (assembly);
4588 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4593 ICALL_EXPORT MonoBoolean
4594 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4596 return assembly->assembly->ref_only;
4599 ICALL_EXPORT MonoString *
4600 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4602 MonoDomain *domain = mono_object_domain (assembly);
4604 return mono_string_new (domain, assembly->assembly->image->version);
4607 ICALL_EXPORT MonoReflectionMethod*
4608 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4611 MonoReflectionMethod *res = NULL;
4614 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4618 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4619 if (!mono_error_ok (&error))
4622 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4625 if (!mono_error_ok (&error))
4626 mono_error_set_pending_exception (&error);
4630 ICALL_EXPORT MonoReflectionModule*
4631 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4634 MonoReflectionModule *result = NULL;
4635 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4636 if (!mono_error_ok (&error))
4637 mono_error_set_pending_exception (&error);
4641 ICALL_EXPORT MonoArray*
4642 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4644 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4645 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4649 for (i = 0; i < table->rows; ++i) {
4650 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4651 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4657 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4659 static MonoMethod *create_version = NULL;
4663 mono_error_init (error);
4666 if (!create_version) {
4667 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4668 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4669 g_assert (create_version);
4670 mono_method_desc_free (desc);
4676 args [3] = &revision;
4677 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4678 return_val_if_nok (error, NULL);
4680 mono_runtime_invoke_checked (create_version, result, args, error);
4681 return_val_if_nok (error, NULL);
4686 ICALL_EXPORT MonoArray*
4687 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4691 MonoDomain *domain = mono_object_domain (assembly);
4693 static MonoMethod *create_culture = NULL;
4694 MonoImage *image = assembly->assembly->image;
4698 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4701 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4703 if (count > 0 && !create_culture) {
4704 MonoMethodDesc *desc = mono_method_desc_new (
4705 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4706 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4707 g_assert (create_culture);
4708 mono_method_desc_free (desc);
4711 for (i = 0; i < count; i++) {
4712 MonoObject *version;
4713 MonoReflectionAssemblyName *aname;
4714 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4716 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4718 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4719 domain, mono_class_get_assembly_name_class (), &error);
4720 mono_error_raise_exception (&error);
4722 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4724 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4725 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4726 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4727 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4728 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4729 aname->versioncompat = 1; /* SameMachine (default) */
4730 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4732 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4733 mono_error_raise_exception (&error);
4735 MONO_OBJECT_SETREF (aname, version, version);
4737 if (create_culture) {
4739 MonoBoolean assembly_ref = 1;
4740 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4741 args [1] = &assembly_ref;
4743 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4744 mono_error_raise_exception (&error);
4746 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4749 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4750 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4751 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4753 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4754 /* public key token isn't copied - the class library will
4755 automatically generate it from the public key if required */
4756 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4757 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4759 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4760 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4763 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4766 /* note: this function doesn't return the codebase on purpose (i.e. it can
4767 be used under partial trust as path information isn't present). */
4769 mono_array_setref (result, i, aname);
4774 /* move this in some file in mono/util/ */
4776 g_concat_dir_and_file (const char *dir, const char *file)
4778 g_return_val_if_fail (dir != NULL, NULL);
4779 g_return_val_if_fail (file != NULL, NULL);
4782 * If the directory name doesn't have a / on the end, we need
4783 * to add one so we get a proper path to the file
4785 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4786 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4788 return g_strconcat (dir, file, NULL);
4792 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4795 char *n = mono_string_to_utf8 (name);
4796 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4798 guint32 cols [MONO_MANIFEST_SIZE];
4799 guint32 impl, file_idx;
4803 for (i = 0; i < table->rows; ++i) {
4804 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4805 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4806 if (strcmp (val, n) == 0)
4810 if (i == table->rows)
4813 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4816 * this code should only be called after obtaining the
4817 * ResourceInfo and handling the other cases.
4819 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4820 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4822 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4827 module = assembly->assembly->image;
4830 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4831 mono_error_raise_exception (&error);
4832 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4834 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4837 ICALL_EXPORT gboolean
4838 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4841 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4843 guint32 cols [MONO_MANIFEST_SIZE];
4844 guint32 file_cols [MONO_FILE_SIZE];
4848 n = mono_string_to_utf8 (name);
4849 for (i = 0; i < table->rows; ++i) {
4850 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4851 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4852 if (strcmp (val, n) == 0)
4856 if (i == table->rows)
4859 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4860 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4863 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4864 case MONO_IMPLEMENTATION_FILE:
4865 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4866 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4867 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4868 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4869 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4870 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4873 info->location = RESOURCE_LOCATION_EMBEDDED;
4876 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4877 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4878 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4879 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4880 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4881 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4883 mono_set_pending_exception (ex);
4886 MonoReflectionAssembly *assm_obj;
4887 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4889 mono_error_set_pending_exception (&error);
4892 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4894 /* Obtain info recursively */
4895 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4896 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4899 case MONO_IMPLEMENTATION_EXP_TYPE:
4900 g_assert_not_reached ();
4908 ICALL_EXPORT MonoObject*
4909 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4911 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4912 MonoArray *result = NULL;
4917 /* check hash if needed */
4919 n = mono_string_to_utf8 (name);
4920 for (i = 0; i < table->rows; ++i) {
4921 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4922 if (strcmp (val, n) == 0) {
4925 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4926 fn = mono_string_new (mono_object_domain (assembly), n);
4928 return (MonoObject*)fn;
4936 for (i = 0; i < table->rows; ++i) {
4937 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4941 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4944 for (i = 0; i < table->rows; ++i) {
4945 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4946 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4947 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4948 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4953 return (MonoObject*)result;
4956 ICALL_EXPORT MonoArray*
4957 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4960 MonoDomain *domain = mono_domain_get();
4963 int i, j, file_count = 0;
4964 MonoImage **modules;
4965 guint32 module_count, real_module_count;
4966 MonoTableInfo *table;
4967 guint32 cols [MONO_FILE_SIZE];
4968 MonoImage *image = assembly->assembly->image;
4970 g_assert (image != NULL);
4971 g_assert (!assembly_is_dynamic (assembly->assembly));
4973 table = &image->tables [MONO_TABLE_FILE];
4974 file_count = table->rows;
4976 modules = image->modules;
4977 module_count = image->module_count;
4979 real_module_count = 0;
4980 for (i = 0; i < module_count; ++i)
4982 real_module_count ++;
4984 klass = mono_class_get_module_class ();
4985 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4987 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
4988 mono_error_raise_exception (&error);
4989 mono_array_setref (res, 0, image_obj);
4991 for (i = 0; i < module_count; ++i)
4993 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
4994 mono_error_raise_exception (&error);
4995 mono_array_setref (res, j, rm);
4999 for (i = 0; i < file_count; ++i, ++j) {
5000 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5001 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5002 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5003 mono_error_raise_exception (&error);
5004 mono_array_setref (res, j, rm);
5007 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5009 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5010 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5013 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5014 mono_error_raise_exception (&error);
5015 mono_array_setref (res, j, rm);
5022 ICALL_EXPORT MonoReflectionMethod*
5023 ves_icall_GetCurrentMethod (void)
5025 MonoReflectionMethod *res = NULL;
5028 MonoMethod *m = mono_method_get_last_managed ();
5031 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5035 while (m->is_inflated)
5036 m = ((MonoMethodInflated*)m)->declaring;
5038 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5039 mono_error_raise_exception (&error);
5045 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5048 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5051 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5052 //method is inflated, we should inflate it on the other class
5053 MonoGenericContext ctx;
5054 ctx.method_inst = inflated->context.method_inst;
5055 ctx.class_inst = inflated->context.class_inst;
5056 if (klass->generic_class)
5057 ctx.class_inst = klass->generic_class->context.class_inst;
5058 else if (klass->generic_container)
5059 ctx.class_inst = klass->generic_container->context.class_inst;
5060 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5061 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5065 mono_class_setup_methods (method->klass);
5066 if (mono_class_has_failure (method->klass))
5068 for (i = 0; i < method->klass->method.count; ++i) {
5069 if (method->klass->methods [i] == method) {
5074 mono_class_setup_methods (klass);
5075 if (mono_class_has_failure (klass))
5077 g_assert (offset >= 0 && offset < klass->method.count);
5078 return klass->methods [offset];
5081 ICALL_EXPORT MonoReflectionMethod*
5082 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5084 MonoReflectionMethod *res = NULL;
5088 klass = mono_class_from_mono_type (type);
5089 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5091 if (method->klass != klass) {
5092 method = mono_method_get_equivalent_method (method, klass);
5097 klass = method->klass;
5098 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5099 mono_error_raise_exception (&error);
5103 ICALL_EXPORT MonoReflectionMethodBody*
5104 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5107 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5108 mono_error_set_pending_exception (&error);
5112 ICALL_EXPORT MonoReflectionAssembly*
5113 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5116 MonoReflectionAssembly *result;
5117 MonoMethod *dest = NULL;
5119 mono_stack_walk_no_il (get_executing, &dest);
5121 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5123 mono_error_set_pending_exception (&error);
5128 ICALL_EXPORT MonoReflectionAssembly*
5129 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5132 MonoReflectionAssembly *result;
5133 MonoDomain* domain = mono_domain_get ();
5135 if (!domain->entry_assembly)
5138 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5140 mono_error_set_pending_exception (&error);
5144 ICALL_EXPORT MonoReflectionAssembly*
5145 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5150 MonoReflectionAssembly *result;
5153 mono_stack_walk_no_il (get_executing, &dest);
5155 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5159 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5162 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5164 mono_error_set_pending_exception (&error);
5168 ICALL_EXPORT MonoString *
5169 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5170 gboolean assembly_qualified)
5172 MonoDomain *domain = mono_object_domain (object);
5173 MonoTypeNameFormat format;
5178 format = assembly_qualified ?
5179 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5180 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5182 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5184 name = mono_type_get_name_full (object->type, format);
5188 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5193 res = mono_string_new (domain, name);
5200 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5203 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5205 mono_class_init_checked (klass, &error);
5206 mono_error_raise_exception (&error);
5207 return mono_security_core_clr_class_level (klass);
5211 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5213 MonoClassField *field = rfield->field;
5214 return mono_security_core_clr_field_level (field, TRUE);
5218 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5220 MonoMethod *method = rfield->method;
5221 return mono_security_core_clr_method_level (method, TRUE);
5225 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)
5227 static MonoMethod *create_culture = NULL;
5231 const char *pkey_ptr;
5233 MonoBoolean assembly_ref = 0;
5235 mono_error_init (error);
5237 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5238 aname->major = name->major;
5239 aname->minor = name->minor;
5240 aname->build = name->build;
5241 aname->flags = name->flags;
5242 aname->revision = name->revision;
5243 aname->hashalg = name->hash_alg;
5244 aname->versioncompat = 1; /* SameMachine (default) */
5245 aname->processor_architecture = name->arch;
5247 if (by_default_version) {
5248 MonoObject *version;
5250 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5251 return_if_nok (error);
5253 MONO_OBJECT_SETREF (aname, version, version);
5257 if (absolute != NULL && *absolute != '\0') {
5258 const gchar *prepend = "file://";
5261 codebase = g_strdup (absolute);
5266 for (i = strlen (codebase) - 1; i >= 0; i--)
5267 if (codebase [i] == '\\')
5270 if (*codebase == '/' && *(codebase + 1) == '/') {
5273 prepend = "file:///";
5277 result = g_strconcat (prepend, codebase, NULL);
5283 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5287 if (!create_culture) {
5288 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5289 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5290 g_assert (create_culture);
5291 mono_method_desc_free (desc);
5294 if (name->culture) {
5295 args [0] = mono_string_new (domain, name->culture);
5296 args [1] = &assembly_ref;
5298 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5299 return_if_nok (error);
5301 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5304 if (name->public_key) {
5305 pkey_ptr = (char*)name->public_key;
5306 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5308 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5309 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5310 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5311 } else if (default_publickey) {
5312 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5313 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5316 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5317 if (name->public_key_token [0]) {
5321 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5322 p = mono_array_addr (aname->keyToken, char, 0);
5324 for (i = 0, j = 0; i < 8; i++) {
5325 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5326 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5329 } else if (default_token) {
5330 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5334 ICALL_EXPORT MonoString *
5335 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5337 MonoDomain *domain = mono_object_domain (assembly);
5338 MonoAssembly *mass = assembly->assembly;
5342 name = mono_stringify_assembly_name (&mass->aname);
5343 res = mono_string_new (domain, name);
5350 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5354 MonoAssembly *mass = assembly->assembly;
5356 if (g_path_is_absolute (mass->image->name)) {
5357 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5358 mono_error_set_pending_exception (&error);
5361 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5363 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5364 mono_error_set_pending_exception (&error);
5370 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5374 MonoImageOpenStatus status = MONO_IMAGE_OK;
5377 MonoAssemblyName name;
5380 filename = mono_string_to_utf8 (fname);
5382 dirname = g_path_get_dirname (filename);
5383 replace_shadow_path (mono_domain_get (), dirname, &filename);
5386 image = mono_image_open (filename, &status);
5392 if (status == MONO_IMAGE_IMAGE_INVALID)
5393 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5395 exc = mono_get_exception_file_not_found2 (NULL, fname);
5396 mono_set_pending_exception (exc);
5400 res = mono_assembly_fill_assembly_name (image, &name);
5402 mono_image_close (image);
5404 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5408 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5409 mono_error_set_pending_exception (&error);
5411 mono_image_close (image);
5415 ICALL_EXPORT MonoBoolean
5416 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5417 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5419 MonoBoolean result = FALSE;
5420 MonoDeclSecurityEntry entry;
5422 /* SecurityAction.RequestMinimum */
5423 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5424 *minimum = entry.blob;
5425 *minLength = entry.size;
5428 /* SecurityAction.RequestOptional */
5429 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5430 *optional = entry.blob;
5431 *optLength = entry.size;
5434 /* SecurityAction.RequestRefuse */
5435 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5436 *refused = entry.blob;
5437 *refLength = entry.size;
5445 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5447 guint32 attrs, visibility;
5449 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5450 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5451 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5454 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5460 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5462 MonoReflectionType *rt;
5465 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5468 mono_error_init (error);
5470 /* we start the count from 1 because we skip the special type <Module> */
5473 for (i = 1; i < tdef->rows; ++i) {
5474 if (mono_module_type_is_visible (tdef, image, i + 1))
5478 count = tdef->rows - 1;
5480 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5481 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5483 for (i = 1; i < tdef->rows; ++i) {
5484 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5485 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5486 mono_loader_assert_no_error (); /* Plug any leaks */
5487 mono_error_assert_ok (error);
5490 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5491 return_val_if_nok (error, NULL);
5493 mono_array_setref (res, count, rt);
5495 MonoException *ex = mono_error_convert_to_exception (error);
5496 mono_array_setref (*exceptions, count, ex);
5505 ICALL_EXPORT MonoArray*
5506 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5509 MonoArray *res = NULL;
5510 MonoArray *exceptions = NULL;
5511 MonoImage *image = NULL;
5512 MonoTableInfo *table = NULL;
5515 int i, len, ex_count;
5517 domain = mono_object_domain (assembly);
5519 g_assert (!assembly_is_dynamic (assembly->assembly));
5520 image = assembly->assembly->image;
5521 table = &image->tables [MONO_TABLE_FILE];
5522 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5523 mono_error_raise_exception (&error);
5525 /* Append data from all modules in the assembly */
5526 for (i = 0; i < table->rows; ++i) {
5527 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5528 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5533 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5534 mono_error_raise_exception (&error);
5536 /* Append the new types to the end of the array */
5537 if (mono_array_length (res2) > 0) {
5539 MonoArray *res3, *ex3;
5541 len1 = mono_array_length (res);
5542 len2 = mono_array_length (res2);
5544 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5545 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5546 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5549 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5550 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5551 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5558 /* the ReflectionTypeLoadException must have all the types (Types property),
5559 * NULL replacing types which throws an exception. The LoaderException must
5560 * contain all exceptions for NULL items.
5563 len = mono_array_length (res);
5566 for (i = 0; i < len; i++) {
5567 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5571 klass = mono_type_get_class (t->type);
5572 if ((klass != NULL) && mono_class_has_failure (klass)) {
5573 /* keep the class in the list */
5574 list = g_list_append (list, klass);
5575 /* and replace Type with NULL */
5576 mono_array_setref (res, i, NULL);
5583 if (list || ex_count) {
5585 MonoException *exc = NULL;
5586 MonoArray *exl = NULL;
5587 int j, length = g_list_length (list) + ex_count;
5589 mono_loader_clear_error ();
5591 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5592 /* Types for which mono_class_get_checked () succeeded */
5593 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5594 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5595 mono_array_setref (exl, i, exc);
5597 /* Types for which it don't */
5598 for (j = 0; j < mono_array_length (exceptions); ++j) {
5599 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5601 g_assert (i < length);
5602 mono_array_setref (exl, i, exc);
5609 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5610 if (!is_ok (&error)) {
5611 mono_error_set_pending_exception (&error);
5614 mono_loader_clear_error ();
5615 mono_set_pending_exception (exc);
5622 ICALL_EXPORT gboolean
5623 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5626 MonoAssemblyName aname;
5627 MonoDomain *domain = mono_object_domain (name);
5629 gboolean is_version_defined;
5630 gboolean is_token_defined;
5632 aname.public_key = NULL;
5633 val = mono_string_to_utf8 (assname);
5634 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5635 g_free ((guint8*) aname.public_key);
5640 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5641 mono_error_set_pending_exception (&error);
5643 mono_assembly_name_free (&aname);
5644 g_free ((guint8*) aname.public_key);
5650 ICALL_EXPORT MonoReflectionType*
5651 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5654 MonoReflectionType *ret;
5655 MonoDomain *domain = mono_object_domain (module);
5658 g_assert (module->image);
5660 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5661 /* These images do not have a global type */
5664 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5665 if (!mono_error_ok (&error)) {
5666 mono_error_set_pending_exception (&error);
5670 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5671 if (!mono_error_ok (&error)) {
5672 mono_error_set_pending_exception (&error);
5680 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5682 /*if (module->image)
5683 mono_image_close (module->image);*/
5686 ICALL_EXPORT MonoString*
5687 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5689 MonoDomain *domain = mono_object_domain (module);
5691 g_assert (module->image);
5692 return mono_string_new (domain, module->image->guid);
5695 ICALL_EXPORT gpointer
5696 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5699 if (module->image && module->image->is_module_handle)
5700 return module->image->raw_data;
5703 return (gpointer) (-1);
5707 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5709 if (image_is_dynamic (image)) {
5710 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5711 *pe_kind = dyn->pe_kind;
5712 *machine = dyn->machine;
5715 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5716 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5721 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5723 return (image->md_version_major << 16) | (image->md_version_minor);
5726 ICALL_EXPORT MonoArray*
5727 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5730 MonoArray *exceptions;
5734 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5738 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5739 mono_error_raise_exception (&error);
5741 for (i = 0; i < mono_array_length (exceptions); ++i) {
5742 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5744 mono_set_pending_exception (ex);
5753 mono_memberref_is_method (MonoImage *image, guint32 token)
5755 if (!image_is_dynamic (image)) {
5756 guint32 cols [MONO_MEMBERREF_SIZE];
5758 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5759 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5760 mono_metadata_decode_blob_size (sig, &sig);
5761 return (*sig != 0x6);
5763 MonoClass *handle_class;
5765 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5768 return mono_defaults.methodhandle_class == handle_class;
5773 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5776 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5777 mono_array_addr (type_args, MonoType*, 0));
5779 context->class_inst = NULL;
5781 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5782 mono_array_addr (method_args, MonoType*, 0));
5784 context->method_inst = NULL;
5787 ICALL_EXPORT MonoType*
5788 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5791 int table = mono_metadata_token_table (token);
5792 int index = mono_metadata_token_index (token);
5793 MonoGenericContext context;
5796 *resolve_error = ResolveTokenError_Other;
5798 /* Validate token */
5799 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5800 (table != MONO_TABLE_TYPESPEC)) {
5801 *resolve_error = ResolveTokenError_BadTable;
5805 if (image_is_dynamic (image)) {
5806 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5807 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5808 return klass ? &klass->byval_arg : NULL;
5811 init_generic_context_from_args (&context, type_args, method_args);
5812 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5813 return klass ? &klass->byval_arg : NULL;
5816 if ((index <= 0) || (index > image->tables [table].rows)) {
5817 *resolve_error = ResolveTokenError_OutOfRange;
5821 init_generic_context_from_args (&context, type_args, method_args);
5822 klass = mono_class_get_checked (image, token, &error);
5824 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5825 if (!mono_error_ok (&error)) {
5826 mono_error_set_pending_exception (&error);
5831 return &klass->byval_arg;
5836 ICALL_EXPORT MonoMethod*
5837 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5840 int table = mono_metadata_token_table (token);
5841 int index = mono_metadata_token_index (token);
5842 MonoGenericContext context;
5845 *resolve_error = ResolveTokenError_Other;
5847 /* Validate token */
5848 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5849 (table != MONO_TABLE_MEMBERREF)) {
5850 *resolve_error = ResolveTokenError_BadTable;
5854 if (image_is_dynamic (image)) {
5855 if (table == MONO_TABLE_METHOD)
5856 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5858 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5859 *resolve_error = ResolveTokenError_BadTable;
5863 init_generic_context_from_args (&context, type_args, method_args);
5864 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5867 if ((index <= 0) || (index > image->tables [table].rows)) {
5868 *resolve_error = ResolveTokenError_OutOfRange;
5871 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5872 *resolve_error = ResolveTokenError_BadTable;
5876 init_generic_context_from_args (&context, type_args, method_args);
5877 method = mono_get_method_checked (image, token, NULL, &context, &error);
5878 mono_error_set_pending_exception (&error);
5883 ICALL_EXPORT MonoString*
5884 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5886 int index = mono_metadata_token_index (token);
5888 *error = ResolveTokenError_Other;
5890 /* Validate token */
5891 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5892 *error = ResolveTokenError_BadTable;
5896 if (image_is_dynamic (image))
5897 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5899 if ((index <= 0) || (index >= image->heap_us.size)) {
5900 *error = ResolveTokenError_OutOfRange;
5904 /* FIXME: What to do if the index points into the middle of a string ? */
5906 return mono_ldstr (mono_domain_get (), image, index);
5909 ICALL_EXPORT MonoClassField*
5910 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5914 int table = mono_metadata_token_table (token);
5915 int index = mono_metadata_token_index (token);
5916 MonoGenericContext context;
5917 MonoClassField *field;
5919 *resolve_error = ResolveTokenError_Other;
5921 /* Validate token */
5922 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5923 *resolve_error = ResolveTokenError_BadTable;
5927 if (image_is_dynamic (image)) {
5928 if (table == MONO_TABLE_FIELD)
5929 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5931 if (mono_memberref_is_method (image, token)) {
5932 *resolve_error = ResolveTokenError_BadTable;
5936 init_generic_context_from_args (&context, type_args, method_args);
5937 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5940 if ((index <= 0) || (index > image->tables [table].rows)) {
5941 *resolve_error = ResolveTokenError_OutOfRange;
5944 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5945 *resolve_error = ResolveTokenError_BadTable;
5949 init_generic_context_from_args (&context, type_args, method_args);
5950 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5951 mono_error_set_pending_exception (&error);
5957 ICALL_EXPORT MonoObject*
5958 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5962 int table = mono_metadata_token_table (token);
5964 *error = ResolveTokenError_Other;
5967 case MONO_TABLE_TYPEDEF:
5968 case MONO_TABLE_TYPEREF:
5969 case MONO_TABLE_TYPESPEC: {
5970 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5972 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5973 mono_error_raise_exception (&merror);
5980 case MONO_TABLE_METHOD:
5981 case MONO_TABLE_METHODSPEC: {
5982 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5984 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5985 mono_error_raise_exception (&merror);
5991 case MONO_TABLE_FIELD: {
5992 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5994 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5995 mono_error_raise_exception (&merror);
6001 case MONO_TABLE_MEMBERREF:
6002 if (mono_memberref_is_method (image, token)) {
6003 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6005 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6006 mono_error_raise_exception (&merror);
6013 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6015 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6016 mono_error_raise_exception (&merror);
6025 *error = ResolveTokenError_BadTable;
6031 ICALL_EXPORT MonoArray*
6032 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6034 int table = mono_metadata_token_table (token);
6035 int idx = mono_metadata_token_index (token);
6036 MonoTableInfo *tables = image->tables;
6041 *error = ResolveTokenError_OutOfRange;
6043 /* FIXME: Support other tables ? */
6044 if (table != MONO_TABLE_STANDALONESIG)
6047 if (image_is_dynamic (image))
6050 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6053 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6055 ptr = mono_metadata_blob_heap (image, sig);
6056 len = mono_metadata_decode_blob_size (ptr, &ptr);
6058 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6059 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6063 ICALL_EXPORT MonoReflectionType*
6064 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6067 MonoReflectionType *ret;
6069 int isbyref = 0, rank;
6070 char *str = mono_string_to_utf8 (smodifiers);
6073 klass = mono_class_from_mono_type (tb->type.type);
6075 /* logic taken from mono_reflection_parse_type(): keep in sync */
6079 if (isbyref) { /* only one level allowed by the spec */
6088 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6089 mono_error_raise_exception (&error);
6093 klass = mono_ptr_class_get (&klass->byval_arg);
6094 mono_class_init (klass);
6105 else if (*p != '*') { /* '*' means unknown lower bound */
6116 klass = mono_array_class_get (klass, rank);
6117 mono_class_init (klass);
6126 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6127 mono_error_raise_exception (&error);
6132 ICALL_EXPORT MonoBoolean
6133 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6139 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6145 check_for_invalid_type (MonoClass *klass, MonoError *error)
6150 mono_error_init (error);
6152 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6155 name = mono_type_get_full_name (klass);
6156 str = mono_string_new (mono_domain_get (), name);
6158 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6161 ICALL_EXPORT MonoReflectionType *
6162 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6165 MonoReflectionType *ret;
6166 MonoClass *klass, *aklass;
6168 klass = mono_class_from_mono_type (type->type);
6169 check_for_invalid_type (klass, &error);
6170 mono_error_raise_exception (&error);
6172 if (rank == 0) //single dimentional array
6173 aklass = mono_array_class_get (klass, 1);
6175 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6177 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6178 mono_error_raise_exception (&error);
6183 ICALL_EXPORT MonoReflectionType *
6184 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6187 MonoReflectionType *ret;
6190 klass = mono_class_from_mono_type (type->type);
6191 mono_class_init_checked (klass, &error);
6192 mono_error_raise_exception (&error);
6193 check_for_invalid_type (klass, &error);
6194 mono_error_raise_exception (&error);
6196 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6197 mono_error_raise_exception (&error);
6202 ICALL_EXPORT MonoReflectionType *
6203 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6206 MonoReflectionType *ret;
6207 MonoClass *klass, *pklass;
6209 klass = mono_class_from_mono_type (type->type);
6210 mono_class_init_checked (klass, &error);
6211 mono_error_raise_exception (&error);
6212 check_for_invalid_type (klass, &error);
6213 mono_error_raise_exception (&error);
6215 pklass = mono_ptr_class_get (type->type);
6217 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6218 mono_error_raise_exception (&error);
6223 ICALL_EXPORT MonoObject *
6224 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6225 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6228 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6229 MonoObject *delegate;
6231 MonoMethod *method = info->method;
6233 mono_class_init_checked (delegate_class, &error);
6234 mono_error_raise_exception (&error);
6236 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6238 if (mono_security_core_clr_enabled ()) {
6239 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6243 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6244 mono_error_raise_exception (&error);
6246 if (method_is_dynamic (method)) {
6247 /* Creating a trampoline would leak memory */
6248 func = mono_compile_method (method);
6250 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6251 method = mono_object_get_virtual_method (target, method);
6252 func = mono_create_ftnptr (mono_domain_get (),
6253 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6256 mono_delegate_ctor_with_method (delegate, target, func, method);
6261 ICALL_EXPORT MonoMulticastDelegate *
6262 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6265 MonoMulticastDelegate *ret;
6267 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6269 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6270 mono_error_raise_exception (&error);
6271 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6276 ICALL_EXPORT MonoReflectionMethod*
6277 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6279 MonoReflectionMethod *ret = NULL;
6281 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6282 mono_error_raise_exception (&error);
6288 static inline gint32
6289 mono_array_get_byte_length (MonoArray *array)
6295 klass = array->obj.vtable->klass;
6297 if (array->bounds == NULL)
6298 length = array->max_length;
6301 for (i = 0; i < klass->rank; ++ i)
6302 length *= array->bounds [i].length;
6305 switch (klass->element_class->byval_arg.type) {
6308 case MONO_TYPE_BOOLEAN:
6312 case MONO_TYPE_CHAR:
6320 return length * sizeof (gpointer);
6331 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6333 return mono_array_get_byte_length (array);
6337 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6339 return mono_array_get (array, gint8, idx);
6343 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6345 mono_array_set (array, gint8, idx, value);
6348 ICALL_EXPORT MonoBoolean
6349 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6351 guint8 *src_buf, *dest_buf;
6354 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6358 g_assert (count >= 0);
6360 /* This is called directly from the class libraries without going through the managed wrapper */
6361 MONO_CHECK_ARG_NULL (src, FALSE);
6362 MONO_CHECK_ARG_NULL (dest, FALSE);
6364 /* watch out for integer overflow */
6365 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6368 src_buf = (guint8 *)src->vector + src_offset;
6369 dest_buf = (guint8 *)dest->vector + dest_offset;
6372 memcpy (dest_buf, src_buf, count);
6374 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6379 #ifndef DISABLE_REMOTING
6380 ICALL_EXPORT MonoObject *
6381 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6384 MonoDomain *domain = mono_object_domain (this_obj);
6386 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6387 MonoTransparentProxy *tp;
6391 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6392 mono_error_raise_exception (&error);
6393 tp = (MonoTransparentProxy*) res;
6395 MONO_OBJECT_SETREF (tp, rp, rp);
6396 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6397 klass = mono_class_from_mono_type (type);
6399 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6400 mono_class_setup_vtable (klass);
6401 if (mono_class_has_failure (klass)) {
6402 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6406 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6407 tp->remote_class = mono_remote_class (domain, class_name, klass);
6409 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6413 ICALL_EXPORT MonoReflectionType *
6414 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6417 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6418 mono_error_raise_exception (&error);
6424 /* System.Environment */
6427 ves_icall_System_Environment_get_UserName (void)
6429 /* using glib is more portable */
6430 return mono_string_new (mono_domain_get (), g_get_user_name ());
6434 ICALL_EXPORT MonoString *
6435 ves_icall_System_Environment_get_MachineName (void)
6437 #if defined (HOST_WIN32)
6442 len = MAX_COMPUTERNAME_LENGTH + 1;
6443 buf = g_new (gunichar2, len);
6446 if (GetComputerName (buf, (PDWORD) &len)) {
6448 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6449 mono_error_raise_exception (&error);
6454 #elif !defined(DISABLE_SOCKETS)
6458 #if defined _SC_HOST_NAME_MAX
6459 n = sysconf (_SC_HOST_NAME_MAX);
6463 buf = g_malloc (n+1);
6465 if (gethostname (buf, n) == 0){
6467 result = mono_string_new (mono_domain_get (), buf);
6474 return mono_string_new (mono_domain_get (), "mono");
6479 ves_icall_System_Environment_get_Platform (void)
6481 #if defined (TARGET_WIN32)
6484 #elif defined(__MACH__)
6487 // Notice that the value is hidden from user code, and only exposed
6488 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6489 // define and making assumptions based on Unix/128/4 values before there
6490 // was a MacOS define. Lots of code would assume that not-Unix meant
6491 // Windows, but in this case, it would be OSX.
6500 ICALL_EXPORT MonoString *
6501 ves_icall_System_Environment_get_NewLine (void)
6503 #if defined (HOST_WIN32)
6504 return mono_string_new (mono_domain_get (), "\r\n");
6506 return mono_string_new (mono_domain_get (), "\n");
6510 ICALL_EXPORT MonoBoolean
6511 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6513 #if SIZEOF_VOID_P == 8
6517 gboolean isWow64Process = FALSE;
6518 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6519 return (MonoBoolean)isWow64Process;
6521 #elif defined(HAVE_SYS_UTSNAME_H)
6522 struct utsname name;
6524 if (uname (&name) >= 0) {
6525 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6532 ICALL_EXPORT MonoString *
6533 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6541 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6542 value = g_getenv (utf8_name);
6549 return mono_string_new (mono_domain_get (), value);
6553 * There is no standard way to get at environ.
6556 #ifndef __MINGW32_VERSION
6557 #if defined(__APPLE__)
6558 #if defined (TARGET_OSX)
6559 /* Apple defines this in crt_externs.h but doesn't provide that header for
6560 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6561 * in fact exist on all implementations (so far)
6563 gchar ***_NSGetEnviron(void);
6564 #define environ (*_NSGetEnviron())
6566 static char *mono_environ[1] = { NULL };
6567 #define environ mono_environ
6568 #endif /* defined (TARGET_OSX) */
6576 ICALL_EXPORT MonoArray *
6577 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6588 env_strings = GetEnvironmentStrings();
6591 env_string = env_strings;
6592 while (*env_string != '\0') {
6593 /* weird case that MS seems to skip */
6594 if (*env_string != '=')
6596 while (*env_string != '\0')
6602 domain = mono_domain_get ();
6603 names = mono_array_new (domain, mono_defaults.string_class, n);
6607 env_string = env_strings;
6608 while (*env_string != '\0') {
6609 /* weird case that MS seems to skip */
6610 if (*env_string != '=') {
6611 equal_str = wcschr(env_string, '=');
6612 g_assert(equal_str);
6614 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6615 mono_error_raise_exception (&error);
6616 mono_array_setref (names, n, str);
6619 while (*env_string != '\0')
6624 FreeEnvironmentStrings (env_strings);
6637 for (e = environ; *e != 0; ++ e)
6640 domain = mono_domain_get ();
6641 names = mono_array_new (domain, mono_defaults.string_class, n);
6644 for (e = environ; *e != 0; ++ e) {
6645 parts = g_strsplit (*e, "=", 2);
6647 str = mono_string_new (domain, *parts);
6648 mono_array_setref (names, n, str);
6661 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6663 #if !GLIB_CHECK_VERSION(2,4,0)
6664 #define g_setenv(a,b,c) setenv(a,b,c)
6665 #define g_unsetenv(a) unsetenv(a)
6669 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6672 gunichar2 *utf16_name, *utf16_value;
6674 gchar *utf8_name, *utf8_value;
6679 utf16_name = mono_string_to_utf16 (name);
6680 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6681 SetEnvironmentVariable (utf16_name, NULL);
6682 g_free (utf16_name);
6686 utf16_value = mono_string_to_utf16 (value);
6688 SetEnvironmentVariable (utf16_name, utf16_value);
6690 g_free (utf16_name);
6691 g_free (utf16_value);
6693 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6695 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6696 g_unsetenv (utf8_name);
6701 utf8_value = mono_string_to_utf8_checked (value, &error);
6702 if (!mono_error_ok (&error)) {
6704 mono_error_set_pending_exception (&error);
6707 g_setenv (utf8_name, utf8_value, TRUE);
6710 g_free (utf8_value);
6715 ves_icall_System_Environment_Exit (int result)
6717 mono_environment_exitcode_set (result);
6719 /* FIXME: There are some cleanup hangs that should be worked out, but
6720 * if the program is going to exit, everything will be cleaned up when
6721 * NaCl exits anyway.
6723 #ifndef __native_client__
6724 if (!mono_runtime_try_shutdown ())
6725 mono_thread_exit ();
6727 /* Suspend all managed threads since the runtime is going away */
6728 mono_thread_suspend_all_other_threads ();
6730 mono_runtime_quit ();
6733 /* we may need to do some cleanup here... */
6737 ICALL_EXPORT MonoString*
6738 ves_icall_System_Environment_GetGacPath (void)
6740 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6743 ICALL_EXPORT MonoString*
6744 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6746 #if defined (HOST_WIN32)
6747 #ifndef CSIDL_FLAG_CREATE
6748 #define CSIDL_FLAG_CREATE 0x8000
6751 WCHAR path [MAX_PATH];
6752 /* Create directory if no existing */
6753 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6758 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6759 mono_error_raise_exception (&error);
6763 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6765 return mono_string_new (mono_domain_get (), "");
6768 ICALL_EXPORT MonoArray *
6769 ves_icall_System_Environment_GetLogicalDrives (void)
6772 gunichar2 buf [256], *ptr, *dname;
6774 guint initial_size = 127, size = 128;
6777 MonoString *drivestr;
6778 MonoDomain *domain = mono_domain_get ();
6784 while (size > initial_size) {
6785 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6786 if (size > initial_size) {
6789 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6790 initial_size = size;
6804 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6809 while (*u16) { u16++; len ++; }
6810 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6811 mono_error_raise_exception (&error);
6812 mono_array_setref (result, ndrives++, drivestr);
6822 ICALL_EXPORT MonoString *
6823 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6825 gunichar2 volume_name [MAX_PATH + 1];
6827 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6829 return mono_string_from_utf16 (volume_name);
6832 ICALL_EXPORT MonoString *
6833 ves_icall_System_Environment_InternalGetHome (void)
6835 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6838 static const char *encodings [] = {
6840 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6841 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6842 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6844 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6845 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6846 "x_unicode_2_0_utf_7",
6848 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6849 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6851 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6854 "unicodefffe", "utf_16be",
6861 * Returns the internal codepage, if the value of "int_code_page" is
6862 * 1 at entry, and we can not compute a suitable code page number,
6863 * returns the code page as a string
6865 ICALL_EXPORT MonoString*
6866 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6871 char *codepage = NULL;
6873 int want_name = *int_code_page;
6876 *int_code_page = -1;
6878 g_get_charset (&cset);
6879 c = codepage = strdup (cset);
6880 for (c = codepage; *c; c++){
6881 if (isascii (*c) && isalpha (*c))
6886 /* g_print ("charset: %s\n", cset); */
6888 /* handle some common aliases */
6891 for (i = 0; p != 0; ){
6894 p = encodings [++i];
6897 if (strcmp (p, codepage) == 0){
6898 *int_code_page = code;
6901 p = encodings [++i];
6904 if (strstr (codepage, "utf_8") != NULL)
6905 *int_code_page |= 0x10000000;
6908 if (want_name && *int_code_page == -1)
6909 return mono_string_new (mono_domain_get (), cset);
6914 ICALL_EXPORT MonoBoolean
6915 ves_icall_System_Environment_get_HasShutdownStarted (void)
6917 if (mono_runtime_is_shutting_down ())
6920 if (mono_domain_is_unloading (mono_domain_get ()))
6927 ves_icall_System_Environment_BroadcastSettingChange (void)
6930 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6935 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6941 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6942 MonoReflectionMethod *method,
6943 MonoArray *out_args)
6945 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6948 #ifndef DISABLE_REMOTING
6949 ICALL_EXPORT MonoBoolean
6950 ves_icall_IsTransparentProxy (MonoObject *proxy)
6955 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6961 ICALL_EXPORT MonoReflectionMethod *
6962 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6963 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6965 MonoReflectionMethod *ret = NULL;
6970 MonoMethod **vtable;
6971 MonoMethod *res = NULL;
6973 MONO_CHECK_ARG_NULL (rtype, NULL);
6974 MONO_CHECK_ARG_NULL (rmethod, NULL);
6976 method = rmethod->method;
6977 klass = mono_class_from_mono_type (rtype->type);
6978 mono_class_init_checked (klass, &error);
6979 mono_error_raise_exception (&error);
6981 if (MONO_CLASS_IS_INTERFACE (klass))
6984 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6987 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6988 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6994 mono_class_setup_vtable (klass);
6995 vtable = klass->vtable;
6997 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6998 gboolean variance_used = FALSE;
6999 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7000 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7002 res = vtable [offs + method->slot];
7004 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7007 if (method->slot != -1)
7008 res = vtable [method->slot];
7014 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7015 mono_error_raise_exception (&error);
7020 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7026 klass = mono_class_from_mono_type (type->type);
7027 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7028 if (!is_ok (&error)) {
7029 mono_error_set_pending_exception (&error);
7033 mono_vtable_set_is_remote (vtable, enable);
7036 #else /* DISABLE_REMOTING */
7039 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7041 g_assert_not_reached ();
7046 ICALL_EXPORT MonoObject *
7047 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7054 domain = mono_object_domain (type);
7055 klass = mono_class_from_mono_type (type->type);
7056 mono_class_init_checked (klass, &error);
7057 mono_error_raise_exception (&error);
7059 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7060 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7064 if (klass->rank >= 1) {
7065 g_assert (klass->rank == 1);
7066 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7068 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7069 if (!is_ok (&error)) {
7070 mono_error_set_pending_exception (&error);
7073 /* Bypass remoting object creation check */
7074 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7075 mono_error_set_pending_exception (&error);
7081 ICALL_EXPORT MonoString *
7082 ves_icall_System_IO_get_temp_path (void)
7084 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7087 #ifndef PLATFORM_NO_DRIVEINFO
7088 ICALL_EXPORT MonoBoolean
7089 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7090 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7094 ULARGE_INTEGER wapi_free_bytes_avail;
7095 ULARGE_INTEGER wapi_total_number_of_bytes;
7096 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7098 *error = ERROR_SUCCESS;
7099 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7100 &wapi_total_number_of_free_bytes);
7103 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7104 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7105 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7107 *free_bytes_avail = 0;
7108 *total_number_of_bytes = 0;
7109 *total_number_of_free_bytes = 0;
7110 *error = GetLastError ();
7116 ICALL_EXPORT guint32
7117 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7119 return GetDriveType (mono_string_chars (root_path_name));
7123 ICALL_EXPORT gpointer
7124 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7126 return mono_compile_method (method);
7129 ICALL_EXPORT MonoString *
7130 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7135 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7137 #if defined (HOST_WIN32)
7138 /* Avoid mixing '/' and '\\' */
7141 for (i = strlen (path) - 1; i >= 0; i--)
7142 if (path [i] == '/')
7146 mcpath = mono_string_new (mono_domain_get (), path);
7153 get_bundled_app_config (void)
7155 const gchar *app_config;
7158 gchar *config_file_name, *config_file_path;
7159 gsize len, config_file_path_length, config_ext_length;
7162 domain = mono_domain_get ();
7163 file = domain->setup->configuration_file;
7164 if (!file || file->length == 0)
7167 // Retrieve config file and remove the extension
7168 config_file_name = mono_string_to_utf8 (file);
7169 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7170 if (!config_file_path)
7171 config_file_path = config_file_name;
7173 config_file_path_length = strlen (config_file_path);
7174 config_ext_length = strlen (".config");
7175 if (config_file_path_length <= config_ext_length)
7178 len = config_file_path_length - config_ext_length;
7179 module = (gchar *)g_malloc0 (len + 1);
7180 memcpy (module, config_file_path, len);
7181 // Get the config file from the module name
7182 app_config = mono_config_string_for_assembly_file (module);
7185 if (config_file_name != config_file_path)
7186 g_free (config_file_name);
7187 g_free (config_file_path);
7192 return mono_string_new (mono_domain_get (), app_config);
7196 get_bundled_machine_config (void)
7198 const gchar *machine_config;
7200 machine_config = mono_get_machine_config ();
7202 if (!machine_config)
7205 return mono_string_new (mono_domain_get (), machine_config);
7208 ICALL_EXPORT MonoString *
7209 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7214 path = g_path_get_dirname (mono_get_config_dir ());
7216 #if defined (HOST_WIN32)
7217 /* Avoid mixing '/' and '\\' */
7220 for (i = strlen (path) - 1; i >= 0; i--)
7221 if (path [i] == '/')
7225 ipath = mono_string_new (mono_domain_get (), path);
7231 ICALL_EXPORT gboolean
7232 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7234 MonoPEResourceDataEntry *entry;
7237 if (!assembly || !result || !size)
7242 image = assembly->assembly->image;
7243 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7247 *result = mono_image_rva_map (image, entry->rde_data_offset);
7252 *size = entry->rde_size;
7257 ICALL_EXPORT MonoBoolean
7258 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7260 return mono_is_debugger_attached ();
7263 ICALL_EXPORT MonoBoolean
7264 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7266 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7267 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7273 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7275 if (mono_get_runtime_callbacks ()->debug_log)
7276 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7280 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7282 #if defined (HOST_WIN32)
7283 OutputDebugString (mono_string_chars (message));
7285 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7289 /* Only used for value types */
7290 ICALL_EXPORT MonoObject *
7291 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7298 domain = mono_object_domain (type);
7299 klass = mono_class_from_mono_type (type->type);
7300 mono_class_init_checked (klass, &error);
7301 mono_error_raise_exception (&error);
7303 if (mono_class_is_nullable (klass))
7304 /* No arguments -> null */
7307 result = mono_object_new_checked (domain, klass, &error);
7308 mono_error_raise_exception (&error);
7312 ICALL_EXPORT MonoReflectionMethod *
7313 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7315 MonoReflectionMethod *ret = NULL;
7318 MonoClass *klass, *parent;
7319 MonoGenericContext *generic_inst = NULL;
7320 MonoMethod *method = m->method;
7321 MonoMethod *result = NULL;
7324 if (method->klass == NULL)
7327 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7328 MONO_CLASS_IS_INTERFACE (method->klass) ||
7329 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7332 slot = mono_method_get_vtable_slot (method);
7336 klass = method->klass;
7337 if (klass->generic_class) {
7338 generic_inst = mono_class_get_context (klass);
7339 klass = klass->generic_class->container_class;
7343 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7344 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7345 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7346 or klass is the generic container class and generic_inst is the instantiation.
7348 when we go to the parent, if the parent is an open constructed type, we need to
7349 replace the type parameters by the definitions from the generic_inst, and then take it
7350 apart again into the klass and the generic_inst.
7352 For cases like this:
7353 class C<T> : B<T, int> {
7354 public override void Foo () { ... }
7356 class B<U,V> : A<HashMap<U,V>> {
7357 public override void Foo () { ... }
7360 public virtual void Foo () { ... }
7363 if at each iteration the parent isn't open, we can skip inflating it. if at some
7364 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7367 MonoGenericContext *parent_inst = NULL;
7368 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7370 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7371 if (!mono_error_ok (&error)) {
7372 mono_error_set_pending_exception (&error);
7376 if (parent->generic_class) {
7377 parent_inst = mono_class_get_context (parent);
7378 parent = parent->generic_class->container_class;
7381 mono_class_setup_vtable (parent);
7382 if (parent->vtable_size <= slot)
7385 generic_inst = parent_inst;
7388 klass = klass->parent;
7391 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7392 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7393 if (!mono_error_ok (&error)) {
7394 mono_error_set_pending_exception (&error);
7398 generic_inst = NULL;
7400 if (klass->generic_class) {
7401 generic_inst = mono_class_get_context (klass);
7402 klass = klass->generic_class->container_class;
7408 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7409 if (!mono_error_ok (&error)) {
7410 mono_error_set_pending_exception (&error);
7415 if (klass == method->klass)
7418 /*This is possible if definition == FALSE.
7419 * Do it here to be really sure we don't read invalid memory.
7421 if (slot >= klass->vtable_size)
7424 mono_class_setup_vtable (klass);
7426 result = klass->vtable [slot];
7427 if (result == NULL) {
7428 /* It is an abstract method */
7429 gpointer iter = NULL;
7430 while ((result = mono_class_get_methods (klass, &iter)))
7431 if (result->slot == slot)
7438 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7439 mono_error_raise_exception (&error);
7443 ICALL_EXPORT MonoString*
7444 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7446 MonoMethod *method = m->method;
7448 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7453 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7455 iter->sig = *(MonoMethodSignature**)argsp;
7457 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7458 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7461 /* FIXME: it's not documented what start is exactly... */
7465 iter->args = argsp + sizeof (gpointer);
7467 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7469 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7472 ICALL_EXPORT MonoTypedRef
7473 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7475 guint32 i, arg_size;
7479 i = iter->sig->sentinelpos + iter->next_arg;
7481 g_assert (i < iter->sig->param_count);
7483 res.type = iter->sig->params [i];
7484 res.klass = mono_class_from_mono_type (res.type);
7485 arg_size = mono_type_stack_size (res.type, &align);
7486 #if defined(__arm__) || defined(__mips__)
7487 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7489 res.value = iter->args;
7490 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7491 /* Values are stored as 8 byte register sized objects, but 'value'
7492 * is dereferenced as a pointer in other routines.
7494 res.value = (char*)res.value + 4;
7496 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7497 if (arg_size <= sizeof (gpointer)) {
7499 int padding = arg_size - mono_type_size (res.type, &dummy);
7500 res.value = (guint8*)res.value + padding;
7503 iter->args = (char*)iter->args + arg_size;
7506 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7511 ICALL_EXPORT MonoTypedRef
7512 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7514 guint32 i, arg_size;
7518 i = iter->sig->sentinelpos + iter->next_arg;
7520 g_assert (i < iter->sig->param_count);
7522 while (i < iter->sig->param_count) {
7523 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7525 res.type = iter->sig->params [i];
7526 res.klass = mono_class_from_mono_type (res.type);
7527 /* FIXME: endianess issue... */
7528 arg_size = mono_type_stack_size (res.type, &align);
7529 #if defined(__arm__) || defined(__mips__)
7530 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7532 res.value = iter->args;
7533 iter->args = (char*)iter->args + arg_size;
7535 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7538 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7546 ICALL_EXPORT MonoType*
7547 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7551 i = iter->sig->sentinelpos + iter->next_arg;
7553 g_assert (i < iter->sig->param_count);
7555 return iter->sig->params [i];
7558 ICALL_EXPORT MonoObject*
7559 mono_TypedReference_ToObject (MonoTypedRef* tref)
7561 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7562 MonoObject** objp = (MonoObject **)tref->value;
7566 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7569 ICALL_EXPORT MonoTypedRef
7570 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7573 MonoReflectionField *f;
7575 MonoType *ftype = NULL;
7579 memset (&res, 0, sizeof (res));
7582 g_assert (mono_array_length (fields) > 0);
7584 klass = target->vtable->klass;
7586 for (i = 0; i < mono_array_length (fields); ++i) {
7587 f = mono_array_get (fields, MonoReflectionField*, i);
7589 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7592 if (f->field->parent != klass) {
7593 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7597 p = (guint8*)target + f->field->offset;
7599 p += f->field->offset - sizeof (MonoObject);
7600 klass = mono_class_from_mono_type (f->field->type);
7601 ftype = f->field->type;
7605 res.klass = mono_class_from_mono_type (ftype);
7612 prelink_method (MonoMethod *method, MonoError *error)
7614 const char *exc_class, *exc_arg;
7616 mono_error_init (error);
7617 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7619 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7621 mono_error_set_exception_instance (error,
7622 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7625 /* create the wrapper, too? */
7629 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7633 prelink_method (method->method, &error);
7634 mono_error_raise_exception (&error);
7638 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7641 MonoClass *klass = mono_class_from_mono_type (type->type);
7643 gpointer iter = NULL;
7645 mono_class_init_checked (klass, &error);
7646 mono_error_raise_exception (&error);
7648 while ((m = mono_class_get_methods (klass, &iter))) {
7649 prelink_method (m, &error);
7650 mono_error_raise_exception (&error);
7654 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7656 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7657 gint32 const **exponents,
7658 gunichar2 const **digitLowerTable,
7659 gunichar2 const **digitUpperTable,
7660 gint64 const **tenPowersList,
7661 gint32 const **decHexDigits)
7663 *mantissas = Formatter_MantissaBitsTable;
7664 *exponents = Formatter_TensExponentTable;
7665 *digitLowerTable = Formatter_DigitLowerTable;
7666 *digitUpperTable = Formatter_DigitUpperTable;
7667 *tenPowersList = Formatter_TenPowersList;
7668 *decHexDigits = Formatter_DecHexDigits;
7672 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7673 * and avoid useless allocations.
7676 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7678 MonoReflectionType *rt;
7682 mono_error_init (error);
7683 for (i = 0; i < type->num_mods; ++i) {
7684 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7689 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7691 for (i = 0; i < type->num_mods; ++i) {
7692 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7693 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7694 return_val_if_nok (error, NULL);
7696 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7697 return_val_if_nok (error, NULL);
7699 mono_array_setref (res, count, rt);
7706 ICALL_EXPORT MonoArray*
7707 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7710 MonoType *type = param->ClassImpl->type;
7711 MonoClass *member_class = mono_object_class (param->MemberImpl);
7712 MonoMethod *method = NULL;
7715 MonoMethodSignature *sig;
7718 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7719 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7720 method = rmethod->method;
7721 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7722 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7723 if (!(method = prop->property->get))
7724 method = prop->property->set;
7727 char *type_name = mono_type_get_full_name (member_class);
7728 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7729 MonoException *ex = mono_get_exception_not_supported (msg);
7732 mono_set_pending_exception (ex);
7736 image = method->klass->image;
7737 pos = param->PositionImpl;
7738 sig = mono_method_signature (method);
7742 type = sig->params [pos];
7744 res = type_array_from_modifiers (image, type, optional, &error);
7745 mono_error_raise_exception (&error);
7750 get_property_type (MonoProperty *prop)
7752 MonoMethodSignature *sig;
7754 sig = mono_method_signature (prop->get);
7756 } else if (prop->set) {
7757 sig = mono_method_signature (prop->set);
7758 return sig->params [sig->param_count - 1];
7763 ICALL_EXPORT MonoArray*
7764 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7767 MonoType *type = get_property_type (property->property);
7768 MonoImage *image = property->klass->image;
7773 res = type_array_from_modifiers (image, type, optional, &error);
7774 mono_error_raise_exception (&error);
7779 *Construct a MonoType suited to be used to decode a constant blob object.
7781 * @type is the target type which will be constructed
7782 * @blob_type is the blob type, for example, that comes from the constant table
7783 * @real_type is the expected constructed type.
7786 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7788 type->type = blob_type;
7789 type->data.klass = NULL;
7790 if (blob_type == MONO_TYPE_CLASS)
7791 type->data.klass = mono_defaults.object_class;
7792 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7793 /* For enums, we need to use the base type */
7794 type->type = MONO_TYPE_VALUETYPE;
7795 type->data.klass = mono_class_from_mono_type (real_type);
7797 type->data.klass = mono_class_from_mono_type (real_type);
7800 ICALL_EXPORT MonoObject*
7801 property_info_get_default_value (MonoReflectionProperty *property)
7805 MonoProperty *prop = property->property;
7806 MonoType *type = get_property_type (prop);
7807 MonoDomain *domain = mono_object_domain (property);
7808 MonoTypeEnum def_type;
7809 const char *def_value;
7812 mono_class_init (prop->parent);
7814 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7815 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7819 def_value = mono_class_get_property_default_value (prop, &def_type);
7821 mono_type_from_blob_type (&blob_type, def_type, type);
7822 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7824 mono_error_set_pending_exception (&error);
7828 ICALL_EXPORT MonoBoolean
7829 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7832 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7833 MonoCustomAttrInfo *cinfo;
7836 mono_class_init_checked (attr_class, &error);
7837 mono_error_raise_exception (&error);
7839 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7840 if (!is_ok (&error)) {
7841 mono_error_set_pending_exception (&error);
7846 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7848 mono_custom_attrs_free (cinfo);
7852 ICALL_EXPORT MonoArray*
7853 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7855 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7860 mono_class_init_checked (attr_class, &error);
7861 mono_error_raise_exception (&error);
7864 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7865 if (!mono_error_ok (&error)) {
7866 mono_error_set_pending_exception (&error);
7870 if (mono_loader_get_last_error ()) {
7871 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7878 ICALL_EXPORT MonoArray*
7879 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7883 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7884 mono_error_set_pending_exception (&error);
7889 ICALL_EXPORT MonoString*
7890 ves_icall_Mono_Runtime_GetDisplayName (void)
7893 MonoString *display_name;
7895 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7896 display_name = mono_string_new (mono_domain_get (), info);
7898 return display_name;
7901 ICALL_EXPORT MonoString*
7902 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7905 MonoString *message;
7909 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7910 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7913 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7915 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7916 mono_error_raise_exception (&error);
7923 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7926 char *path_str = mono_string_to_utf8 (path);
7928 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7936 ICALL_EXPORT gpointer
7937 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7939 return GetCurrentProcess ();
7942 ICALL_EXPORT MonoBoolean
7943 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7945 return GetExitCodeProcess (handle, (guint32*) exitcode);
7948 ICALL_EXPORT MonoBoolean
7949 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7951 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7952 return CloseHandle (handle);
7954 return CloseProcess (handle);
7958 ICALL_EXPORT MonoBoolean
7959 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7961 return TerminateProcess (handle, exitcode);
7965 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7967 return WaitForInputIdle (handle, milliseconds);
7970 ICALL_EXPORT MonoBoolean
7971 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7973 return GetProcessWorkingSetSize (handle, min, max);
7976 ICALL_EXPORT MonoBoolean
7977 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7979 return SetProcessWorkingSetSize (handle, min, max);
7982 ICALL_EXPORT MonoBoolean
7983 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7985 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7989 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7991 return mono_process_current_pid ();
7995 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7997 return GetPriorityClass (handle);
8000 ICALL_EXPORT MonoBoolean
8001 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8003 return SetPriorityClass (handle, priorityClass);
8006 #ifndef DISABLE_ICALL_TABLES
8008 #define ICALL_TYPE(id,name,first)
8009 #define ICALL(id,name,func) Icall_ ## id,
8012 #include "metadata/icall-def.h"
8018 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8019 #define ICALL(id,name,func)
8021 #include "metadata/icall-def.h"
8027 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8028 #define ICALL(id,name,func)
8030 guint16 first_icall;
8033 static const IcallTypeDesc
8034 icall_type_descs [] = {
8035 #include "metadata/icall-def.h"
8039 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8042 #define ICALL_TYPE(id,name,first)
8045 #ifdef HAVE_ARRAY_ELEM_INIT
8046 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8047 #define MSGSTRFIELD1(line) str##line
8049 static const struct msgstrtn_t {
8050 #define ICALL(id,name,func)
8052 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8053 #include "metadata/icall-def.h"
8055 } icall_type_names_str = {
8056 #define ICALL_TYPE(id,name,first) (name),
8057 #include "metadata/icall-def.h"
8060 static const guint16 icall_type_names_idx [] = {
8061 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8062 #include "metadata/icall-def.h"
8065 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8067 static const struct msgstr_t {
8069 #define ICALL_TYPE(id,name,first)
8070 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8071 #include "metadata/icall-def.h"
8073 } icall_names_str = {
8074 #define ICALL(id,name,func) (name),
8075 #include "metadata/icall-def.h"
8078 static const guint16 icall_names_idx [] = {
8079 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8080 #include "metadata/icall-def.h"
8083 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8089 #define ICALL_TYPE(id,name,first) name,
8090 #define ICALL(id,name,func)
8091 static const char* const
8092 icall_type_names [] = {
8093 #include "metadata/icall-def.h"
8097 #define icall_type_name_get(id) (icall_type_names [(id)])
8101 #define ICALL_TYPE(id,name,first)
8102 #define ICALL(id,name,func) name,
8103 static const char* const
8105 #include "metadata/icall-def.h"
8108 #define icall_name_get(id) icall_names [(id)]
8110 #endif /* !HAVE_ARRAY_ELEM_INIT */
8114 #define ICALL_TYPE(id,name,first)
8115 #define ICALL(id,name,func) func,
8116 static const gconstpointer
8117 icall_functions [] = {
8118 #include "metadata/icall-def.h"
8122 #ifdef ENABLE_ICALL_SYMBOL_MAP
8125 #define ICALL_TYPE(id,name,first)
8126 #define ICALL(id,name,func) #func,
8127 static const gconstpointer
8128 icall_symbols [] = {
8129 #include "metadata/icall-def.h"
8134 #endif /* DISABLE_ICALL_TABLES */
8136 static mono_mutex_t icall_mutex;
8137 static GHashTable *icall_hash = NULL;
8138 static GHashTable *jit_icall_hash_name = NULL;
8139 static GHashTable *jit_icall_hash_addr = NULL;
8142 mono_icall_init (void)
8144 #ifndef DISABLE_ICALL_TABLES
8147 /* check that tables are sorted: disable in release */
8150 const char *prev_class = NULL;
8151 const char *prev_method;
8153 for (i = 0; i < Icall_type_num; ++i) {
8154 const IcallTypeDesc *desc;
8157 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8158 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8159 prev_class = icall_type_name_get (i);
8160 desc = &icall_type_descs [i];
8161 num_icalls = icall_desc_num_icalls (desc);
8162 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8163 for (j = 0; j < num_icalls; ++j) {
8164 const char *methodn = icall_name_get (desc->first_icall + j);
8165 if (prev_method && strcmp (prev_method, methodn) >= 0)
8166 g_print ("method %s should come before method %s\n", methodn, prev_method);
8167 prev_method = methodn;
8173 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8174 mono_os_mutex_init (&icall_mutex);
8178 mono_icall_lock (void)
8180 mono_locks_os_acquire (&icall_mutex, IcallLock);
8184 mono_icall_unlock (void)
8186 mono_locks_os_release (&icall_mutex, IcallLock);
8190 mono_icall_cleanup (void)
8192 g_hash_table_destroy (icall_hash);
8193 g_hash_table_destroy (jit_icall_hash_name);
8194 g_hash_table_destroy (jit_icall_hash_addr);
8195 mono_os_mutex_destroy (&icall_mutex);
8199 * mono_add_internal_call:
8200 * @name: method specification to surface to the managed world
8201 * @method: pointer to a C method to invoke when the method is called
8203 * This method surfaces the C function pointed by @method as a method
8204 * that has been surfaced in managed code with the method specified in
8205 * @name as an internal call.
8207 * Internal calls are surfaced to all app domains loaded and they are
8208 * accessibly by a type with the specified name.
8210 * You must provide a fully qualified type name, that is namespaces
8211 * and type name, followed by a colon and the method name, with an
8212 * optional signature to bind.
8214 * For example, the following are all valid declarations:
8216 * "MyApp.Services.ScriptService:Accelerate"
8217 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8219 * You use method parameters in cases where there might be more than
8220 * one surface method to managed code. That way you can register different
8221 * internal calls for different method overloads.
8223 * The internal calls are invoked with no marshalling. This means that .NET
8224 * types like System.String are exposed as `MonoString *` parameters. This is
8225 * different than the way that strings are surfaced in P/Invoke.
8227 * For more information on how the parameters are marshalled, see the
8228 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8231 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8232 * reference for more information on the format of method descriptions.
8235 mono_add_internal_call (const char *name, gconstpointer method)
8239 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8241 mono_icall_unlock ();
8244 #ifndef DISABLE_ICALL_TABLES
8246 #ifdef HAVE_ARRAY_ELEM_INIT
8248 compare_method_imap (const void *key, const void *elem)
8250 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8251 return strcmp (key, method_name);
8255 find_method_icall (const IcallTypeDesc *imap, const char *name)
8257 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);
8260 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8264 compare_class_imap (const void *key, const void *elem)
8266 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8267 return strcmp (key, class_name);
8270 static const IcallTypeDesc*
8271 find_class_icalls (const char *name)
8273 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);
8276 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8279 #else /* HAVE_ARRAY_ELEM_INIT */
8282 compare_method_imap (const void *key, const void *elem)
8284 const char** method_name = (const char**)elem;
8285 return strcmp (key, *method_name);
8289 find_method_icall (const IcallTypeDesc *imap, const char *name)
8291 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8294 return (gpointer)icall_functions [(nameslot - icall_names)];
8298 compare_class_imap (const void *key, const void *elem)
8300 const char** class_name = (const char**)elem;
8301 return strcmp (key, *class_name);
8304 static const IcallTypeDesc*
8305 find_class_icalls (const char *name)
8307 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8310 return &icall_type_descs [nameslot - icall_type_names];
8313 #endif /* HAVE_ARRAY_ELEM_INIT */
8315 #endif /* DISABLE_ICALL_TABLES */
8318 * we should probably export this as an helper (handle nested types).
8319 * Returns the number of chars written in buf.
8322 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8324 int nspacelen, cnamelen;
8325 nspacelen = strlen (klass->name_space);
8326 cnamelen = strlen (klass->name);
8327 if (nspacelen + cnamelen + 2 > bufsize)
8330 memcpy (buf, klass->name_space, nspacelen);
8331 buf [nspacelen ++] = '.';
8333 memcpy (buf + nspacelen, klass->name, cnamelen);
8334 buf [nspacelen + cnamelen] = 0;
8335 return nspacelen + cnamelen;
8338 #ifdef DISABLE_ICALL_TABLES
8340 no_icall_table (void)
8342 g_assert_not_reached ();
8347 mono_lookup_internal_call (MonoMethod *method)
8352 int typelen = 0, mlen, siglen;
8354 #ifndef DISABLE_ICALL_TABLES
8355 const IcallTypeDesc *imap = NULL;
8358 g_assert (method != NULL);
8360 if (method->is_inflated)
8361 method = ((MonoMethodInflated *) method)->declaring;
8363 if (method->klass->nested_in) {
8364 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8368 mname [pos++] = '/';
8371 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8377 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8382 #ifndef DISABLE_ICALL_TABLES
8383 imap = find_class_icalls (mname);
8386 mname [typelen] = ':';
8387 mname [typelen + 1] = ':';
8389 mlen = strlen (method->name);
8390 memcpy (mname + typelen + 2, method->name, mlen);
8391 sigstart = mname + typelen + 2 + mlen;
8394 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8395 siglen = strlen (tmpsig);
8396 if (typelen + mlen + siglen + 6 > sizeof (mname))
8399 memcpy (sigstart + 1, tmpsig, siglen);
8400 sigstart [siglen + 1] = ')';
8401 sigstart [siglen + 2] = 0;
8406 res = g_hash_table_lookup (icall_hash, mname);
8408 mono_icall_unlock ();;
8411 /* try without signature */
8413 res = g_hash_table_lookup (icall_hash, mname);
8415 mono_icall_unlock ();
8419 #ifdef DISABLE_ICALL_TABLES
8420 mono_icall_unlock ();
8421 /* Fail only when the result is actually used */
8422 /* mono_marshal_get_native_wrapper () depends on this */
8423 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8424 return ves_icall_System_String_ctor_RedirectToCreateString;
8426 return no_icall_table;
8428 /* it wasn't found in the static call tables */
8430 mono_icall_unlock ();
8433 res = find_method_icall (imap, sigstart - mlen);
8435 mono_icall_unlock ();
8438 /* try _with_ signature */
8440 res = find_method_icall (imap, sigstart - mlen);
8442 mono_icall_unlock ();
8446 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8447 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8448 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8449 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8450 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");
8451 g_print ("If you see other errors or faults after this message they are probably related\n");
8452 g_print ("and you need to fix your mono install first.\n");
8454 mono_icall_unlock ();
8460 #ifdef ENABLE_ICALL_SYMBOL_MAP
8462 func_cmp (gconstpointer key, gconstpointer p)
8464 return (gsize)key - (gsize)*(gsize*)p;
8469 * mono_lookup_icall_symbol:
8471 * Given the icall METHOD, returns its C symbol.
8474 mono_lookup_icall_symbol (MonoMethod *m)
8476 #ifdef DISABLE_ICALL_TABLES
8477 g_assert_not_reached ();
8480 #ifdef ENABLE_ICALL_SYMBOL_MAP
8484 static gconstpointer *functions_sorted;
8485 static const char**symbols_sorted;
8486 static gboolean inited;
8491 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8492 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8493 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8494 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8495 /* Bubble sort the two arrays */
8499 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8500 if (functions_sorted [i] > functions_sorted [i + 1]) {
8503 tmp = functions_sorted [i];
8504 functions_sorted [i] = functions_sorted [i + 1];
8505 functions_sorted [i + 1] = tmp;
8506 tmp = symbols_sorted [i];
8507 symbols_sorted [i] = symbols_sorted [i + 1];
8508 symbols_sorted [i + 1] = tmp;
8515 func = mono_lookup_internal_call (m);
8518 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8522 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8524 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8525 g_assert_not_reached ();
8532 type_from_typename (char *type_name)
8534 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8536 if (!strcmp (type_name, "int"))
8537 klass = mono_defaults.int_class;
8538 else if (!strcmp (type_name, "ptr"))
8539 klass = mono_defaults.int_class;
8540 else if (!strcmp (type_name, "void"))
8541 klass = mono_defaults.void_class;
8542 else if (!strcmp (type_name, "int32"))
8543 klass = mono_defaults.int32_class;
8544 else if (!strcmp (type_name, "uint32"))
8545 klass = mono_defaults.uint32_class;
8546 else if (!strcmp (type_name, "int8"))
8547 klass = mono_defaults.sbyte_class;
8548 else if (!strcmp (type_name, "uint8"))
8549 klass = mono_defaults.byte_class;
8550 else if (!strcmp (type_name, "int16"))
8551 klass = mono_defaults.int16_class;
8552 else if (!strcmp (type_name, "uint16"))
8553 klass = mono_defaults.uint16_class;
8554 else if (!strcmp (type_name, "long"))
8555 klass = mono_defaults.int64_class;
8556 else if (!strcmp (type_name, "ulong"))
8557 klass = mono_defaults.uint64_class;
8558 else if (!strcmp (type_name, "float"))
8559 klass = mono_defaults.single_class;
8560 else if (!strcmp (type_name, "double"))
8561 klass = mono_defaults.double_class;
8562 else if (!strcmp (type_name, "object"))
8563 klass = mono_defaults.object_class;
8564 else if (!strcmp (type_name, "obj"))
8565 klass = mono_defaults.object_class;
8566 else if (!strcmp (type_name, "string"))
8567 klass = mono_defaults.string_class;
8568 else if (!strcmp (type_name, "bool"))
8569 klass = mono_defaults.boolean_class;
8570 else if (!strcmp (type_name, "boolean"))
8571 klass = mono_defaults.boolean_class;
8573 g_error ("%s", type_name);
8574 g_assert_not_reached ();
8576 return &klass->byval_arg;
8580 * LOCKING: Take the corlib image lock.
8582 MonoMethodSignature*
8583 mono_create_icall_signature (const char *sigstr)
8588 MonoMethodSignature *res, *res2;
8589 MonoImage *corlib = mono_defaults.corlib;
8591 mono_image_lock (corlib);
8592 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8593 mono_image_unlock (corlib);
8598 parts = g_strsplit (sigstr, " ", 256);
8607 res = mono_metadata_signature_alloc (corlib, len - 1);
8612 * Under windows, the default pinvoke calling convention is STDCALL but
8615 res->call_convention = MONO_CALL_C;
8618 res->ret = type_from_typename (parts [0]);
8619 for (i = 1; i < len; ++i) {
8620 res->params [i - 1] = type_from_typename (parts [i]);
8625 mono_image_lock (corlib);
8626 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8628 res = res2; /*Value is allocated in the image pool*/
8630 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8631 mono_image_unlock (corlib);
8637 mono_find_jit_icall_by_name (const char *name)
8639 MonoJitICallInfo *info;
8640 g_assert (jit_icall_hash_name);
8643 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8644 mono_icall_unlock ();
8649 mono_find_jit_icall_by_addr (gconstpointer addr)
8651 MonoJitICallInfo *info;
8652 g_assert (jit_icall_hash_addr);
8655 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8656 mono_icall_unlock ();
8662 * mono_get_jit_icall_info:
8664 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8665 * caller should access it while holding the icall lock.
8668 mono_get_jit_icall_info (void)
8670 return jit_icall_hash_name;
8674 * mono_lookup_jit_icall_symbol:
8676 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8679 mono_lookup_jit_icall_symbol (const char *name)
8681 MonoJitICallInfo *info;
8682 const char *res = NULL;
8685 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8687 res = info->c_symbol;
8688 mono_icall_unlock ();
8693 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8696 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8697 mono_icall_unlock ();
8701 * 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
8702 * icalls without wrappers in some cases.
8705 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8707 MonoJitICallInfo *info;
8714 if (!jit_icall_hash_name) {
8715 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8716 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8719 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8720 g_warning ("jit icall already defined \"%s\"\n", name);
8721 g_assert_not_reached ();
8724 info = g_new0 (MonoJitICallInfo, 1);
8729 info->c_symbol = c_symbol;
8730 info->no_raise = no_raise;
8733 info->wrapper = func;
8735 info->wrapper = NULL;
8738 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8739 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8741 mono_icall_unlock ();
8746 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8748 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);