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)
5106 return mono_method_body_get_object (mono_domain_get (), method);
5109 ICALL_EXPORT MonoReflectionAssembly*
5110 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5113 MonoReflectionAssembly *result;
5114 MonoMethod *dest = NULL;
5116 mono_stack_walk_no_il (get_executing, &dest);
5118 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5120 mono_error_set_pending_exception (&error);
5125 ICALL_EXPORT MonoReflectionAssembly*
5126 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5129 MonoReflectionAssembly *result;
5130 MonoDomain* domain = mono_domain_get ();
5132 if (!domain->entry_assembly)
5135 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5137 mono_error_set_pending_exception (&error);
5141 ICALL_EXPORT MonoReflectionAssembly*
5142 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5147 MonoReflectionAssembly *result;
5150 mono_stack_walk_no_il (get_executing, &dest);
5152 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5156 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5159 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5161 mono_error_set_pending_exception (&error);
5165 ICALL_EXPORT MonoString *
5166 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5167 gboolean assembly_qualified)
5169 MonoDomain *domain = mono_object_domain (object);
5170 MonoTypeNameFormat format;
5175 format = assembly_qualified ?
5176 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5177 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5179 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5181 name = mono_type_get_name_full (object->type, format);
5185 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5190 res = mono_string_new (domain, name);
5197 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5200 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5202 mono_class_init_checked (klass, &error);
5203 mono_error_raise_exception (&error);
5204 return mono_security_core_clr_class_level (klass);
5208 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5210 MonoClassField *field = rfield->field;
5211 return mono_security_core_clr_field_level (field, TRUE);
5215 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5217 MonoMethod *method = rfield->method;
5218 return mono_security_core_clr_method_level (method, TRUE);
5222 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)
5224 static MonoMethod *create_culture = NULL;
5228 const char *pkey_ptr;
5230 MonoBoolean assembly_ref = 0;
5232 mono_error_init (error);
5234 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5235 aname->major = name->major;
5236 aname->minor = name->minor;
5237 aname->build = name->build;
5238 aname->flags = name->flags;
5239 aname->revision = name->revision;
5240 aname->hashalg = name->hash_alg;
5241 aname->versioncompat = 1; /* SameMachine (default) */
5242 aname->processor_architecture = name->arch;
5244 if (by_default_version) {
5245 MonoObject *version;
5247 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5248 return_if_nok (error);
5250 MONO_OBJECT_SETREF (aname, version, version);
5254 if (absolute != NULL && *absolute != '\0') {
5255 const gchar *prepend = "file://";
5258 codebase = g_strdup (absolute);
5263 for (i = strlen (codebase) - 1; i >= 0; i--)
5264 if (codebase [i] == '\\')
5267 if (*codebase == '/' && *(codebase + 1) == '/') {
5270 prepend = "file:///";
5274 result = g_strconcat (prepend, codebase, NULL);
5280 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5284 if (!create_culture) {
5285 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5286 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5287 g_assert (create_culture);
5288 mono_method_desc_free (desc);
5291 if (name->culture) {
5292 args [0] = mono_string_new (domain, name->culture);
5293 args [1] = &assembly_ref;
5295 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5296 return_if_nok (error);
5298 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5301 if (name->public_key) {
5302 pkey_ptr = (char*)name->public_key;
5303 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5305 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5306 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5307 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5308 } else if (default_publickey) {
5309 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5310 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5313 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5314 if (name->public_key_token [0]) {
5318 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5319 p = mono_array_addr (aname->keyToken, char, 0);
5321 for (i = 0, j = 0; i < 8; i++) {
5322 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5323 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5326 } else if (default_token) {
5327 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5331 ICALL_EXPORT MonoString *
5332 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5334 MonoDomain *domain = mono_object_domain (assembly);
5335 MonoAssembly *mass = assembly->assembly;
5339 name = mono_stringify_assembly_name (&mass->aname);
5340 res = mono_string_new (domain, name);
5347 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5351 MonoAssembly *mass = assembly->assembly;
5353 if (g_path_is_absolute (mass->image->name)) {
5354 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5355 mono_error_set_pending_exception (&error);
5358 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5360 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5361 mono_error_set_pending_exception (&error);
5367 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5371 MonoImageOpenStatus status = MONO_IMAGE_OK;
5374 MonoAssemblyName name;
5377 filename = mono_string_to_utf8 (fname);
5379 dirname = g_path_get_dirname (filename);
5380 replace_shadow_path (mono_domain_get (), dirname, &filename);
5383 image = mono_image_open (filename, &status);
5389 if (status == MONO_IMAGE_IMAGE_INVALID)
5390 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5392 exc = mono_get_exception_file_not_found2 (NULL, fname);
5393 mono_set_pending_exception (exc);
5397 res = mono_assembly_fill_assembly_name (image, &name);
5399 mono_image_close (image);
5401 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5405 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5406 mono_error_set_pending_exception (&error);
5408 mono_image_close (image);
5412 ICALL_EXPORT MonoBoolean
5413 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5414 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5416 MonoBoolean result = FALSE;
5417 MonoDeclSecurityEntry entry;
5419 /* SecurityAction.RequestMinimum */
5420 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5421 *minimum = entry.blob;
5422 *minLength = entry.size;
5425 /* SecurityAction.RequestOptional */
5426 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5427 *optional = entry.blob;
5428 *optLength = entry.size;
5431 /* SecurityAction.RequestRefuse */
5432 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5433 *refused = entry.blob;
5434 *refLength = entry.size;
5442 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5444 guint32 attrs, visibility;
5446 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5447 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5448 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5451 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5457 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5459 MonoReflectionType *rt;
5462 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5465 mono_error_init (error);
5467 /* we start the count from 1 because we skip the special type <Module> */
5470 for (i = 1; i < tdef->rows; ++i) {
5471 if (mono_module_type_is_visible (tdef, image, i + 1))
5475 count = tdef->rows - 1;
5477 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5478 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5480 for (i = 1; i < tdef->rows; ++i) {
5481 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5482 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5483 mono_loader_assert_no_error (); /* Plug any leaks */
5484 mono_error_assert_ok (error);
5487 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5488 return_val_if_nok (error, NULL);
5490 mono_array_setref (res, count, rt);
5492 MonoException *ex = mono_error_convert_to_exception (error);
5493 mono_array_setref (*exceptions, count, ex);
5502 ICALL_EXPORT MonoArray*
5503 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5506 MonoArray *res = NULL;
5507 MonoArray *exceptions = NULL;
5508 MonoImage *image = NULL;
5509 MonoTableInfo *table = NULL;
5512 int i, len, ex_count;
5514 domain = mono_object_domain (assembly);
5516 g_assert (!assembly_is_dynamic (assembly->assembly));
5517 image = assembly->assembly->image;
5518 table = &image->tables [MONO_TABLE_FILE];
5519 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5520 mono_error_raise_exception (&error);
5522 /* Append data from all modules in the assembly */
5523 for (i = 0; i < table->rows; ++i) {
5524 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5525 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5530 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5531 mono_error_raise_exception (&error);
5533 /* Append the new types to the end of the array */
5534 if (mono_array_length (res2) > 0) {
5536 MonoArray *res3, *ex3;
5538 len1 = mono_array_length (res);
5539 len2 = mono_array_length (res2);
5541 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5542 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5543 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5546 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5547 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5548 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5555 /* the ReflectionTypeLoadException must have all the types (Types property),
5556 * NULL replacing types which throws an exception. The LoaderException must
5557 * contain all exceptions for NULL items.
5560 len = mono_array_length (res);
5563 for (i = 0; i < len; i++) {
5564 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5568 klass = mono_type_get_class (t->type);
5569 if ((klass != NULL) && mono_class_has_failure (klass)) {
5570 /* keep the class in the list */
5571 list = g_list_append (list, klass);
5572 /* and replace Type with NULL */
5573 mono_array_setref (res, i, NULL);
5580 if (list || ex_count) {
5582 MonoException *exc = NULL;
5583 MonoArray *exl = NULL;
5584 int j, length = g_list_length (list) + ex_count;
5586 mono_loader_clear_error ();
5588 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5589 /* Types for which mono_class_get_checked () succeeded */
5590 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5591 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5592 mono_array_setref (exl, i, exc);
5594 /* Types for which it don't */
5595 for (j = 0; j < mono_array_length (exceptions); ++j) {
5596 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5598 g_assert (i < length);
5599 mono_array_setref (exl, i, exc);
5606 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5607 if (!is_ok (&error)) {
5608 mono_error_set_pending_exception (&error);
5611 mono_loader_clear_error ();
5612 mono_set_pending_exception (exc);
5619 ICALL_EXPORT gboolean
5620 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5623 MonoAssemblyName aname;
5624 MonoDomain *domain = mono_object_domain (name);
5626 gboolean is_version_defined;
5627 gboolean is_token_defined;
5629 aname.public_key = NULL;
5630 val = mono_string_to_utf8 (assname);
5631 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5632 g_free ((guint8*) aname.public_key);
5637 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5638 mono_error_set_pending_exception (&error);
5640 mono_assembly_name_free (&aname);
5641 g_free ((guint8*) aname.public_key);
5647 ICALL_EXPORT MonoReflectionType*
5648 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5651 MonoReflectionType *ret;
5652 MonoDomain *domain = mono_object_domain (module);
5655 g_assert (module->image);
5657 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5658 /* These images do not have a global type */
5661 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5662 if (!mono_error_ok (&error)) {
5663 mono_error_set_pending_exception (&error);
5667 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5668 if (!mono_error_ok (&error)) {
5669 mono_error_set_pending_exception (&error);
5677 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5679 /*if (module->image)
5680 mono_image_close (module->image);*/
5683 ICALL_EXPORT MonoString*
5684 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5686 MonoDomain *domain = mono_object_domain (module);
5688 g_assert (module->image);
5689 return mono_string_new (domain, module->image->guid);
5692 ICALL_EXPORT gpointer
5693 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5696 if (module->image && module->image->is_module_handle)
5697 return module->image->raw_data;
5700 return (gpointer) (-1);
5704 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5706 if (image_is_dynamic (image)) {
5707 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5708 *pe_kind = dyn->pe_kind;
5709 *machine = dyn->machine;
5712 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5713 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5718 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5720 return (image->md_version_major << 16) | (image->md_version_minor);
5723 ICALL_EXPORT MonoArray*
5724 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5727 MonoArray *exceptions;
5731 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5735 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5736 mono_error_raise_exception (&error);
5738 for (i = 0; i < mono_array_length (exceptions); ++i) {
5739 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5741 mono_set_pending_exception (ex);
5750 mono_memberref_is_method (MonoImage *image, guint32 token)
5752 if (!image_is_dynamic (image)) {
5753 guint32 cols [MONO_MEMBERREF_SIZE];
5755 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5756 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5757 mono_metadata_decode_blob_size (sig, &sig);
5758 return (*sig != 0x6);
5760 MonoClass *handle_class;
5762 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5765 return mono_defaults.methodhandle_class == handle_class;
5770 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5773 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5774 mono_array_addr (type_args, MonoType*, 0));
5776 context->class_inst = NULL;
5778 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5779 mono_array_addr (method_args, MonoType*, 0));
5781 context->method_inst = NULL;
5784 ICALL_EXPORT MonoType*
5785 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5788 int table = mono_metadata_token_table (token);
5789 int index = mono_metadata_token_index (token);
5790 MonoGenericContext context;
5793 *resolve_error = ResolveTokenError_Other;
5795 /* Validate token */
5796 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5797 (table != MONO_TABLE_TYPESPEC)) {
5798 *resolve_error = ResolveTokenError_BadTable;
5802 if (image_is_dynamic (image)) {
5803 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5804 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5805 return klass ? &klass->byval_arg : NULL;
5808 init_generic_context_from_args (&context, type_args, method_args);
5809 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5810 return klass ? &klass->byval_arg : NULL;
5813 if ((index <= 0) || (index > image->tables [table].rows)) {
5814 *resolve_error = ResolveTokenError_OutOfRange;
5818 init_generic_context_from_args (&context, type_args, method_args);
5819 klass = mono_class_get_checked (image, token, &error);
5821 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5822 if (!mono_error_ok (&error)) {
5823 mono_error_set_pending_exception (&error);
5828 return &klass->byval_arg;
5833 ICALL_EXPORT MonoMethod*
5834 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5837 int table = mono_metadata_token_table (token);
5838 int index = mono_metadata_token_index (token);
5839 MonoGenericContext context;
5842 *resolve_error = ResolveTokenError_Other;
5844 /* Validate token */
5845 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5846 (table != MONO_TABLE_MEMBERREF)) {
5847 *resolve_error = ResolveTokenError_BadTable;
5851 if (image_is_dynamic (image)) {
5852 if (table == MONO_TABLE_METHOD)
5853 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5855 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5856 *resolve_error = ResolveTokenError_BadTable;
5860 init_generic_context_from_args (&context, type_args, method_args);
5861 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5864 if ((index <= 0) || (index > image->tables [table].rows)) {
5865 *resolve_error = ResolveTokenError_OutOfRange;
5868 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5869 *resolve_error = ResolveTokenError_BadTable;
5873 init_generic_context_from_args (&context, type_args, method_args);
5874 method = mono_get_method_checked (image, token, NULL, &context, &error);
5875 mono_error_set_pending_exception (&error);
5880 ICALL_EXPORT MonoString*
5881 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5883 int index = mono_metadata_token_index (token);
5885 *error = ResolveTokenError_Other;
5887 /* Validate token */
5888 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5889 *error = ResolveTokenError_BadTable;
5893 if (image_is_dynamic (image))
5894 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5896 if ((index <= 0) || (index >= image->heap_us.size)) {
5897 *error = ResolveTokenError_OutOfRange;
5901 /* FIXME: What to do if the index points into the middle of a string ? */
5903 return mono_ldstr (mono_domain_get (), image, index);
5906 ICALL_EXPORT MonoClassField*
5907 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5911 int table = mono_metadata_token_table (token);
5912 int index = mono_metadata_token_index (token);
5913 MonoGenericContext context;
5914 MonoClassField *field;
5916 *resolve_error = ResolveTokenError_Other;
5918 /* Validate token */
5919 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5920 *resolve_error = ResolveTokenError_BadTable;
5924 if (image_is_dynamic (image)) {
5925 if (table == MONO_TABLE_FIELD)
5926 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5928 if (mono_memberref_is_method (image, token)) {
5929 *resolve_error = ResolveTokenError_BadTable;
5933 init_generic_context_from_args (&context, type_args, method_args);
5934 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5937 if ((index <= 0) || (index > image->tables [table].rows)) {
5938 *resolve_error = ResolveTokenError_OutOfRange;
5941 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5942 *resolve_error = ResolveTokenError_BadTable;
5946 init_generic_context_from_args (&context, type_args, method_args);
5947 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5948 mono_error_set_pending_exception (&error);
5954 ICALL_EXPORT MonoObject*
5955 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5959 int table = mono_metadata_token_table (token);
5961 *error = ResolveTokenError_Other;
5964 case MONO_TABLE_TYPEDEF:
5965 case MONO_TABLE_TYPEREF:
5966 case MONO_TABLE_TYPESPEC: {
5967 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5969 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
5970 mono_error_raise_exception (&merror);
5977 case MONO_TABLE_METHOD:
5978 case MONO_TABLE_METHODSPEC: {
5979 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5981 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
5982 mono_error_raise_exception (&merror);
5988 case MONO_TABLE_FIELD: {
5989 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5991 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
5992 mono_error_raise_exception (&merror);
5998 case MONO_TABLE_MEMBERREF:
5999 if (mono_memberref_is_method (image, token)) {
6000 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6002 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6003 mono_error_raise_exception (&merror);
6010 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6012 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6013 mono_error_raise_exception (&merror);
6022 *error = ResolveTokenError_BadTable;
6028 ICALL_EXPORT MonoArray*
6029 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6031 int table = mono_metadata_token_table (token);
6032 int idx = mono_metadata_token_index (token);
6033 MonoTableInfo *tables = image->tables;
6038 *error = ResolveTokenError_OutOfRange;
6040 /* FIXME: Support other tables ? */
6041 if (table != MONO_TABLE_STANDALONESIG)
6044 if (image_is_dynamic (image))
6047 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6050 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6052 ptr = mono_metadata_blob_heap (image, sig);
6053 len = mono_metadata_decode_blob_size (ptr, &ptr);
6055 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6056 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6060 ICALL_EXPORT MonoReflectionType*
6061 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6064 MonoReflectionType *ret;
6066 int isbyref = 0, rank;
6067 char *str = mono_string_to_utf8 (smodifiers);
6070 klass = mono_class_from_mono_type (tb->type.type);
6072 /* logic taken from mono_reflection_parse_type(): keep in sync */
6076 if (isbyref) { /* only one level allowed by the spec */
6085 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6086 mono_error_raise_exception (&error);
6090 klass = mono_ptr_class_get (&klass->byval_arg);
6091 mono_class_init (klass);
6102 else if (*p != '*') { /* '*' means unknown lower bound */
6113 klass = mono_array_class_get (klass, rank);
6114 mono_class_init (klass);
6123 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6124 mono_error_raise_exception (&error);
6129 ICALL_EXPORT MonoBoolean
6130 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6136 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6142 check_for_invalid_type (MonoClass *klass, MonoError *error)
6147 mono_error_init (error);
6149 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6152 name = mono_type_get_full_name (klass);
6153 str = mono_string_new (mono_domain_get (), name);
6155 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6158 ICALL_EXPORT MonoReflectionType *
6159 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6162 MonoReflectionType *ret;
6163 MonoClass *klass, *aklass;
6165 klass = mono_class_from_mono_type (type->type);
6166 check_for_invalid_type (klass, &error);
6167 mono_error_raise_exception (&error);
6169 if (rank == 0) //single dimentional array
6170 aklass = mono_array_class_get (klass, 1);
6172 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6174 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6175 mono_error_raise_exception (&error);
6180 ICALL_EXPORT MonoReflectionType *
6181 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6184 MonoReflectionType *ret;
6187 klass = mono_class_from_mono_type (type->type);
6188 mono_class_init_checked (klass, &error);
6189 mono_error_raise_exception (&error);
6190 check_for_invalid_type (klass, &error);
6191 mono_error_raise_exception (&error);
6193 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6194 mono_error_raise_exception (&error);
6199 ICALL_EXPORT MonoReflectionType *
6200 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6203 MonoReflectionType *ret;
6204 MonoClass *klass, *pklass;
6206 klass = mono_class_from_mono_type (type->type);
6207 mono_class_init_checked (klass, &error);
6208 mono_error_raise_exception (&error);
6209 check_for_invalid_type (klass, &error);
6210 mono_error_raise_exception (&error);
6212 pklass = mono_ptr_class_get (type->type);
6214 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6215 mono_error_raise_exception (&error);
6220 ICALL_EXPORT MonoObject *
6221 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6222 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6225 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6226 MonoObject *delegate;
6228 MonoMethod *method = info->method;
6230 mono_class_init_checked (delegate_class, &error);
6231 mono_error_raise_exception (&error);
6233 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6235 if (mono_security_core_clr_enabled ()) {
6236 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6240 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6241 mono_error_raise_exception (&error);
6243 if (method_is_dynamic (method)) {
6244 /* Creating a trampoline would leak memory */
6245 func = mono_compile_method (method);
6247 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6248 method = mono_object_get_virtual_method (target, method);
6249 func = mono_create_ftnptr (mono_domain_get (),
6250 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6253 mono_delegate_ctor_with_method (delegate, target, func, method);
6258 ICALL_EXPORT MonoMulticastDelegate *
6259 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6262 MonoMulticastDelegate *ret;
6264 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6266 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6267 mono_error_raise_exception (&error);
6268 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6273 ICALL_EXPORT MonoReflectionMethod*
6274 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6276 MonoReflectionMethod *ret = NULL;
6278 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6279 mono_error_raise_exception (&error);
6285 static inline gint32
6286 mono_array_get_byte_length (MonoArray *array)
6292 klass = array->obj.vtable->klass;
6294 if (array->bounds == NULL)
6295 length = array->max_length;
6298 for (i = 0; i < klass->rank; ++ i)
6299 length *= array->bounds [i].length;
6302 switch (klass->element_class->byval_arg.type) {
6305 case MONO_TYPE_BOOLEAN:
6309 case MONO_TYPE_CHAR:
6317 return length * sizeof (gpointer);
6328 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6330 return mono_array_get_byte_length (array);
6334 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6336 return mono_array_get (array, gint8, idx);
6340 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6342 mono_array_set (array, gint8, idx, value);
6345 ICALL_EXPORT MonoBoolean
6346 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6348 guint8 *src_buf, *dest_buf;
6351 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6355 g_assert (count >= 0);
6357 /* This is called directly from the class libraries without going through the managed wrapper */
6358 MONO_CHECK_ARG_NULL (src, FALSE);
6359 MONO_CHECK_ARG_NULL (dest, FALSE);
6361 /* watch out for integer overflow */
6362 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6365 src_buf = (guint8 *)src->vector + src_offset;
6366 dest_buf = (guint8 *)dest->vector + dest_offset;
6369 memcpy (dest_buf, src_buf, count);
6371 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6376 #ifndef DISABLE_REMOTING
6377 ICALL_EXPORT MonoObject *
6378 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6381 MonoDomain *domain = mono_object_domain (this_obj);
6383 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6384 MonoTransparentProxy *tp;
6388 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6389 mono_error_raise_exception (&error);
6390 tp = (MonoTransparentProxy*) res;
6392 MONO_OBJECT_SETREF (tp, rp, rp);
6393 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6394 klass = mono_class_from_mono_type (type);
6396 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6397 mono_class_setup_vtable (klass);
6398 if (mono_class_has_failure (klass)) {
6399 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6403 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6404 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6405 if (!is_ok (&error)) {
6406 mono_error_set_pending_exception (&error);
6410 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6414 ICALL_EXPORT MonoReflectionType *
6415 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6418 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6419 mono_error_raise_exception (&error);
6425 /* System.Environment */
6428 ves_icall_System_Environment_get_UserName (void)
6430 /* using glib is more portable */
6431 return mono_string_new (mono_domain_get (), g_get_user_name ());
6435 ICALL_EXPORT MonoString *
6436 ves_icall_System_Environment_get_MachineName (void)
6438 #if defined (HOST_WIN32)
6443 len = MAX_COMPUTERNAME_LENGTH + 1;
6444 buf = g_new (gunichar2, len);
6447 if (GetComputerName (buf, (PDWORD) &len)) {
6449 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6450 mono_error_raise_exception (&error);
6455 #elif !defined(DISABLE_SOCKETS)
6459 #if defined _SC_HOST_NAME_MAX
6460 n = sysconf (_SC_HOST_NAME_MAX);
6464 buf = g_malloc (n+1);
6466 if (gethostname (buf, n) == 0){
6468 result = mono_string_new (mono_domain_get (), buf);
6475 return mono_string_new (mono_domain_get (), "mono");
6480 ves_icall_System_Environment_get_Platform (void)
6482 #if defined (TARGET_WIN32)
6485 #elif defined(__MACH__)
6488 // Notice that the value is hidden from user code, and only exposed
6489 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6490 // define and making assumptions based on Unix/128/4 values before there
6491 // was a MacOS define. Lots of code would assume that not-Unix meant
6492 // Windows, but in this case, it would be OSX.
6501 ICALL_EXPORT MonoString *
6502 ves_icall_System_Environment_get_NewLine (void)
6504 #if defined (HOST_WIN32)
6505 return mono_string_new (mono_domain_get (), "\r\n");
6507 return mono_string_new (mono_domain_get (), "\n");
6511 ICALL_EXPORT MonoBoolean
6512 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6514 #if SIZEOF_VOID_P == 8
6518 gboolean isWow64Process = FALSE;
6519 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6520 return (MonoBoolean)isWow64Process;
6522 #elif defined(HAVE_SYS_UTSNAME_H)
6523 struct utsname name;
6525 if (uname (&name) >= 0) {
6526 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6533 ICALL_EXPORT MonoString *
6534 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6542 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6543 value = g_getenv (utf8_name);
6550 return mono_string_new (mono_domain_get (), value);
6554 * There is no standard way to get at environ.
6557 #ifndef __MINGW32_VERSION
6558 #if defined(__APPLE__)
6559 #if defined (TARGET_OSX)
6560 /* Apple defines this in crt_externs.h but doesn't provide that header for
6561 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6562 * in fact exist on all implementations (so far)
6564 gchar ***_NSGetEnviron(void);
6565 #define environ (*_NSGetEnviron())
6567 static char *mono_environ[1] = { NULL };
6568 #define environ mono_environ
6569 #endif /* defined (TARGET_OSX) */
6577 ICALL_EXPORT MonoArray *
6578 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6589 env_strings = GetEnvironmentStrings();
6592 env_string = env_strings;
6593 while (*env_string != '\0') {
6594 /* weird case that MS seems to skip */
6595 if (*env_string != '=')
6597 while (*env_string != '\0')
6603 domain = mono_domain_get ();
6604 names = mono_array_new (domain, mono_defaults.string_class, n);
6608 env_string = env_strings;
6609 while (*env_string != '\0') {
6610 /* weird case that MS seems to skip */
6611 if (*env_string != '=') {
6612 equal_str = wcschr(env_string, '=');
6613 g_assert(equal_str);
6615 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6616 mono_error_raise_exception (&error);
6617 mono_array_setref (names, n, str);
6620 while (*env_string != '\0')
6625 FreeEnvironmentStrings (env_strings);
6638 for (e = environ; *e != 0; ++ e)
6641 domain = mono_domain_get ();
6642 names = mono_array_new (domain, mono_defaults.string_class, n);
6645 for (e = environ; *e != 0; ++ e) {
6646 parts = g_strsplit (*e, "=", 2);
6648 str = mono_string_new (domain, *parts);
6649 mono_array_setref (names, n, str);
6662 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6664 #if !GLIB_CHECK_VERSION(2,4,0)
6665 #define g_setenv(a,b,c) setenv(a,b,c)
6666 #define g_unsetenv(a) unsetenv(a)
6670 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6673 gunichar2 *utf16_name, *utf16_value;
6675 gchar *utf8_name, *utf8_value;
6680 utf16_name = mono_string_to_utf16 (name);
6681 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6682 SetEnvironmentVariable (utf16_name, NULL);
6683 g_free (utf16_name);
6687 utf16_value = mono_string_to_utf16 (value);
6689 SetEnvironmentVariable (utf16_name, utf16_value);
6691 g_free (utf16_name);
6692 g_free (utf16_value);
6694 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6696 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6697 g_unsetenv (utf8_name);
6702 utf8_value = mono_string_to_utf8_checked (value, &error);
6703 if (!mono_error_ok (&error)) {
6705 mono_error_set_pending_exception (&error);
6708 g_setenv (utf8_name, utf8_value, TRUE);
6711 g_free (utf8_value);
6716 ves_icall_System_Environment_Exit (int result)
6718 mono_environment_exitcode_set (result);
6720 /* FIXME: There are some cleanup hangs that should be worked out, but
6721 * if the program is going to exit, everything will be cleaned up when
6722 * NaCl exits anyway.
6724 #ifndef __native_client__
6725 if (!mono_runtime_try_shutdown ())
6726 mono_thread_exit ();
6728 /* Suspend all managed threads since the runtime is going away */
6729 mono_thread_suspend_all_other_threads ();
6731 mono_runtime_quit ();
6734 /* we may need to do some cleanup here... */
6738 ICALL_EXPORT MonoString*
6739 ves_icall_System_Environment_GetGacPath (void)
6741 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6744 ICALL_EXPORT MonoString*
6745 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6747 #if defined (HOST_WIN32)
6748 #ifndef CSIDL_FLAG_CREATE
6749 #define CSIDL_FLAG_CREATE 0x8000
6752 WCHAR path [MAX_PATH];
6753 /* Create directory if no existing */
6754 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6759 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6760 mono_error_raise_exception (&error);
6764 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6766 return mono_string_new (mono_domain_get (), "");
6769 ICALL_EXPORT MonoArray *
6770 ves_icall_System_Environment_GetLogicalDrives (void)
6773 gunichar2 buf [256], *ptr, *dname;
6775 guint initial_size = 127, size = 128;
6778 MonoString *drivestr;
6779 MonoDomain *domain = mono_domain_get ();
6785 while (size > initial_size) {
6786 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6787 if (size > initial_size) {
6790 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6791 initial_size = size;
6805 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6810 while (*u16) { u16++; len ++; }
6811 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6812 mono_error_raise_exception (&error);
6813 mono_array_setref (result, ndrives++, drivestr);
6823 ICALL_EXPORT MonoString *
6824 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6826 gunichar2 volume_name [MAX_PATH + 1];
6828 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6830 return mono_string_from_utf16 (volume_name);
6833 ICALL_EXPORT MonoString *
6834 ves_icall_System_Environment_InternalGetHome (void)
6836 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6839 static const char *encodings [] = {
6841 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6842 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6843 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6845 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6846 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6847 "x_unicode_2_0_utf_7",
6849 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6850 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6852 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6855 "unicodefffe", "utf_16be",
6862 * Returns the internal codepage, if the value of "int_code_page" is
6863 * 1 at entry, and we can not compute a suitable code page number,
6864 * returns the code page as a string
6866 ICALL_EXPORT MonoString*
6867 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6872 char *codepage = NULL;
6874 int want_name = *int_code_page;
6877 *int_code_page = -1;
6879 g_get_charset (&cset);
6880 c = codepage = strdup (cset);
6881 for (c = codepage; *c; c++){
6882 if (isascii (*c) && isalpha (*c))
6887 /* g_print ("charset: %s\n", cset); */
6889 /* handle some common aliases */
6892 for (i = 0; p != 0; ){
6895 p = encodings [++i];
6898 if (strcmp (p, codepage) == 0){
6899 *int_code_page = code;
6902 p = encodings [++i];
6905 if (strstr (codepage, "utf_8") != NULL)
6906 *int_code_page |= 0x10000000;
6909 if (want_name && *int_code_page == -1)
6910 return mono_string_new (mono_domain_get (), cset);
6915 ICALL_EXPORT MonoBoolean
6916 ves_icall_System_Environment_get_HasShutdownStarted (void)
6918 if (mono_runtime_is_shutting_down ())
6921 if (mono_domain_is_unloading (mono_domain_get ()))
6928 ves_icall_System_Environment_BroadcastSettingChange (void)
6931 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6936 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6942 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6943 MonoReflectionMethod *method,
6944 MonoArray *out_args)
6946 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6949 #ifndef DISABLE_REMOTING
6950 ICALL_EXPORT MonoBoolean
6951 ves_icall_IsTransparentProxy (MonoObject *proxy)
6956 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6962 ICALL_EXPORT MonoReflectionMethod *
6963 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6964 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6966 MonoReflectionMethod *ret = NULL;
6971 MonoMethod **vtable;
6972 MonoMethod *res = NULL;
6974 MONO_CHECK_ARG_NULL (rtype, NULL);
6975 MONO_CHECK_ARG_NULL (rmethod, NULL);
6977 method = rmethod->method;
6978 klass = mono_class_from_mono_type (rtype->type);
6979 mono_class_init_checked (klass, &error);
6980 mono_error_raise_exception (&error);
6982 if (MONO_CLASS_IS_INTERFACE (klass))
6985 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6988 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6989 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6995 mono_class_setup_vtable (klass);
6996 vtable = klass->vtable;
6998 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6999 gboolean variance_used = FALSE;
7000 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7001 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7003 res = vtable [offs + method->slot];
7005 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7008 if (method->slot != -1)
7009 res = vtable [method->slot];
7015 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7016 mono_error_raise_exception (&error);
7021 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7027 klass = mono_class_from_mono_type (type->type);
7028 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7029 if (!is_ok (&error)) {
7030 mono_error_set_pending_exception (&error);
7034 mono_vtable_set_is_remote (vtable, enable);
7037 #else /* DISABLE_REMOTING */
7040 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7042 g_assert_not_reached ();
7047 ICALL_EXPORT MonoObject *
7048 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7055 domain = mono_object_domain (type);
7056 klass = mono_class_from_mono_type (type->type);
7057 mono_class_init_checked (klass, &error);
7058 mono_error_raise_exception (&error);
7060 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7061 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7065 if (klass->rank >= 1) {
7066 g_assert (klass->rank == 1);
7067 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7069 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7070 if (!is_ok (&error)) {
7071 mono_error_set_pending_exception (&error);
7074 /* Bypass remoting object creation check */
7075 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7076 mono_error_set_pending_exception (&error);
7082 ICALL_EXPORT MonoString *
7083 ves_icall_System_IO_get_temp_path (void)
7085 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7088 #ifndef PLATFORM_NO_DRIVEINFO
7089 ICALL_EXPORT MonoBoolean
7090 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7091 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7095 ULARGE_INTEGER wapi_free_bytes_avail;
7096 ULARGE_INTEGER wapi_total_number_of_bytes;
7097 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7099 *error = ERROR_SUCCESS;
7100 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7101 &wapi_total_number_of_free_bytes);
7104 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7105 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7106 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7108 *free_bytes_avail = 0;
7109 *total_number_of_bytes = 0;
7110 *total_number_of_free_bytes = 0;
7111 *error = GetLastError ();
7117 ICALL_EXPORT guint32
7118 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7120 return GetDriveType (mono_string_chars (root_path_name));
7124 ICALL_EXPORT gpointer
7125 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7127 return mono_compile_method (method);
7130 ICALL_EXPORT MonoString *
7131 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7136 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7138 #if defined (HOST_WIN32)
7139 /* Avoid mixing '/' and '\\' */
7142 for (i = strlen (path) - 1; i >= 0; i--)
7143 if (path [i] == '/')
7147 mcpath = mono_string_new (mono_domain_get (), path);
7154 get_bundled_app_config (void)
7156 const gchar *app_config;
7159 gchar *config_file_name, *config_file_path;
7160 gsize len, config_file_path_length, config_ext_length;
7163 domain = mono_domain_get ();
7164 file = domain->setup->configuration_file;
7165 if (!file || file->length == 0)
7168 // Retrieve config file and remove the extension
7169 config_file_name = mono_string_to_utf8 (file);
7170 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7171 if (!config_file_path)
7172 config_file_path = config_file_name;
7174 config_file_path_length = strlen (config_file_path);
7175 config_ext_length = strlen (".config");
7176 if (config_file_path_length <= config_ext_length)
7179 len = config_file_path_length - config_ext_length;
7180 module = (gchar *)g_malloc0 (len + 1);
7181 memcpy (module, config_file_path, len);
7182 // Get the config file from the module name
7183 app_config = mono_config_string_for_assembly_file (module);
7186 if (config_file_name != config_file_path)
7187 g_free (config_file_name);
7188 g_free (config_file_path);
7193 return mono_string_new (mono_domain_get (), app_config);
7197 get_bundled_machine_config (void)
7199 const gchar *machine_config;
7201 machine_config = mono_get_machine_config ();
7203 if (!machine_config)
7206 return mono_string_new (mono_domain_get (), machine_config);
7209 ICALL_EXPORT MonoString *
7210 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7215 path = g_path_get_dirname (mono_get_config_dir ());
7217 #if defined (HOST_WIN32)
7218 /* Avoid mixing '/' and '\\' */
7221 for (i = strlen (path) - 1; i >= 0; i--)
7222 if (path [i] == '/')
7226 ipath = mono_string_new (mono_domain_get (), path);
7232 ICALL_EXPORT gboolean
7233 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7235 MonoPEResourceDataEntry *entry;
7238 if (!assembly || !result || !size)
7243 image = assembly->assembly->image;
7244 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7248 *result = mono_image_rva_map (image, entry->rde_data_offset);
7253 *size = entry->rde_size;
7258 ICALL_EXPORT MonoBoolean
7259 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7261 return mono_is_debugger_attached ();
7264 ICALL_EXPORT MonoBoolean
7265 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7267 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7268 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7274 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7276 if (mono_get_runtime_callbacks ()->debug_log)
7277 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7281 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7283 #if defined (HOST_WIN32)
7284 OutputDebugString (mono_string_chars (message));
7286 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7290 /* Only used for value types */
7291 ICALL_EXPORT MonoObject *
7292 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7299 domain = mono_object_domain (type);
7300 klass = mono_class_from_mono_type (type->type);
7301 mono_class_init_checked (klass, &error);
7302 mono_error_raise_exception (&error);
7304 if (mono_class_is_nullable (klass))
7305 /* No arguments -> null */
7308 result = mono_object_new_checked (domain, klass, &error);
7309 mono_error_raise_exception (&error);
7313 ICALL_EXPORT MonoReflectionMethod *
7314 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7316 MonoReflectionMethod *ret = NULL;
7319 MonoClass *klass, *parent;
7320 MonoGenericContext *generic_inst = NULL;
7321 MonoMethod *method = m->method;
7322 MonoMethod *result = NULL;
7325 if (method->klass == NULL)
7328 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7329 MONO_CLASS_IS_INTERFACE (method->klass) ||
7330 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7333 slot = mono_method_get_vtable_slot (method);
7337 klass = method->klass;
7338 if (klass->generic_class) {
7339 generic_inst = mono_class_get_context (klass);
7340 klass = klass->generic_class->container_class;
7344 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7345 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7346 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7347 or klass is the generic container class and generic_inst is the instantiation.
7349 when we go to the parent, if the parent is an open constructed type, we need to
7350 replace the type parameters by the definitions from the generic_inst, and then take it
7351 apart again into the klass and the generic_inst.
7353 For cases like this:
7354 class C<T> : B<T, int> {
7355 public override void Foo () { ... }
7357 class B<U,V> : A<HashMap<U,V>> {
7358 public override void Foo () { ... }
7361 public virtual void Foo () { ... }
7364 if at each iteration the parent isn't open, we can skip inflating it. if at some
7365 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7368 MonoGenericContext *parent_inst = NULL;
7369 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7371 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7372 if (!mono_error_ok (&error)) {
7373 mono_error_set_pending_exception (&error);
7377 if (parent->generic_class) {
7378 parent_inst = mono_class_get_context (parent);
7379 parent = parent->generic_class->container_class;
7382 mono_class_setup_vtable (parent);
7383 if (parent->vtable_size <= slot)
7386 generic_inst = parent_inst;
7389 klass = klass->parent;
7392 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7393 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7394 if (!mono_error_ok (&error)) {
7395 mono_error_set_pending_exception (&error);
7399 generic_inst = NULL;
7401 if (klass->generic_class) {
7402 generic_inst = mono_class_get_context (klass);
7403 klass = klass->generic_class->container_class;
7409 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7410 if (!mono_error_ok (&error)) {
7411 mono_error_set_pending_exception (&error);
7416 if (klass == method->klass)
7419 /*This is possible if definition == FALSE.
7420 * Do it here to be really sure we don't read invalid memory.
7422 if (slot >= klass->vtable_size)
7425 mono_class_setup_vtable (klass);
7427 result = klass->vtable [slot];
7428 if (result == NULL) {
7429 /* It is an abstract method */
7430 gpointer iter = NULL;
7431 while ((result = mono_class_get_methods (klass, &iter)))
7432 if (result->slot == slot)
7439 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7440 mono_error_raise_exception (&error);
7444 ICALL_EXPORT MonoString*
7445 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7447 MonoMethod *method = m->method;
7449 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7454 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7456 iter->sig = *(MonoMethodSignature**)argsp;
7458 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7459 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7462 /* FIXME: it's not documented what start is exactly... */
7466 iter->args = argsp + sizeof (gpointer);
7468 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7470 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7473 ICALL_EXPORT MonoTypedRef
7474 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7476 guint32 i, arg_size;
7480 i = iter->sig->sentinelpos + iter->next_arg;
7482 g_assert (i < iter->sig->param_count);
7484 res.type = iter->sig->params [i];
7485 res.klass = mono_class_from_mono_type (res.type);
7486 arg_size = mono_type_stack_size (res.type, &align);
7487 #if defined(__arm__) || defined(__mips__)
7488 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7490 res.value = iter->args;
7491 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7492 /* Values are stored as 8 byte register sized objects, but 'value'
7493 * is dereferenced as a pointer in other routines.
7495 res.value = (char*)res.value + 4;
7497 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7498 if (arg_size <= sizeof (gpointer)) {
7500 int padding = arg_size - mono_type_size (res.type, &dummy);
7501 res.value = (guint8*)res.value + padding;
7504 iter->args = (char*)iter->args + arg_size;
7507 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7512 ICALL_EXPORT MonoTypedRef
7513 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7515 guint32 i, arg_size;
7519 i = iter->sig->sentinelpos + iter->next_arg;
7521 g_assert (i < iter->sig->param_count);
7523 while (i < iter->sig->param_count) {
7524 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7526 res.type = iter->sig->params [i];
7527 res.klass = mono_class_from_mono_type (res.type);
7528 /* FIXME: endianess issue... */
7529 arg_size = mono_type_stack_size (res.type, &align);
7530 #if defined(__arm__) || defined(__mips__)
7531 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7533 res.value = iter->args;
7534 iter->args = (char*)iter->args + arg_size;
7536 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7539 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7547 ICALL_EXPORT MonoType*
7548 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7552 i = iter->sig->sentinelpos + iter->next_arg;
7554 g_assert (i < iter->sig->param_count);
7556 return iter->sig->params [i];
7559 ICALL_EXPORT MonoObject*
7560 mono_TypedReference_ToObject (MonoTypedRef* tref)
7562 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7563 MonoObject** objp = (MonoObject **)tref->value;
7567 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7570 ICALL_EXPORT MonoTypedRef
7571 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7574 MonoReflectionField *f;
7576 MonoType *ftype = NULL;
7580 memset (&res, 0, sizeof (res));
7583 g_assert (mono_array_length (fields) > 0);
7585 klass = target->vtable->klass;
7587 for (i = 0; i < mono_array_length (fields); ++i) {
7588 f = mono_array_get (fields, MonoReflectionField*, i);
7590 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7593 if (f->field->parent != klass) {
7594 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7598 p = (guint8*)target + f->field->offset;
7600 p += f->field->offset - sizeof (MonoObject);
7601 klass = mono_class_from_mono_type (f->field->type);
7602 ftype = f->field->type;
7606 res.klass = mono_class_from_mono_type (ftype);
7613 prelink_method (MonoMethod *method, MonoError *error)
7615 const char *exc_class, *exc_arg;
7617 mono_error_init (error);
7618 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7620 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7622 mono_error_set_exception_instance (error,
7623 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7626 /* create the wrapper, too? */
7630 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7634 prelink_method (method->method, &error);
7635 mono_error_raise_exception (&error);
7639 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7642 MonoClass *klass = mono_class_from_mono_type (type->type);
7644 gpointer iter = NULL;
7646 mono_class_init_checked (klass, &error);
7647 mono_error_raise_exception (&error);
7649 while ((m = mono_class_get_methods (klass, &iter))) {
7650 prelink_method (m, &error);
7651 mono_error_raise_exception (&error);
7655 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7657 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7658 gint32 const **exponents,
7659 gunichar2 const **digitLowerTable,
7660 gunichar2 const **digitUpperTable,
7661 gint64 const **tenPowersList,
7662 gint32 const **decHexDigits)
7664 *mantissas = Formatter_MantissaBitsTable;
7665 *exponents = Formatter_TensExponentTable;
7666 *digitLowerTable = Formatter_DigitLowerTable;
7667 *digitUpperTable = Formatter_DigitUpperTable;
7668 *tenPowersList = Formatter_TenPowersList;
7669 *decHexDigits = Formatter_DecHexDigits;
7673 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7674 * and avoid useless allocations.
7677 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7679 MonoReflectionType *rt;
7683 mono_error_init (error);
7684 for (i = 0; i < type->num_mods; ++i) {
7685 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7690 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7692 for (i = 0; i < type->num_mods; ++i) {
7693 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7694 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7695 return_val_if_nok (error, NULL);
7697 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7698 return_val_if_nok (error, NULL);
7700 mono_array_setref (res, count, rt);
7707 ICALL_EXPORT MonoArray*
7708 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7711 MonoType *type = param->ClassImpl->type;
7712 MonoClass *member_class = mono_object_class (param->MemberImpl);
7713 MonoMethod *method = NULL;
7716 MonoMethodSignature *sig;
7719 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7720 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7721 method = rmethod->method;
7722 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7723 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7724 if (!(method = prop->property->get))
7725 method = prop->property->set;
7728 char *type_name = mono_type_get_full_name (member_class);
7729 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7730 MonoException *ex = mono_get_exception_not_supported (msg);
7733 mono_set_pending_exception (ex);
7737 image = method->klass->image;
7738 pos = param->PositionImpl;
7739 sig = mono_method_signature (method);
7743 type = sig->params [pos];
7745 res = type_array_from_modifiers (image, type, optional, &error);
7746 mono_error_raise_exception (&error);
7751 get_property_type (MonoProperty *prop)
7753 MonoMethodSignature *sig;
7755 sig = mono_method_signature (prop->get);
7757 } else if (prop->set) {
7758 sig = mono_method_signature (prop->set);
7759 return sig->params [sig->param_count - 1];
7764 ICALL_EXPORT MonoArray*
7765 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7768 MonoType *type = get_property_type (property->property);
7769 MonoImage *image = property->klass->image;
7774 res = type_array_from_modifiers (image, type, optional, &error);
7775 mono_error_raise_exception (&error);
7780 *Construct a MonoType suited to be used to decode a constant blob object.
7782 * @type is the target type which will be constructed
7783 * @blob_type is the blob type, for example, that comes from the constant table
7784 * @real_type is the expected constructed type.
7787 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7789 type->type = blob_type;
7790 type->data.klass = NULL;
7791 if (blob_type == MONO_TYPE_CLASS)
7792 type->data.klass = mono_defaults.object_class;
7793 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7794 /* For enums, we need to use the base type */
7795 type->type = MONO_TYPE_VALUETYPE;
7796 type->data.klass = mono_class_from_mono_type (real_type);
7798 type->data.klass = mono_class_from_mono_type (real_type);
7801 ICALL_EXPORT MonoObject*
7802 property_info_get_default_value (MonoReflectionProperty *property)
7806 MonoProperty *prop = property->property;
7807 MonoType *type = get_property_type (prop);
7808 MonoDomain *domain = mono_object_domain (property);
7809 MonoTypeEnum def_type;
7810 const char *def_value;
7813 mono_class_init (prop->parent);
7815 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7816 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7820 def_value = mono_class_get_property_default_value (prop, &def_type);
7822 mono_type_from_blob_type (&blob_type, def_type, type);
7823 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7825 mono_error_set_pending_exception (&error);
7829 ICALL_EXPORT MonoBoolean
7830 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7833 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7834 MonoCustomAttrInfo *cinfo;
7837 mono_class_init_checked (attr_class, &error);
7838 mono_error_raise_exception (&error);
7840 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7841 if (!is_ok (&error)) {
7842 mono_error_set_pending_exception (&error);
7847 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7849 mono_custom_attrs_free (cinfo);
7853 ICALL_EXPORT MonoArray*
7854 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7856 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7861 mono_class_init_checked (attr_class, &error);
7862 mono_error_raise_exception (&error);
7865 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7866 if (!mono_error_ok (&error)) {
7867 mono_error_set_pending_exception (&error);
7871 if (mono_loader_get_last_error ()) {
7872 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7879 ICALL_EXPORT MonoArray*
7880 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7884 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7885 mono_error_set_pending_exception (&error);
7890 ICALL_EXPORT MonoString*
7891 ves_icall_Mono_Runtime_GetDisplayName (void)
7894 MonoString *display_name;
7896 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7897 display_name = mono_string_new (mono_domain_get (), info);
7899 return display_name;
7902 ICALL_EXPORT MonoString*
7903 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7906 MonoString *message;
7910 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7911 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7914 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7916 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7917 mono_error_raise_exception (&error);
7924 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7927 char *path_str = mono_string_to_utf8 (path);
7929 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7937 ICALL_EXPORT gpointer
7938 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7940 return GetCurrentProcess ();
7943 ICALL_EXPORT MonoBoolean
7944 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7946 return GetExitCodeProcess (handle, (guint32*) exitcode);
7949 ICALL_EXPORT MonoBoolean
7950 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7952 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7953 return CloseHandle (handle);
7955 return CloseProcess (handle);
7959 ICALL_EXPORT MonoBoolean
7960 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7962 return TerminateProcess (handle, exitcode);
7966 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
7968 return WaitForInputIdle (handle, milliseconds);
7971 ICALL_EXPORT MonoBoolean
7972 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
7974 return GetProcessWorkingSetSize (handle, min, max);
7977 ICALL_EXPORT MonoBoolean
7978 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
7980 return SetProcessWorkingSetSize (handle, min, max);
7983 ICALL_EXPORT MonoBoolean
7984 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
7986 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
7990 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
7992 return mono_process_current_pid ();
7996 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
7998 return GetPriorityClass (handle);
8001 ICALL_EXPORT MonoBoolean
8002 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8004 return SetPriorityClass (handle, priorityClass);
8007 #ifndef DISABLE_ICALL_TABLES
8009 #define ICALL_TYPE(id,name,first)
8010 #define ICALL(id,name,func) Icall_ ## id,
8013 #include "metadata/icall-def.h"
8019 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8020 #define ICALL(id,name,func)
8022 #include "metadata/icall-def.h"
8028 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8029 #define ICALL(id,name,func)
8031 guint16 first_icall;
8034 static const IcallTypeDesc
8035 icall_type_descs [] = {
8036 #include "metadata/icall-def.h"
8040 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8043 #define ICALL_TYPE(id,name,first)
8046 #ifdef HAVE_ARRAY_ELEM_INIT
8047 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8048 #define MSGSTRFIELD1(line) str##line
8050 static const struct msgstrtn_t {
8051 #define ICALL(id,name,func)
8053 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8054 #include "metadata/icall-def.h"
8056 } icall_type_names_str = {
8057 #define ICALL_TYPE(id,name,first) (name),
8058 #include "metadata/icall-def.h"
8061 static const guint16 icall_type_names_idx [] = {
8062 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8063 #include "metadata/icall-def.h"
8066 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8068 static const struct msgstr_t {
8070 #define ICALL_TYPE(id,name,first)
8071 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8072 #include "metadata/icall-def.h"
8074 } icall_names_str = {
8075 #define ICALL(id,name,func) (name),
8076 #include "metadata/icall-def.h"
8079 static const guint16 icall_names_idx [] = {
8080 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8081 #include "metadata/icall-def.h"
8084 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8090 #define ICALL_TYPE(id,name,first) name,
8091 #define ICALL(id,name,func)
8092 static const char* const
8093 icall_type_names [] = {
8094 #include "metadata/icall-def.h"
8098 #define icall_type_name_get(id) (icall_type_names [(id)])
8102 #define ICALL_TYPE(id,name,first)
8103 #define ICALL(id,name,func) name,
8104 static const char* const
8106 #include "metadata/icall-def.h"
8109 #define icall_name_get(id) icall_names [(id)]
8111 #endif /* !HAVE_ARRAY_ELEM_INIT */
8115 #define ICALL_TYPE(id,name,first)
8116 #define ICALL(id,name,func) func,
8117 static const gconstpointer
8118 icall_functions [] = {
8119 #include "metadata/icall-def.h"
8123 #ifdef ENABLE_ICALL_SYMBOL_MAP
8126 #define ICALL_TYPE(id,name,first)
8127 #define ICALL(id,name,func) #func,
8128 static const gconstpointer
8129 icall_symbols [] = {
8130 #include "metadata/icall-def.h"
8135 #endif /* DISABLE_ICALL_TABLES */
8137 static mono_mutex_t icall_mutex;
8138 static GHashTable *icall_hash = NULL;
8139 static GHashTable *jit_icall_hash_name = NULL;
8140 static GHashTable *jit_icall_hash_addr = NULL;
8143 mono_icall_init (void)
8145 #ifndef DISABLE_ICALL_TABLES
8148 /* check that tables are sorted: disable in release */
8151 const char *prev_class = NULL;
8152 const char *prev_method;
8154 for (i = 0; i < Icall_type_num; ++i) {
8155 const IcallTypeDesc *desc;
8158 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8159 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8160 prev_class = icall_type_name_get (i);
8161 desc = &icall_type_descs [i];
8162 num_icalls = icall_desc_num_icalls (desc);
8163 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8164 for (j = 0; j < num_icalls; ++j) {
8165 const char *methodn = icall_name_get (desc->first_icall + j);
8166 if (prev_method && strcmp (prev_method, methodn) >= 0)
8167 g_print ("method %s should come before method %s\n", methodn, prev_method);
8168 prev_method = methodn;
8174 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8175 mono_os_mutex_init (&icall_mutex);
8179 mono_icall_lock (void)
8181 mono_locks_os_acquire (&icall_mutex, IcallLock);
8185 mono_icall_unlock (void)
8187 mono_locks_os_release (&icall_mutex, IcallLock);
8191 mono_icall_cleanup (void)
8193 g_hash_table_destroy (icall_hash);
8194 g_hash_table_destroy (jit_icall_hash_name);
8195 g_hash_table_destroy (jit_icall_hash_addr);
8196 mono_os_mutex_destroy (&icall_mutex);
8200 * mono_add_internal_call:
8201 * @name: method specification to surface to the managed world
8202 * @method: pointer to a C method to invoke when the method is called
8204 * This method surfaces the C function pointed by @method as a method
8205 * that has been surfaced in managed code with the method specified in
8206 * @name as an internal call.
8208 * Internal calls are surfaced to all app domains loaded and they are
8209 * accessibly by a type with the specified name.
8211 * You must provide a fully qualified type name, that is namespaces
8212 * and type name, followed by a colon and the method name, with an
8213 * optional signature to bind.
8215 * For example, the following are all valid declarations:
8217 * "MyApp.Services.ScriptService:Accelerate"
8218 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8220 * You use method parameters in cases where there might be more than
8221 * one surface method to managed code. That way you can register different
8222 * internal calls for different method overloads.
8224 * The internal calls are invoked with no marshalling. This means that .NET
8225 * types like System.String are exposed as `MonoString *` parameters. This is
8226 * different than the way that strings are surfaced in P/Invoke.
8228 * For more information on how the parameters are marshalled, see the
8229 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8232 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8233 * reference for more information on the format of method descriptions.
8236 mono_add_internal_call (const char *name, gconstpointer method)
8240 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8242 mono_icall_unlock ();
8245 #ifndef DISABLE_ICALL_TABLES
8247 #ifdef HAVE_ARRAY_ELEM_INIT
8249 compare_method_imap (const void *key, const void *elem)
8251 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8252 return strcmp (key, method_name);
8256 find_method_icall (const IcallTypeDesc *imap, const char *name)
8258 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);
8261 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8265 compare_class_imap (const void *key, const void *elem)
8267 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8268 return strcmp (key, class_name);
8271 static const IcallTypeDesc*
8272 find_class_icalls (const char *name)
8274 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);
8277 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8280 #else /* HAVE_ARRAY_ELEM_INIT */
8283 compare_method_imap (const void *key, const void *elem)
8285 const char** method_name = (const char**)elem;
8286 return strcmp (key, *method_name);
8290 find_method_icall (const IcallTypeDesc *imap, const char *name)
8292 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8295 return (gpointer)icall_functions [(nameslot - icall_names)];
8299 compare_class_imap (const void *key, const void *elem)
8301 const char** class_name = (const char**)elem;
8302 return strcmp (key, *class_name);
8305 static const IcallTypeDesc*
8306 find_class_icalls (const char *name)
8308 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8311 return &icall_type_descs [nameslot - icall_type_names];
8314 #endif /* HAVE_ARRAY_ELEM_INIT */
8316 #endif /* DISABLE_ICALL_TABLES */
8319 * we should probably export this as an helper (handle nested types).
8320 * Returns the number of chars written in buf.
8323 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8325 int nspacelen, cnamelen;
8326 nspacelen = strlen (klass->name_space);
8327 cnamelen = strlen (klass->name);
8328 if (nspacelen + cnamelen + 2 > bufsize)
8331 memcpy (buf, klass->name_space, nspacelen);
8332 buf [nspacelen ++] = '.';
8334 memcpy (buf + nspacelen, klass->name, cnamelen);
8335 buf [nspacelen + cnamelen] = 0;
8336 return nspacelen + cnamelen;
8339 #ifdef DISABLE_ICALL_TABLES
8341 no_icall_table (void)
8343 g_assert_not_reached ();
8348 mono_lookup_internal_call (MonoMethod *method)
8353 int typelen = 0, mlen, siglen;
8355 #ifndef DISABLE_ICALL_TABLES
8356 const IcallTypeDesc *imap = NULL;
8359 g_assert (method != NULL);
8361 if (method->is_inflated)
8362 method = ((MonoMethodInflated *) method)->declaring;
8364 if (method->klass->nested_in) {
8365 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8369 mname [pos++] = '/';
8372 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8378 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8383 #ifndef DISABLE_ICALL_TABLES
8384 imap = find_class_icalls (mname);
8387 mname [typelen] = ':';
8388 mname [typelen + 1] = ':';
8390 mlen = strlen (method->name);
8391 memcpy (mname + typelen + 2, method->name, mlen);
8392 sigstart = mname + typelen + 2 + mlen;
8395 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8396 siglen = strlen (tmpsig);
8397 if (typelen + mlen + siglen + 6 > sizeof (mname))
8400 memcpy (sigstart + 1, tmpsig, siglen);
8401 sigstart [siglen + 1] = ')';
8402 sigstart [siglen + 2] = 0;
8407 res = g_hash_table_lookup (icall_hash, mname);
8409 mono_icall_unlock ();;
8412 /* try without signature */
8414 res = g_hash_table_lookup (icall_hash, mname);
8416 mono_icall_unlock ();
8420 #ifdef DISABLE_ICALL_TABLES
8421 mono_icall_unlock ();
8422 /* Fail only when the result is actually used */
8423 /* mono_marshal_get_native_wrapper () depends on this */
8424 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8425 return ves_icall_System_String_ctor_RedirectToCreateString;
8427 return no_icall_table;
8429 /* it wasn't found in the static call tables */
8431 mono_icall_unlock ();
8434 res = find_method_icall (imap, sigstart - mlen);
8436 mono_icall_unlock ();
8439 /* try _with_ signature */
8441 res = find_method_icall (imap, sigstart - mlen);
8443 mono_icall_unlock ();
8447 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8448 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8449 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8450 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8451 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");
8452 g_print ("If you see other errors or faults after this message they are probably related\n");
8453 g_print ("and you need to fix your mono install first.\n");
8455 mono_icall_unlock ();
8461 #ifdef ENABLE_ICALL_SYMBOL_MAP
8463 func_cmp (gconstpointer key, gconstpointer p)
8465 return (gsize)key - (gsize)*(gsize*)p;
8470 * mono_lookup_icall_symbol:
8472 * Given the icall METHOD, returns its C symbol.
8475 mono_lookup_icall_symbol (MonoMethod *m)
8477 #ifdef DISABLE_ICALL_TABLES
8478 g_assert_not_reached ();
8481 #ifdef ENABLE_ICALL_SYMBOL_MAP
8485 static gconstpointer *functions_sorted;
8486 static const char**symbols_sorted;
8487 static gboolean inited;
8492 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8493 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8494 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8495 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8496 /* Bubble sort the two arrays */
8500 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8501 if (functions_sorted [i] > functions_sorted [i + 1]) {
8504 tmp = functions_sorted [i];
8505 functions_sorted [i] = functions_sorted [i + 1];
8506 functions_sorted [i + 1] = tmp;
8507 tmp = symbols_sorted [i];
8508 symbols_sorted [i] = symbols_sorted [i + 1];
8509 symbols_sorted [i + 1] = tmp;
8516 func = mono_lookup_internal_call (m);
8519 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8523 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8525 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8526 g_assert_not_reached ();
8533 type_from_typename (char *type_name)
8535 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8537 if (!strcmp (type_name, "int"))
8538 klass = mono_defaults.int_class;
8539 else if (!strcmp (type_name, "ptr"))
8540 klass = mono_defaults.int_class;
8541 else if (!strcmp (type_name, "void"))
8542 klass = mono_defaults.void_class;
8543 else if (!strcmp (type_name, "int32"))
8544 klass = mono_defaults.int32_class;
8545 else if (!strcmp (type_name, "uint32"))
8546 klass = mono_defaults.uint32_class;
8547 else if (!strcmp (type_name, "int8"))
8548 klass = mono_defaults.sbyte_class;
8549 else if (!strcmp (type_name, "uint8"))
8550 klass = mono_defaults.byte_class;
8551 else if (!strcmp (type_name, "int16"))
8552 klass = mono_defaults.int16_class;
8553 else if (!strcmp (type_name, "uint16"))
8554 klass = mono_defaults.uint16_class;
8555 else if (!strcmp (type_name, "long"))
8556 klass = mono_defaults.int64_class;
8557 else if (!strcmp (type_name, "ulong"))
8558 klass = mono_defaults.uint64_class;
8559 else if (!strcmp (type_name, "float"))
8560 klass = mono_defaults.single_class;
8561 else if (!strcmp (type_name, "double"))
8562 klass = mono_defaults.double_class;
8563 else if (!strcmp (type_name, "object"))
8564 klass = mono_defaults.object_class;
8565 else if (!strcmp (type_name, "obj"))
8566 klass = mono_defaults.object_class;
8567 else if (!strcmp (type_name, "string"))
8568 klass = mono_defaults.string_class;
8569 else if (!strcmp (type_name, "bool"))
8570 klass = mono_defaults.boolean_class;
8571 else if (!strcmp (type_name, "boolean"))
8572 klass = mono_defaults.boolean_class;
8574 g_error ("%s", type_name);
8575 g_assert_not_reached ();
8577 return &klass->byval_arg;
8581 * LOCKING: Take the corlib image lock.
8583 MonoMethodSignature*
8584 mono_create_icall_signature (const char *sigstr)
8589 MonoMethodSignature *res, *res2;
8590 MonoImage *corlib = mono_defaults.corlib;
8592 mono_image_lock (corlib);
8593 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8594 mono_image_unlock (corlib);
8599 parts = g_strsplit (sigstr, " ", 256);
8608 res = mono_metadata_signature_alloc (corlib, len - 1);
8613 * Under windows, the default pinvoke calling convention is STDCALL but
8616 res->call_convention = MONO_CALL_C;
8619 res->ret = type_from_typename (parts [0]);
8620 for (i = 1; i < len; ++i) {
8621 res->params [i - 1] = type_from_typename (parts [i]);
8626 mono_image_lock (corlib);
8627 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8629 res = res2; /*Value is allocated in the image pool*/
8631 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8632 mono_image_unlock (corlib);
8638 mono_find_jit_icall_by_name (const char *name)
8640 MonoJitICallInfo *info;
8641 g_assert (jit_icall_hash_name);
8644 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8645 mono_icall_unlock ();
8650 mono_find_jit_icall_by_addr (gconstpointer addr)
8652 MonoJitICallInfo *info;
8653 g_assert (jit_icall_hash_addr);
8656 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8657 mono_icall_unlock ();
8663 * mono_get_jit_icall_info:
8665 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8666 * caller should access it while holding the icall lock.
8669 mono_get_jit_icall_info (void)
8671 return jit_icall_hash_name;
8675 * mono_lookup_jit_icall_symbol:
8677 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8680 mono_lookup_jit_icall_symbol (const char *name)
8682 MonoJitICallInfo *info;
8683 const char *res = NULL;
8686 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8688 res = info->c_symbol;
8689 mono_icall_unlock ();
8694 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8697 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8698 mono_icall_unlock ();
8702 * 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
8703 * icalls without wrappers in some cases.
8706 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8708 MonoJitICallInfo *info;
8715 if (!jit_icall_hash_name) {
8716 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8717 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8720 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8721 g_warning ("jit icall already defined \"%s\"\n", name);
8722 g_assert_not_reached ();
8725 info = g_new0 (MonoJitICallInfo, 1);
8730 info->c_symbol = c_symbol;
8731 info->no_raise = no_raise;
8734 info->wrapper = func;
8736 info->wrapper = NULL;
8739 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8740 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8742 mono_icall_unlock ();
8747 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8749 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);