5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
9 * Aleksey Kliger (aleksey@xamarin.com)
11 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
12 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
13 * Copyright 2011-2015 Xamarin Inc (http://www.xamarin.com).
24 #ifdef HAVE_SYS_TIME_H
30 #if defined (HOST_WIN32)
33 #if defined (HAVE_WCHAR_H)
37 #include "mono/utils/mono-membar.h"
38 #include <mono/metadata/object.h>
39 #include <mono/metadata/threads.h>
40 #include <mono/metadata/threads-types.h>
41 #include <mono/metadata/threadpool-ms.h>
42 #include <mono/metadata/threadpool-ms-io.h>
43 #include <mono/metadata/monitor.h>
44 #include <mono/metadata/reflection.h>
45 #include <mono/metadata/assembly.h>
46 #include <mono/metadata/tabledefs.h>
47 #include <mono/metadata/exception.h>
48 #include <mono/metadata/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/io-layer/io-layer.h>
85 #include <mono/utils/monobitset.h>
86 #include <mono/utils/mono-time.h>
87 #include <mono/utils/mono-proclib.h>
88 #include <mono/utils/mono-string.h>
89 #include <mono/utils/mono-error-internals.h>
90 #include <mono/utils/mono-mmap.h>
91 #include <mono/utils/mono-io-portability.h>
92 #include <mono/utils/mono-digest.h>
93 #include <mono/utils/bsearch.h>
94 #include <mono/utils/mono-os-mutex.h>
95 #include <mono/utils/mono-threads.h>
97 #if defined (HOST_WIN32)
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
138 ICALL_EXPORT MonoObject *
139 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
145 ac = (MonoClass *)arr->obj.vtable->klass;
147 esize = mono_array_element_size (ac);
148 ea = (gpointer*)((char*)arr->vector + (pos * esize));
150 if (ac->element_class->valuetype)
151 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
153 return (MonoObject *)*ea;
156 ICALL_EXPORT MonoObject *
157 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
163 MONO_CHECK_ARG_NULL (idxs, NULL);
166 ic = (MonoClass *)io->obj.vtable->klass;
168 ac = (MonoClass *)arr->obj.vtable->klass;
170 g_assert (ic->rank == 1);
171 if (io->bounds != NULL || io->max_length != ac->rank) {
172 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
176 ind = (gint32 *)io->vector;
178 if (arr->bounds == NULL) {
179 if (*ind < 0 || *ind >= arr->max_length) {
180 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
184 return ves_icall_System_Array_GetValueImpl (arr, *ind);
187 for (i = 0; i < ac->rank; i++) {
188 if ((ind [i] < arr->bounds [i].lower_bound) ||
189 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
190 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
195 pos = ind [0] - arr->bounds [0].lower_bound;
196 for (i = 1; i < ac->rank; i++)
197 pos = pos * arr->bounds [i].length + ind [i] -
198 arr->bounds [i].lower_bound;
200 return ves_icall_System_Array_GetValueImpl (arr, pos);
204 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
206 MonoClass *ac, *vc, *ec;
216 vc = value->vtable->klass;
220 ac = arr->obj.vtable->klass;
221 ec = ac->element_class;
223 esize = mono_array_element_size (ac);
224 ea = (gpointer*)((char*)arr->vector + (pos * esize));
225 va = (gpointer*)((char*)value + sizeof (MonoObject));
227 if (mono_class_is_nullable (ec)) {
228 mono_nullable_init ((guint8*)ea, value, ec);
233 mono_gc_bzero_atomic (ea, esize);
237 #define NO_WIDENING_CONVERSION G_STMT_START{\
238 mono_set_pending_exception (mono_get_exception_argument ( \
239 "value", "not a widening conversion")); \
243 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
244 if (esize < vsize + (extra)) { \
245 mono_set_pending_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
251 #define INVALID_CAST G_STMT_START{ \
252 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
253 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
257 /* Check element (destination) type. */
258 switch (ec->byval_arg.type) {
259 case MONO_TYPE_STRING:
260 switch (vc->byval_arg.type) {
261 case MONO_TYPE_STRING:
267 case MONO_TYPE_BOOLEAN:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_BOOLEAN:
282 NO_WIDENING_CONVERSION;
291 if (!ec->valuetype) {
292 if (!mono_object_isinst (value, ec))
294 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
298 if (mono_object_isinst (value, ec)) {
299 if (ec->has_references)
300 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
302 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
309 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
311 et = ec->byval_arg.type;
312 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
313 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
315 vt = vc->byval_arg.type;
316 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
317 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
319 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
325 case MONO_TYPE_CHAR: \
326 CHECK_WIDENING_CONVERSION(0); \
327 *(etype *) ea = (etype) u64; \
329 /* You can't assign a signed value to an unsigned array. */ \
334 /* You can't assign a floating point number to an integer array. */ \
337 NO_WIDENING_CONVERSION; \
341 #define ASSIGN_SIGNED(etype) G_STMT_START{\
347 CHECK_WIDENING_CONVERSION(0); \
348 *(etype *) ea = (etype) i64; \
350 /* You can assign an unsigned value to a signed array if the array's */ \
351 /* element size is larger than the value size. */ \
356 case MONO_TYPE_CHAR: \
357 CHECK_WIDENING_CONVERSION(1); \
358 *(etype *) ea = (etype) u64; \
360 /* You can't assign a floating point number to an integer array. */ \
363 NO_WIDENING_CONVERSION; \
367 #define ASSIGN_REAL(etype) G_STMT_START{\
371 CHECK_WIDENING_CONVERSION(0); \
372 *(etype *) ea = (etype) r64; \
374 /* All integer values fit into a floating point array, so we don't */ \
375 /* need to CHECK_WIDENING_CONVERSION here. */ \
380 *(etype *) ea = (etype) i64; \
386 case MONO_TYPE_CHAR: \
387 *(etype *) ea = (etype) u64; \
394 u64 = *(guint8 *) va;
397 u64 = *(guint16 *) va;
400 u64 = *(guint32 *) va;
403 u64 = *(guint64 *) va;
409 i64 = *(gint16 *) va;
412 i64 = *(gint32 *) va;
415 i64 = *(gint64 *) va;
418 r64 = *(gfloat *) va;
421 r64 = *(gdouble *) va;
424 u64 = *(guint16 *) va;
426 case MONO_TYPE_BOOLEAN:
427 /* Boolean is only compatible with itself. */
440 NO_WIDENING_CONVERSION;
447 /* If we can't do a direct copy, let's try a widening conversion. */
450 ASSIGN_UNSIGNED (guint16);
452 ASSIGN_UNSIGNED (guint8);
454 ASSIGN_UNSIGNED (guint16);
456 ASSIGN_UNSIGNED (guint32);
458 ASSIGN_UNSIGNED (guint64);
460 ASSIGN_SIGNED (gint8);
462 ASSIGN_SIGNED (gint16);
464 ASSIGN_SIGNED (gint32);
466 ASSIGN_SIGNED (gint64);
468 ASSIGN_REAL (gfloat);
470 ASSIGN_REAL (gdouble);
474 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
478 #undef NO_WIDENING_CONVERSION
479 #undef CHECK_WIDENING_CONVERSION
480 #undef ASSIGN_UNSIGNED
486 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
492 MONO_CHECK_ARG_NULL (idxs,);
494 ic = idxs->obj.vtable->klass;
495 ac = arr->obj.vtable->klass;
497 g_assert (ic->rank == 1);
498 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
499 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
503 ind = (gint32 *)idxs->vector;
505 if (arr->bounds == NULL) {
506 if (*ind < 0 || *ind >= arr->max_length) {
507 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
511 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
515 for (i = 0; i < ac->rank; i++)
516 if ((ind [i] < arr->bounds [i].lower_bound) ||
517 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
518 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
522 pos = ind [0] - arr->bounds [0].lower_bound;
523 for (i = 1; i < ac->rank; i++)
524 pos = pos * arr->bounds [i].length + ind [i] -
525 arr->bounds [i].lower_bound;
527 ves_icall_System_Array_SetValueImpl (arr, value, pos);
530 ICALL_EXPORT MonoArray *
531 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
534 MonoClass *aklass, *klass;
537 gboolean bounded = FALSE;
539 MONO_CHECK_ARG_NULL (type, NULL);
540 MONO_CHECK_ARG_NULL (lengths, NULL);
542 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
544 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
546 for (i = 0; i < mono_array_length (lengths); i++) {
547 if (mono_array_get (lengths, gint32, i) < 0) {
548 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
553 klass = mono_class_from_mono_type (type->type);
554 mono_class_init_checked (klass, &error);
555 mono_error_raise_exception (&error);
557 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
558 /* vectors are not the same as one dimensional arrays with no-zero bounds */
563 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
565 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
566 for (i = 0; i < aklass->rank; ++i) {
567 sizes [i] = mono_array_get (lengths, guint32, i);
569 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
571 sizes [i + aklass->rank] = 0;
574 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
575 mono_error_set_pending_exception (&error);
580 ICALL_EXPORT MonoArray *
581 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
584 MonoClass *aklass, *klass;
587 gboolean bounded = FALSE;
589 MONO_CHECK_ARG_NULL (type, NULL);
590 MONO_CHECK_ARG_NULL (lengths, NULL);
592 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
594 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
596 for (i = 0; i < mono_array_length (lengths); i++) {
597 if ((mono_array_get (lengths, gint64, i) < 0) ||
598 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
599 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
604 klass = mono_class_from_mono_type (type->type);
605 mono_class_init_checked (klass, &error);
606 mono_error_raise_exception (&error);
608 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
609 /* vectors are not the same as one dimensional arrays with no-zero bounds */
614 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
616 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
617 for (i = 0; i < aklass->rank; ++i) {
618 sizes [i] = mono_array_get (lengths, guint64, i);
620 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
622 sizes [i + aklass->rank] = 0;
625 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
626 mono_error_set_pending_exception (&error);
632 ves_icall_System_Array_GetRank (MonoObject *arr)
634 return arr->vtable->klass->rank;
638 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
640 gint32 rank = arr->obj.vtable->klass->rank;
643 if ((dimension < 0) || (dimension >= rank)) {
644 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
648 if (arr->bounds == NULL)
649 length = arr->max_length;
651 length = arr->bounds [dimension].length;
653 #ifdef MONO_BIG_ARRAYS
654 if (length > G_MAXINT32) {
655 mono_set_pending_exception (mono_get_exception_overflow ());
663 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
665 gint32 rank = arr->obj.vtable->klass->rank;
667 if ((dimension < 0) || (dimension >= rank)) {
668 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
672 if (arr->bounds == NULL)
673 return arr->max_length;
675 return arr->bounds [dimension].length;
679 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
681 gint32 rank = arr->obj.vtable->klass->rank;
683 if ((dimension < 0) || (dimension >= rank)) {
684 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
688 if (arr->bounds == NULL)
691 return arr->bounds [dimension].lower_bound;
695 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
697 int sz = mono_array_element_size (mono_object_class (arr));
698 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
701 ICALL_EXPORT gboolean
702 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
707 MonoVTable *src_vtable;
708 MonoVTable *dest_vtable;
709 MonoClass *src_class;
710 MonoClass *dest_class;
712 src_vtable = source->obj.vtable;
713 dest_vtable = dest->obj.vtable;
715 if (src_vtable->rank != dest_vtable->rank)
718 if (source->bounds || dest->bounds)
721 /* there's no integer overflow since mono_array_length returns an unsigned integer */
722 if ((dest_idx + length > mono_array_length_fast (dest)) ||
723 (source_idx + length > mono_array_length_fast (source)))
726 src_class = src_vtable->klass->element_class;
727 dest_class = dest_vtable->klass->element_class;
730 * Handle common cases.
733 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
734 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
736 if (src_class == mono_defaults.object_class && dest_class->valuetype)
739 /* Check if we're copying a char[] <==> (u)short[] */
740 if (src_class != dest_class) {
741 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
744 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
745 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
749 if (dest_class->valuetype) {
750 element_size = mono_array_element_size (source->obj.vtable->klass);
751 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
752 if (dest_class->has_references) {
753 mono_value_copy_array (dest, dest_idx, source_addr, length);
755 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
756 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
759 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
766 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
772 ac = (MonoClass *)arr->obj.vtable->klass;
774 esize = mono_array_element_size (ac);
775 ea = (gpointer*)((char*)arr->vector + (pos * esize));
777 mono_gc_memmove_atomic (value, ea, esize);
781 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
787 ac = (MonoClass *)arr->obj.vtable->klass;
788 ec = ac->element_class;
790 esize = mono_array_element_size (ac);
791 ea = (gpointer*)((char*)arr->vector + (pos * esize));
793 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
794 g_assert (esize == sizeof (gpointer));
795 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
797 g_assert (ec->inited);
798 g_assert (esize == mono_class_value_size (ec, NULL));
799 if (ec->has_references)
800 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
802 mono_gc_memmove_atomic (ea, value, esize);
807 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
809 MonoClass *klass = array->obj.vtable->klass;
810 guint32 size = mono_array_element_size (klass);
811 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
813 const char *field_data;
815 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
816 MonoException *exc = mono_get_exception_argument("array",
817 "Cannot initialize array of non-primitive type.");
818 mono_set_pending_exception (exc);
822 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
823 MonoException *exc = mono_get_exception_argument("field_handle",
824 "Field doesn't have an RVA");
825 mono_set_pending_exception (exc);
829 size *= array->max_length;
830 field_data = mono_field_get_data (field_handle);
832 if (size > mono_type_size (field_handle->type, &align)) {
833 MonoException *exc = mono_get_exception_argument("field_handle",
834 "Field not large enough to fill array");
835 mono_set_pending_exception (exc);
839 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
841 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
842 guint ## n *src = (guint ## n *) field_data; \
844 nEnt = (size / sizeof(guint ## n)); \
846 for (i = 0; i < nEnt; i++) { \
847 data[i] = read ## n (&src[i]); \
851 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
853 switch (type->type) {
870 memcpy (mono_array_addr (array, char, 0), field_data, size);
874 memcpy (mono_array_addr (array, char, 0), field_data, size);
879 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
881 return offsetof (MonoString, chars);
884 ICALL_EXPORT MonoObject *
885 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
887 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
891 MonoObject *ret = mono_object_clone_checked (obj, &error);
892 mono_error_set_pending_exception (&error);
899 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
905 MONO_CHECK_ARG_NULL (handle,);
907 klass = mono_class_from_mono_type (handle);
908 MONO_CHECK_ARG (handle, klass,);
910 if (klass->generic_container)
913 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
914 if (!is_ok (&error)) {
915 mono_error_set_pending_exception (&error);
919 /* This will call the type constructor */
920 if (!mono_runtime_class_init_full (vtable, &error))
921 mono_error_set_pending_exception (&error);
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
929 mono_image_check_for_module_cctor (image);
930 if (image->has_module_cctor) {
931 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
932 if (!mono_error_ok (&error)) {
933 mono_error_set_pending_exception (&error);
936 /*It's fine to raise the exception here*/
937 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
938 if (!is_ok (&error)) {
939 mono_error_set_pending_exception (&error);
942 if (!mono_runtime_class_init_full (vtable, &error))
943 mono_error_set_pending_exception (&error);
947 ICALL_EXPORT MonoBoolean
948 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
953 /* later make this configurable and per-arch */
954 int min_size = 4096 * 4 * sizeof (void*);
955 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
956 /* if we have no info we are optimistic and assume there is enough room */
960 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
964 current = (guint8 *)&stack_addr;
965 if (current > stack_addr) {
966 if ((current - stack_addr) < min_size)
969 if (current - (stack_addr - stack_size) < min_size)
975 ICALL_EXPORT MonoObject *
976 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
979 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
980 mono_error_set_pending_exception (&error);
986 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
990 MonoObject **values = NULL;
993 gint32 result = (int)(gsize)mono_defaults.int32_class;
994 MonoClassField* field;
997 klass = mono_object_class (this_obj);
999 if (mono_class_num_fields (klass) == 0)
1003 * Compute the starting value of the hashcode for fields of primitive
1004 * types, and return the remaining fields in an array to the managed side.
1005 * This way, we can avoid costly reflection operations in managed code.
1008 while ((field = mono_class_get_fields (klass, &iter))) {
1009 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1011 if (mono_field_is_deleted (field))
1013 /* FIXME: Add more types */
1014 switch (field->type->type) {
1016 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1018 case MONO_TYPE_STRING: {
1020 s = *(MonoString**)((guint8*)this_obj + field->offset);
1022 result ^= mono_string_hash (s);
1027 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1028 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1029 if (!is_ok (&error)) {
1030 mono_error_set_pending_exception (&error);
1033 values [count++] = o;
1039 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1040 for (i = 0; i < count; ++i)
1041 mono_array_setref (*fields, i, values [i]);
1048 ICALL_EXPORT MonoBoolean
1049 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1053 MonoObject **values = NULL;
1055 MonoClassField* field;
1059 MONO_CHECK_ARG_NULL (that, FALSE);
1061 if (this_obj->vtable != that->vtable)
1064 klass = mono_object_class (this_obj);
1066 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1067 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1070 * Do the comparison for fields of primitive type and return a result if
1071 * possible. Otherwise, return the remaining fields in an array to the
1072 * managed side. This way, we can avoid costly reflection operations in
1077 while ((field = mono_class_get_fields (klass, &iter))) {
1078 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1080 if (mono_field_is_deleted (field))
1082 /* FIXME: Add more types */
1083 switch (field->type->type) {
1086 case MONO_TYPE_BOOLEAN:
1087 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1092 case MONO_TYPE_CHAR:
1093 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1098 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1103 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1107 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1111 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1116 case MONO_TYPE_STRING: {
1117 MonoString *s1, *s2;
1118 guint32 s1len, s2len;
1119 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1120 s2 = *(MonoString**)((guint8*)that + field->offset);
1123 if ((s1 == NULL) || (s2 == NULL))
1125 s1len = mono_string_length (s1);
1126 s2len = mono_string_length (s2);
1130 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1136 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1137 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1138 if (!is_ok (&error)) {
1139 mono_error_set_pending_exception (&error);
1142 values [count++] = o;
1143 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1144 if (!is_ok (&error)) {
1145 mono_error_set_pending_exception (&error);
1148 values [count++] = o;
1151 if (klass->enumtype)
1152 /* enums only have one non-static field */
1158 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1159 for (i = 0; i < count; ++i)
1160 mono_array_setref_fast (*fields, i, values [i]);
1167 ICALL_EXPORT MonoReflectionType *
1168 ves_icall_System_Object_GetType (MonoObject *obj)
1171 MonoReflectionType *ret;
1172 #ifndef DISABLE_REMOTING
1173 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1174 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1177 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1179 mono_error_raise_exception (&error);
1185 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1187 mtype->type = &obj->vtable->klass->byval_arg;
1188 g_assert (mtype->type->type);
1192 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1194 MONO_CHECK_ARG_NULL (obj, 0);
1197 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1198 mono_error_raise_exception (&error);
1203 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1204 MonoReflectionMethod *method,
1205 MonoArray *opt_param_types)
1207 MONO_CHECK_ARG_NULL (method, 0);
1210 gint32 result = mono_image_create_method_token (
1211 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1212 mono_error_raise_exception (&error);
1217 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1220 mono_image_create_pefile (mb, file, &error);
1221 mono_error_raise_exception (&error);
1225 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1228 if (!mono_image_build_metadata (mb, &error))
1229 mono_error_raise_exception (&error);
1233 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1235 mono_image_register_token (mb->dynamic_image, token, obj);
1238 ICALL_EXPORT MonoObject*
1239 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1243 mono_loader_lock ();
1244 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1245 mono_loader_unlock ();
1250 ICALL_EXPORT MonoReflectionModule*
1251 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1254 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1255 mono_error_set_pending_exception (&error);
1260 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1262 MonoMethod **dest = (MonoMethod **)data;
1264 /* skip unmanaged frames */
1280 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1282 MonoMethod **dest = (MonoMethod **)data;
1284 /* skip unmanaged frames */
1289 if (!strcmp (m->klass->name_space, "System.Reflection"))
1298 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1300 MonoMethod **dest = (MonoMethod **)data;
1302 /* skip unmanaged frames */
1306 if (m->wrapper_type != MONO_WRAPPER_NONE)
1309 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1323 static MonoReflectionType *
1324 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1326 MonoMethod *m, *dest;
1328 MonoType *type = NULL;
1329 MonoAssembly *assembly = NULL;
1330 gboolean type_resolve = FALSE;
1332 mono_error_init (error);
1335 * We must compute the calling assembly as type loading must happen under a metadata context.
1336 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1337 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1339 m = mono_method_get_last_managed ();
1342 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1347 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1348 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1349 * to crash. This only seems to happen in some strange remoting
1350 * scenarios and I was unable to figure out what's happening there.
1351 * Dec 10, 2005 - Martin.
1355 assembly = dest->klass->image->assembly;
1356 type_resolve = TRUE;
1358 g_warning (G_STRLOC);
1361 if (info->assembly.name)
1362 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1366 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1367 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1368 return_val_if_nok (error, NULL);
1371 if (!info->assembly.name && !type) {
1373 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1374 return_val_if_nok (error, NULL);
1376 if (assembly && !type && type_resolve) {
1377 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1378 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1379 return_val_if_nok (error, NULL);
1385 return mono_type_get_object_checked (mono_domain_get (), type, error);
1388 ICALL_EXPORT MonoReflectionType*
1389 ves_icall_System_Type_internal_from_name (MonoString *name,
1390 MonoBoolean throwOnError,
1391 MonoBoolean ignoreCase)
1394 char *str = mono_string_to_utf8 (name);
1395 MonoTypeNameParse info;
1396 MonoReflectionType *type;
1399 parsedOk = mono_reflection_parse_type (str, &info);
1401 /* mono_reflection_parse_type() mangles the string */
1403 mono_reflection_free_type_info (&info);
1406 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1411 type = type_from_parsed_name (&info, ignoreCase, &error);
1413 mono_reflection_free_type_info (&info);
1416 if (!mono_error_ok (&error)) {
1418 mono_error_set_pending_exception (&error);
1420 mono_error_cleanup (&error);
1425 MonoException *e = NULL;
1428 e = mono_get_exception_type_load (name, NULL);
1430 mono_loader_clear_error ();
1432 mono_set_pending_exception (e);
1441 ICALL_EXPORT MonoReflectionType*
1442 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1445 MonoReflectionType *ret;
1446 MonoDomain *domain = mono_domain_get ();
1448 ret = mono_type_get_object_checked (domain, handle, &error);
1449 mono_error_raise_exception (&error);
1454 /* System.TypeCode */
1473 TYPECODE_STRING = 18
1476 ICALL_EXPORT guint32
1477 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1479 int t = type->type->type;
1481 if (type->type->byref)
1482 return TYPECODE_OBJECT;
1486 case MONO_TYPE_VOID:
1487 return TYPECODE_OBJECT;
1488 case MONO_TYPE_BOOLEAN:
1489 return TYPECODE_BOOLEAN;
1491 return TYPECODE_BYTE;
1493 return TYPECODE_SBYTE;
1495 return TYPECODE_UINT16;
1497 return TYPECODE_INT16;
1498 case MONO_TYPE_CHAR:
1499 return TYPECODE_CHAR;
1503 return TYPECODE_OBJECT;
1505 return TYPECODE_UINT32;
1507 return TYPECODE_INT32;
1509 return TYPECODE_UINT64;
1511 return TYPECODE_INT64;
1513 return TYPECODE_SINGLE;
1515 return TYPECODE_DOUBLE;
1516 case MONO_TYPE_VALUETYPE: {
1517 MonoClass *klass = type->type->data.klass;
1519 if (klass->enumtype) {
1520 t = mono_class_enum_basetype (klass)->type;
1522 } else if (mono_is_corlib_image (klass->image)) {
1523 if (strcmp (klass->name_space, "System") == 0) {
1524 if (strcmp (klass->name, "Decimal") == 0)
1525 return TYPECODE_DECIMAL;
1526 else if (strcmp (klass->name, "DateTime") == 0)
1527 return TYPECODE_DATETIME;
1530 return TYPECODE_OBJECT;
1532 case MONO_TYPE_STRING:
1533 return TYPECODE_STRING;
1534 case MONO_TYPE_SZARRAY:
1535 case MONO_TYPE_ARRAY:
1536 case MONO_TYPE_OBJECT:
1538 case MONO_TYPE_MVAR:
1539 case MONO_TYPE_TYPEDBYREF:
1540 return TYPECODE_OBJECT;
1541 case MONO_TYPE_CLASS:
1543 MonoClass *klass = type->type->data.klass;
1544 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1545 if (strcmp (klass->name, "DBNull") == 0)
1546 return TYPECODE_DBNULL;
1549 return TYPECODE_OBJECT;
1550 case MONO_TYPE_GENERICINST:
1551 return TYPECODE_OBJECT;
1553 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1559 mono_type_is_primitive (MonoType *type)
1561 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1562 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1566 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1568 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1569 return mono_class_enum_basetype (type->data.klass);
1570 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1571 return mono_class_enum_basetype (type->data.generic_class->container_class);
1575 ICALL_EXPORT guint32
1576 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1581 g_assert (type != NULL);
1583 klass = mono_class_from_mono_type (type->type);
1584 klassc = mono_class_from_mono_type (c->type);
1586 if (type->type->byref ^ c->type->byref)
1589 if (type->type->byref) {
1590 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1591 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1593 klass = mono_class_from_mono_type (t);
1594 klassc = mono_class_from_mono_type (ot);
1596 if (mono_type_is_primitive (t)) {
1597 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1598 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1599 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1600 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1601 return t->type == ot->type;
1603 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1606 if (klass->valuetype)
1607 return klass == klassc;
1608 return klass->valuetype == klassc->valuetype;
1611 return mono_class_is_assignable_from (klass, klassc);
1614 ICALL_EXPORT guint32
1615 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1618 MonoClass *klass = mono_class_from_mono_type (type->type);
1619 mono_class_init_checked (klass, &error);
1620 mono_error_raise_exception (&error);
1621 return mono_object_isinst (obj, klass) != NULL;
1624 ICALL_EXPORT guint32
1625 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1627 MonoClass *klass = mono_class_from_mono_type (type->type);
1628 return klass->flags;
1631 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1632 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1635 MonoClass *klass = field->field->parent;
1636 MonoMarshalType *info;
1640 if (klass->generic_container ||
1641 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1644 ftype = mono_field_get_type (field->field);
1645 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1648 info = mono_marshal_load_type_info (klass);
1650 for (i = 0; i < info->num_fields; ++i) {
1651 if (info->fields [i].field == field->field) {
1652 if (!info->fields [i].mspec)
1655 MonoReflectionMarshalAsAttribute* obj;
1656 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1657 if (!mono_error_ok (&error))
1658 mono_error_set_pending_exception (&error);
1667 ICALL_EXPORT MonoReflectionField*
1668 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1671 gboolean found = FALSE;
1678 klass = handle->parent;
1680 klass = mono_class_from_mono_type (type);
1682 /* Check that the field belongs to the class */
1683 for (k = klass; k; k = k->parent) {
1684 if (k == handle->parent) {
1691 /* The managed code will throw the exception */
1695 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1696 mono_error_raise_exception (&error);
1700 ICALL_EXPORT MonoArray*
1701 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1704 MonoType *type = mono_field_get_type_checked (field->field, &error);
1707 if (!mono_error_ok (&error)) {
1708 mono_error_set_pending_exception (&error);
1712 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1713 mono_error_raise_exception (&error);
1718 vell_icall_get_method_attributes (MonoMethod *method)
1720 return method->flags;
1724 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1727 MonoReflectionType *rt;
1728 MonoDomain *domain = mono_domain_get ();
1729 MonoMethodSignature* sig;
1731 sig = mono_method_signature_checked (method, &error);
1732 if (!mono_error_ok (&error)) {
1733 mono_error_set_pending_exception (&error);
1737 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1738 if (!mono_error_ok (&error)) {
1739 mono_error_set_pending_exception (&error);
1743 MONO_STRUCT_SETREF (info, parent, rt);
1745 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1746 if (!mono_error_ok (&error)) {
1747 mono_error_set_pending_exception (&error);
1751 MONO_STRUCT_SETREF (info, ret, rt);
1753 info->attrs = method->flags;
1754 info->implattrs = method->iflags;
1755 if (sig->call_convention == MONO_CALL_DEFAULT)
1756 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1758 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1763 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1766 ICALL_EXPORT MonoArray*
1767 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1770 MonoDomain *domain = mono_domain_get ();
1772 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1773 mono_error_set_pending_exception (&error);
1777 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1778 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1781 MonoDomain *domain = mono_domain_get ();
1782 MonoReflectionMarshalAsAttribute* res = NULL;
1783 MonoMarshalSpec **mspecs;
1786 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1787 mono_method_get_marshal_info (method, mspecs);
1790 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1791 if (!mono_error_ok (&error)) {
1792 mono_error_set_pending_exception (&error);
1797 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1799 mono_metadata_free_marshal_spec (mspecs [i]);
1806 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1808 MonoClass *parent = field->field->parent;
1809 if (!parent->size_inited)
1810 mono_class_init (parent);
1811 mono_class_setup_fields_locking (parent);
1813 return field->field->offset - sizeof (MonoObject);
1816 ICALL_EXPORT MonoReflectionType*
1817 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1820 MonoReflectionType *ret;
1823 parent = declaring? field->field->parent: field->klass;
1825 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1826 mono_error_raise_exception (&error);
1832 ICALL_EXPORT MonoObject *
1833 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1836 MonoClass *fklass = field->klass;
1837 MonoClassField *cf = field->field;
1838 MonoDomain *domain = mono_object_domain (field);
1840 if (fklass->image->assembly->ref_only) {
1841 mono_set_pending_exception (mono_get_exception_invalid_operation (
1842 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1846 if (mono_security_core_clr_enabled ())
1847 mono_security_core_clr_ensure_reflection_access_field (cf);
1849 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1850 mono_error_set_pending_exception (&error);
1855 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1858 MonoClassField *cf = field->field;
1862 if (field->klass->image->assembly->ref_only) {
1863 mono_set_pending_exception (mono_get_exception_invalid_operation (
1864 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1868 if (mono_security_core_clr_enabled ())
1869 mono_security_core_clr_ensure_reflection_access_field (cf);
1871 type = mono_field_get_type_checked (cf, &error);
1872 if (!mono_error_ok (&error)) {
1873 mono_error_set_pending_exception (&error);
1877 v = (gchar *) value;
1879 switch (type->type) {
1882 case MONO_TYPE_BOOLEAN:
1885 case MONO_TYPE_CHAR:
1894 case MONO_TYPE_VALUETYPE:
1897 v += sizeof (MonoObject);
1899 case MONO_TYPE_STRING:
1900 case MONO_TYPE_OBJECT:
1901 case MONO_TYPE_CLASS:
1902 case MONO_TYPE_ARRAY:
1903 case MONO_TYPE_SZARRAY:
1906 case MONO_TYPE_GENERICINST: {
1907 MonoGenericClass *gclass = type->data.generic_class;
1908 g_assert (!gclass->context.class_inst->is_open);
1910 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1911 MonoClass *nklass = mono_class_from_mono_type (type);
1912 MonoObject *nullable;
1915 * Convert the boxed vtype into a Nullable structure.
1916 * This is complicated by the fact that Nullables have
1917 * a variable structure.
1919 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1920 if (!mono_error_ok (&error)) {
1921 mono_error_set_pending_exception (&error);
1925 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1927 v = (gchar *)mono_object_unbox (nullable);
1930 if (gclass->container_class->valuetype && (v != NULL))
1931 v += sizeof (MonoObject);
1935 g_error ("type 0x%x not handled in "
1936 "ves_icall_FieldInfo_SetValueInternal", type->type);
1941 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1942 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1943 if (!is_ok (&error)) {
1944 mono_error_set_pending_exception (&error);
1947 if (!vtable->initialized) {
1948 if (!mono_runtime_class_init_full (vtable, &error)) {
1949 mono_error_set_pending_exception (&error);
1953 mono_field_static_set_value (vtable, cf, v);
1955 mono_field_set_value (obj, cf, v);
1960 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1969 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1970 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1974 if (MONO_TYPE_IS_REFERENCE (f->type))
1975 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1977 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1980 ICALL_EXPORT MonoObject *
1981 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1983 MonoObject *o = NULL;
1984 MonoClassField *field = rfield->field;
1986 MonoDomain *domain = mono_object_domain (rfield);
1988 MonoTypeEnum def_type;
1989 const char *def_value;
1993 mono_class_init (field->parent);
1995 t = mono_field_get_type_checked (field, &error);
1996 if (!mono_error_ok (&error)) {
1997 mono_error_set_pending_exception (&error);
2001 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2002 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2006 if (image_is_dynamic (field->parent->image)) {
2007 MonoClass *klass = field->parent;
2008 int fidx = field - klass->fields;
2010 g_assert (fidx >= 0 && fidx < klass->field.count);
2011 g_assert (klass->ext);
2012 g_assert (klass->ext->field_def_values);
2013 def_type = klass->ext->field_def_values [fidx].def_type;
2014 def_value = klass->ext->field_def_values [fidx].data;
2015 if (def_type == MONO_TYPE_END) {
2016 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2020 def_value = mono_class_get_field_default_value (field, &def_type);
2021 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2023 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2028 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2032 case MONO_TYPE_BOOLEAN:
2035 case MONO_TYPE_CHAR:
2043 case MONO_TYPE_R8: {
2046 /* boxed value type */
2047 t = g_new0 (MonoType, 1);
2049 klass = mono_class_from_mono_type (t);
2051 o = mono_object_new_checked (domain, klass, &error);
2052 if (!mono_error_ok (&error)) {
2053 mono_error_set_pending_exception (&error);
2056 v = ((gchar *) o) + sizeof (MonoObject);
2057 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2060 case MONO_TYPE_STRING:
2061 case MONO_TYPE_CLASS:
2062 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2065 g_assert_not_reached ();
2071 ICALL_EXPORT MonoReflectionType*
2072 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2075 MonoReflectionType *ret;
2078 type = mono_field_get_type_checked (ref_field->field, &error);
2079 if (!mono_error_ok (&error)) {
2080 mono_error_set_pending_exception (&error);
2084 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2085 if (!mono_error_ok (&error)) {
2086 mono_error_set_pending_exception (&error);
2093 /* From MonoProperty.cs */
2095 PInfo_Attributes = 1,
2096 PInfo_GetMethod = 1 << 1,
2097 PInfo_SetMethod = 1 << 2,
2098 PInfo_ReflectedType = 1 << 3,
2099 PInfo_DeclaringType = 1 << 4,
2104 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2107 MonoReflectionType *rt;
2108 MonoReflectionMethod *rm;
2109 MonoDomain *domain = mono_object_domain (property);
2110 const MonoProperty *pproperty = property->property;
2112 if ((req_info & PInfo_ReflectedType) != 0) {
2113 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2114 mono_error_raise_exception (&error);
2116 MONO_STRUCT_SETREF (info, parent, rt);
2118 if ((req_info & PInfo_DeclaringType) != 0) {
2119 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2120 mono_error_raise_exception (&error);
2122 MONO_STRUCT_SETREF (info, declaring_type, rt);
2125 if ((req_info & PInfo_Name) != 0)
2126 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2128 if ((req_info & PInfo_Attributes) != 0)
2129 info->attrs = pproperty->attrs;
2131 if ((req_info & PInfo_GetMethod) != 0) {
2132 if (pproperty->get &&
2133 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2134 pproperty->get->klass == property->klass)) {
2135 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2136 mono_error_raise_exception (&error);
2141 MONO_STRUCT_SETREF (info, get, rm);
2143 if ((req_info & PInfo_SetMethod) != 0) {
2144 if (pproperty->set &&
2145 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2146 pproperty->set->klass == property->klass)) {
2147 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2148 mono_error_raise_exception (&error);
2153 MONO_STRUCT_SETREF (info, set, rm);
2156 * There may be other methods defined for properties, though, it seems they are not exposed
2157 * in the reflection API
2162 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2165 MonoReflectionType *rt;
2166 MonoReflectionMethod *rm;
2167 MonoDomain *domain = mono_object_domain (event);
2169 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2170 mono_error_raise_exception (&error);
2172 MONO_STRUCT_SETREF (info, reflected_type, rt);
2174 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2175 mono_error_raise_exception (&error);
2177 MONO_STRUCT_SETREF (info, declaring_type, rt);
2179 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2180 info->attrs = event->event->attrs;
2182 if (event->event->add) {
2183 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2184 mono_error_raise_exception (&error);
2189 MONO_STRUCT_SETREF (info, add_method, rm);
2191 if (event->event->remove) {
2192 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2193 mono_error_raise_exception (&error);
2198 MONO_STRUCT_SETREF (info, remove_method, rm);
2200 if (event->event->raise) {
2201 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2202 mono_error_raise_exception (&error);
2207 MONO_STRUCT_SETREF (info, raise_method, rm);
2209 #ifndef MONO_SMALL_CONFIG
2210 if (event->event->other) {
2212 while (event->event->other [n])
2214 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2216 for (i = 0; i < n; i++) {
2217 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2218 mono_error_raise_exception (&error);
2219 mono_array_setref (info->other_methods, i, rm);
2226 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2231 mono_class_setup_interfaces (klass, error);
2232 if (!mono_error_ok (error))
2235 for (i = 0; i < klass->interface_count; i++) {
2236 ic = klass->interfaces [i];
2237 g_hash_table_insert (ifaces, ic, ic);
2239 collect_interfaces (ic, ifaces, error);
2240 if (!mono_error_ok (error))
2246 MonoArray *iface_array;
2247 MonoGenericContext *context;
2251 } FillIfaceArrayData;
2254 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2256 MonoReflectionType *rt;
2257 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2258 MonoClass *ic = (MonoClass *)key;
2259 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2261 if (!mono_error_ok (data->error))
2264 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2265 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2266 if (!mono_error_ok (data->error))
2270 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2271 if (!mono_error_ok (data->error))
2274 mono_array_setref (data->iface_array, data->next_idx++, rt);
2277 mono_metadata_free_type (inflated);
2281 get_interfaces_hash (gconstpointer v1)
2283 MonoClass *k = (MonoClass*)v1;
2285 return k->type_token;
2288 ICALL_EXPORT MonoArray*
2289 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2292 MonoClass *klass = mono_class_from_mono_type (type->type);
2294 FillIfaceArrayData data = { 0 };
2297 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2299 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2300 data.context = mono_class_get_context (klass);
2301 klass = klass->generic_class->container_class;
2304 for (parent = klass; parent; parent = parent->parent) {
2305 mono_class_setup_interfaces (parent, &error);
2306 if (!mono_error_ok (&error))
2308 collect_interfaces (parent, iface_hash, &error);
2309 if (!mono_error_ok (&error))
2313 data.error = &error;
2314 data.domain = mono_object_domain (type);
2316 len = g_hash_table_size (iface_hash);
2318 g_hash_table_destroy (iface_hash);
2319 if (!data.domain->empty_types)
2320 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2321 return data.domain->empty_types;
2324 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2325 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2326 if (!mono_error_ok (&error))
2329 g_hash_table_destroy (iface_hash);
2330 return data.iface_array;
2333 g_hash_table_destroy (iface_hash);
2334 mono_error_set_pending_exception (&error);
2339 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2341 gboolean variance_used;
2342 MonoClass *klass = mono_class_from_mono_type (type->type);
2343 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2344 MonoReflectionMethod *member;
2347 int i = 0, len, ioffset;
2351 mono_class_init_checked (klass, &error);
2352 mono_error_raise_exception (&error);
2353 mono_class_init_checked (iclass, &error);
2354 mono_error_raise_exception (&error);
2356 mono_class_setup_vtable (klass);
2358 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2362 len = mono_class_num_methods (iclass);
2363 domain = mono_object_domain (type);
2364 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2365 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2367 while ((method = mono_class_get_methods (iclass, &iter))) {
2368 member = mono_method_get_object_checked (domain, method, iclass, &error);
2369 mono_error_raise_exception (&error);
2370 mono_array_setref (*methods, i, member);
2371 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2372 mono_error_raise_exception (&error);
2373 mono_array_setref (*targets, i, member);
2380 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2383 MonoClass *klass = mono_class_from_mono_type (type->type);
2385 mono_class_init_checked (klass, &error);
2386 mono_error_raise_exception (&error);
2388 if (image_is_dynamic (klass->image)) {
2389 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2390 *packing = tb->packing_size;
2391 *size = tb->class_size;
2393 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2397 ICALL_EXPORT MonoReflectionType*
2398 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2401 MonoReflectionType *ret;
2404 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2405 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2406 mono_error_raise_exception (&error);
2411 klass = mono_class_from_mono_type (type->type);
2412 mono_class_init_checked (klass, &error);
2413 mono_error_raise_exception (&error);
2415 // GetElementType should only return a type for:
2416 // Array Pointer PassedByRef
2417 if (type->type->byref)
2418 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2419 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2420 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2421 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2422 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2426 mono_error_raise_exception (&error);
2431 ICALL_EXPORT MonoReflectionType*
2432 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2435 MonoReflectionType *ret;
2437 if (type->type->byref)
2440 MonoClass *klass = mono_class_from_mono_type (type->type);
2444 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2445 mono_error_raise_exception (&error);
2450 ICALL_EXPORT MonoBoolean
2451 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2453 return type->type->type == MONO_TYPE_PTR;
2456 ICALL_EXPORT MonoBoolean
2457 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2459 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2462 ICALL_EXPORT MonoBoolean
2463 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2465 return type->type->byref;
2468 ICALL_EXPORT MonoBoolean
2469 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2472 MonoClass *klass = mono_class_from_mono_type (type->type);
2473 mono_class_init_checked (klass, &error);
2474 mono_error_raise_exception (&error);
2476 return mono_class_is_com_object (klass);
2479 ICALL_EXPORT guint32
2480 ves_icall_reflection_get_token (MonoObject* obj)
2483 guint32 result = mono_reflection_get_token_checked (obj, &error);
2484 mono_error_set_pending_exception (&error);
2488 ICALL_EXPORT MonoReflectionModule*
2489 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2492 MonoReflectionModule *result = NULL;
2493 MonoClass *klass = mono_class_from_mono_type (type->type);
2494 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2495 if (!mono_error_ok (&error))
2496 mono_error_set_pending_exception (&error);
2500 ICALL_EXPORT MonoReflectionAssembly*
2501 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2504 MonoDomain *domain = mono_domain_get ();
2505 MonoClass *klass = mono_class_from_mono_type (type->type);
2506 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2508 mono_error_set_pending_exception (&error);
2512 ICALL_EXPORT MonoReflectionType*
2513 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2516 MonoReflectionType *ret;
2517 MonoDomain *domain = mono_domain_get ();
2520 if (type->type->byref)
2522 if (type->type->type == MONO_TYPE_VAR) {
2523 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2524 klass = param ? param->owner.klass : NULL;
2525 } else if (type->type->type == MONO_TYPE_MVAR) {
2526 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2527 klass = param ? param->owner.method->klass : NULL;
2529 klass = mono_class_from_mono_type (type->type)->nested_in;
2535 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2536 mono_error_raise_exception (&error);
2541 ICALL_EXPORT MonoString*
2542 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2544 MonoDomain *domain = mono_domain_get ();
2545 MonoClass *klass = mono_class_from_mono_type (type->type);
2547 if (type->type->byref) {
2548 char *n = g_strdup_printf ("%s&", klass->name);
2549 MonoString *res = mono_string_new (domain, n);
2555 return mono_string_new (domain, klass->name);
2559 ICALL_EXPORT MonoString*
2560 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2562 MonoDomain *domain = mono_domain_get ();
2563 MonoClass *klass = mono_class_from_mono_type (type->type);
2565 while (klass->nested_in)
2566 klass = klass->nested_in;
2568 if (klass->name_space [0] == '\0')
2571 return mono_string_new (domain, klass->name_space);
2575 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2579 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2580 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2584 klass = mono_class_from_mono_type (type->type);
2590 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2593 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2597 ICALL_EXPORT MonoArray*
2598 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2601 MonoReflectionType *rt;
2603 MonoClass *klass, *pklass;
2604 MonoDomain *domain = mono_object_domain (type);
2607 klass = mono_class_from_mono_type (type->type);
2609 if (klass->generic_container) {
2610 MonoGenericContainer *container = klass->generic_container;
2611 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2612 for (i = 0; i < container->type_argc; ++i) {
2613 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2615 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2616 mono_error_raise_exception (&error);
2618 mono_array_setref (res, i, rt);
2620 } else if (klass->generic_class) {
2621 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2622 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2623 for (i = 0; i < inst->type_argc; ++i) {
2624 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2625 mono_error_raise_exception (&error);
2627 mono_array_setref (res, i, rt);
2635 ICALL_EXPORT gboolean
2636 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2640 if (!IS_MONOTYPE (type))
2643 if (type->type->byref)
2646 klass = mono_class_from_mono_type (type->type);
2647 return klass->generic_container != NULL;
2650 ICALL_EXPORT MonoReflectionType*
2651 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2654 MonoReflectionType *ret;
2657 if (type->type->byref)
2660 klass = mono_class_from_mono_type (type->type);
2662 if (klass->generic_container) {
2663 return type; /* check this one */
2665 if (klass->generic_class) {
2666 MonoClass *generic_class = klass->generic_class->container_class;
2669 tb = mono_class_get_ref_info (generic_class);
2671 if (generic_class->wastypebuilder && tb)
2672 return (MonoReflectionType *)tb;
2674 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2675 mono_error_raise_exception (&error);
2683 ICALL_EXPORT MonoReflectionType*
2684 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2687 MonoReflectionType *ret;
2689 MonoType *geninst, **types;
2692 g_assert (IS_MONOTYPE (type));
2693 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2694 mono_error_raise_exception (&error);
2696 count = mono_array_length (type_array);
2697 types = g_new0 (MonoType *, count);
2699 for (i = 0; i < count; i++) {
2700 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2701 types [i] = t->type;
2704 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2709 klass = mono_class_from_mono_type (geninst);
2711 /*we might inflate to the GTD*/
2712 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2713 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2717 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2718 mono_error_raise_exception (&error);
2723 ICALL_EXPORT gboolean
2724 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2728 if (!IS_MONOTYPE (type))
2731 if (type->type->byref)
2734 klass = mono_class_from_mono_type (type->type);
2735 return klass->generic_class != NULL || klass->generic_container != NULL;
2739 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2741 if (!IS_MONOTYPE (type))
2744 if (is_generic_parameter (type->type))
2745 return mono_type_get_generic_param_num (type->type);
2749 ICALL_EXPORT GenericParameterAttributes
2750 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2752 g_assert (IS_MONOTYPE (type));
2753 g_assert (is_generic_parameter (type->type));
2754 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2757 ICALL_EXPORT MonoArray *
2758 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2761 MonoReflectionType *rt;
2762 MonoGenericParamInfo *param_info;
2768 g_assert (IS_MONOTYPE (type));
2770 domain = mono_object_domain (type);
2771 param_info = mono_generic_param_info (type->type->data.generic_param);
2772 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2775 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2776 for (i = 0; i < count; i++) {
2777 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2778 mono_error_raise_exception (&error);
2780 mono_array_setref (res, i, rt);
2787 ICALL_EXPORT MonoBoolean
2788 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2790 return is_generic_parameter (type->type);
2793 ICALL_EXPORT MonoBoolean
2794 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2796 return is_generic_parameter (tb->type.type);
2800 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2801 MonoReflectionType *t)
2803 enumtype->type = t->type;
2806 ICALL_EXPORT MonoReflectionMethod*
2807 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2808 MonoReflectionMethod* generic)
2815 MonoReflectionMethod *ret = NULL;
2817 domain = ((MonoObject *)type)->vtable->domain;
2819 klass = mono_class_from_mono_type (type->type);
2820 mono_class_init_checked (klass, &error);
2821 mono_error_raise_exception (&error);
2824 while ((method = mono_class_get_methods (klass, &iter))) {
2825 if (method->token == generic->method->token) {
2826 ret = mono_method_get_object_checked (domain, method, klass, &error);
2827 mono_error_raise_exception (&error);
2834 ICALL_EXPORT MonoReflectionMethod *
2835 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2838 MonoType *type = ref_type->type;
2840 MonoReflectionMethod *ret = NULL;
2842 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2843 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2846 if (type->type == MONO_TYPE_VAR)
2849 method = mono_type_get_generic_param_owner (type)->owner.method;
2852 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2853 if (!mono_error_ok (&error))
2854 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2858 ICALL_EXPORT MonoBoolean
2859 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2861 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2865 ICALL_EXPORT MonoBoolean
2866 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2868 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2873 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2875 MonoDomain *domain = mono_domain_get ();
2876 MonoImage *image = method->method->klass->image;
2877 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2878 MonoTableInfo *tables = image->tables;
2879 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2880 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2881 guint32 im_cols [MONO_IMPLMAP_SIZE];
2882 guint32 scope_token;
2883 const char *import = NULL;
2884 const char *scope = NULL;
2886 if (image_is_dynamic (image)) {
2887 MonoReflectionMethodAux *method_aux =
2888 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2890 import = method_aux->dllentry;
2891 scope = method_aux->dll;
2894 if (!import || !scope) {
2895 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2900 if (piinfo->implmap_idx) {
2901 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2903 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2904 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2905 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2906 scope = mono_metadata_string_heap (image, scope_token);
2910 *flags = piinfo->piflags;
2911 *entry_point = mono_string_new (domain, import);
2912 *dll_name = mono_string_new (domain, scope);
2915 ICALL_EXPORT MonoReflectionMethod *
2916 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2918 MonoMethodInflated *imethod;
2920 MonoReflectionMethod *ret = NULL;
2923 if (method->method->is_generic)
2926 if (!method->method->is_inflated)
2929 imethod = (MonoMethodInflated *) method->method;
2931 result = imethod->declaring;
2932 /* Not a generic method. */
2933 if (!result->is_generic)
2936 if (image_is_dynamic (method->method->klass->image)) {
2937 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2938 MonoReflectionMethod *res;
2941 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2942 * the dynamic case as well ?
2944 mono_image_lock ((MonoImage*)image);
2945 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2946 mono_image_unlock ((MonoImage*)image);
2952 if (imethod->context.class_inst) {
2953 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2954 /*Generic methods gets the context of the GTD.*/
2955 if (mono_class_get_context (klass)) {
2956 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2957 if (!mono_error_ok (&error))
2962 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2964 if (!mono_error_ok (&error))
2965 mono_error_set_pending_exception (&error);
2969 ICALL_EXPORT gboolean
2970 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2972 return mono_method_signature (method->method)->generic_param_count != 0;
2975 ICALL_EXPORT gboolean
2976 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2978 return method->method->is_generic;
2981 ICALL_EXPORT MonoArray*
2982 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2985 MonoReflectionType *rt;
2990 domain = mono_object_domain (method);
2992 if (method->method->is_inflated) {
2993 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2996 count = inst->type_argc;
2997 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2999 for (i = 0; i < count; i++) {
3000 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3001 mono_error_raise_exception (&error);
3003 mono_array_setref (res, i, rt);
3010 count = mono_method_signature (method->method)->generic_param_count;
3011 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3013 for (i = 0; i < count; i++) {
3014 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3015 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3016 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3018 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3019 mono_error_raise_exception (&error);
3021 mono_array_setref (res, i, rt);
3027 ICALL_EXPORT MonoObject *
3028 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3032 * Invoke from reflection is supposed to always be a virtual call (the API
3033 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3034 * greater flexibility.
3036 MonoMethod *m = method->method;
3037 MonoMethodSignature *sig = mono_method_signature (m);
3040 void *obj = this_arg;
3044 if (mono_security_core_clr_enabled ())
3045 mono_security_core_clr_ensure_reflection_access_method (m);
3047 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3048 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3049 mono_error_cleanup (&error); /* FIXME does this make sense? */
3050 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3055 if (!mono_object_isinst (this_arg, m->klass)) {
3056 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3057 char *target_name = mono_type_get_full_name (m->klass);
3058 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3059 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3061 g_free (target_name);
3065 m = mono_object_get_virtual_method (this_arg, m);
3066 /* must pass the pointer to the value for valuetype methods */
3067 if (m->klass->valuetype)
3068 obj = mono_object_unbox (this_arg);
3069 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3070 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3075 if (sig->ret->byref) {
3076 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"));
3080 pcount = params? mono_array_length (params): 0;
3081 if (pcount != sig->param_count) {
3082 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3086 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3087 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."));
3091 image = m->klass->image;
3092 if (image->assembly->ref_only) {
3093 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."));
3097 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3098 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3102 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3106 intptr_t *lower_bounds;
3107 pcount = mono_array_length (params);
3108 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3109 /* Note: the synthetized array .ctors have int32 as argument type */
3110 for (i = 0; i < pcount; ++i)
3111 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3113 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3114 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3115 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3116 if (!mono_error_ok (&error)) {
3117 mono_error_set_pending_exception (&error);
3121 for (i = 0; i < mono_array_length (arr); ++i) {
3122 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3123 if (!mono_error_ok (&error)) {
3124 mono_error_set_pending_exception (&error);
3127 mono_array_setref_fast (arr, i, subarray);
3129 return (MonoObject*)arr;
3132 if (m->klass->rank == pcount) {
3133 /* Only lengths provided. */
3134 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3135 if (!mono_error_ok (&error)) {
3136 mono_error_set_pending_exception (&error);
3140 return (MonoObject*)arr;
3142 g_assert (pcount == (m->klass->rank * 2));
3143 /* The arguments are lower-bound-length pairs */
3144 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3146 for (i = 0; i < pcount / 2; ++i) {
3147 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3148 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3151 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3152 if (!mono_error_ok (&error)) {
3153 mono_error_set_pending_exception (&error);
3157 return (MonoObject*)arr;
3160 return mono_runtime_invoke_array (m, obj, params, NULL);
3163 #ifndef DISABLE_REMOTING
3164 ICALL_EXPORT MonoObject *
3165 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3167 MonoDomain *domain = mono_object_domain (method);
3168 MonoMethod *m = method->method;
3169 MonoMethodSignature *sig = mono_method_signature (m);
3170 MonoArray *out_args;
3172 int i, j, outarg_count = 0;
3174 if (m->klass == mono_defaults.object_class) {
3175 if (!strcmp (m->name, "FieldGetter")) {
3176 MonoClass *k = this_arg->vtable->klass;
3180 /* If this is a proxy, then it must be a CBO */
3181 if (k == mono_defaults.transparent_proxy_class) {
3182 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3183 this_arg = tp->rp->unwrapped_server;
3184 g_assert (this_arg);
3185 k = this_arg->vtable->klass;
3188 name = mono_array_get (params, MonoString *, 1);
3189 str = mono_string_to_utf8 (name);
3192 MonoClassField* field = mono_class_get_field_from_name (k, str);
3194 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3195 if (field_klass->valuetype)
3196 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3198 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3200 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3201 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3202 mono_array_setref (out_args, 0, result);
3210 g_assert_not_reached ();
3212 } else if (!strcmp (m->name, "FieldSetter")) {
3213 MonoClass *k = this_arg->vtable->klass;
3219 /* If this is a proxy, then it must be a CBO */
3220 if (k == mono_defaults.transparent_proxy_class) {
3221 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3222 this_arg = tp->rp->unwrapped_server;
3223 g_assert (this_arg);
3224 k = this_arg->vtable->klass;
3227 name = mono_array_get (params, MonoString *, 1);
3228 str = mono_string_to_utf8 (name);
3231 MonoClassField* field = mono_class_get_field_from_name (k, str);
3233 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3234 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3236 if (field_klass->valuetype) {
3237 size = mono_type_size (field->type, &align);
3238 g_assert (size == mono_class_value_size (field_klass, NULL));
3239 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3241 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3244 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3245 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3255 g_assert_not_reached ();
3260 for (i = 0; i < mono_array_length (params); i++) {
3261 if (sig->params [i]->byref)
3265 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3267 /* handle constructors only for objects already allocated */
3268 if (!strcmp (method->method->name, ".ctor"))
3269 g_assert (this_arg);
3271 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3272 g_assert (!method->method->klass->valuetype);
3273 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3275 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3276 if (sig->params [i]->byref) {
3278 arg = mono_array_get (params, gpointer, i);
3279 mono_array_setref (out_args, j, arg);
3284 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3291 read_enum_value (const char *mem, int type)
3294 case MONO_TYPE_BOOLEAN:
3296 return *(guint8*)mem;
3298 return *(gint8*)mem;
3299 case MONO_TYPE_CHAR:
3301 return read16 (mem);
3303 return (gint16) read16 (mem);
3305 return read32 (mem);
3307 return (gint32) read32 (mem);
3310 return read64 (mem);
3312 g_assert_not_reached ();
3318 write_enum_value (char *mem, int type, guint64 value)
3322 case MONO_TYPE_I1: {
3323 guint8 *p = (guint8*)mem;
3328 case MONO_TYPE_I2: {
3329 guint16 *p = (guint16 *)mem;
3334 case MONO_TYPE_I4: {
3335 guint32 *p = (guint32 *)mem;
3340 case MONO_TYPE_I8: {
3341 guint64 *p = (guint64 *)mem;
3346 g_assert_not_reached ();
3351 ICALL_EXPORT MonoObject *
3352 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3360 domain = mono_object_domain (enumType);
3361 enumc = mono_class_from_mono_type (enumType->type);
3363 mono_class_init_checked (enumc, &error);
3364 mono_error_raise_exception (&error);
3366 etype = mono_class_enum_basetype (enumc);
3368 res = mono_object_new_checked (domain, enumc, &error);
3369 mono_error_raise_exception (&error);
3370 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3375 ICALL_EXPORT MonoBoolean
3376 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3378 int size = mono_class_value_size (a->vtable->klass, NULL);
3379 guint64 a_val = 0, b_val = 0;
3381 memcpy (&a_val, mono_object_unbox (a), size);
3382 memcpy (&b_val, mono_object_unbox (b), size);
3384 return (a_val & b_val) == b_val;
3387 ICALL_EXPORT MonoObject *
3388 ves_icall_System_Enum_get_value (MonoObject *eobj)
3400 g_assert (eobj->vtable->klass->enumtype);
3402 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3403 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3404 mono_error_raise_exception (&error);
3405 dst = (char *)res + sizeof (MonoObject);
3406 src = (char *)eobj + sizeof (MonoObject);
3407 size = mono_class_value_size (enumc, NULL);
3409 memcpy (dst, src, size);
3414 ICALL_EXPORT MonoReflectionType *
3415 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3418 MonoReflectionType *ret;
3422 klass = mono_class_from_mono_type (type->type);
3423 mono_class_init_checked (klass, &error);
3424 mono_error_raise_exception (&error);
3426 etype = mono_class_enum_basetype (klass);
3428 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3432 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3433 mono_error_raise_exception (&error);
3439 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3441 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3442 gpointer odata = (char *)other + sizeof (MonoObject);
3443 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3444 g_assert (basetype);
3449 if (eobj->vtable->klass != other->vtable->klass)
3452 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3453 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3454 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3457 return me > other ? 1 : -1; \
3460 switch (basetype->type) {
3462 COMPARE_ENUM_VALUES (guint8);
3464 COMPARE_ENUM_VALUES (gint8);
3465 case MONO_TYPE_CHAR:
3467 COMPARE_ENUM_VALUES (guint16);
3469 COMPARE_ENUM_VALUES (gint16);
3471 COMPARE_ENUM_VALUES (guint32);
3473 COMPARE_ENUM_VALUES (gint32);
3475 COMPARE_ENUM_VALUES (guint64);
3477 COMPARE_ENUM_VALUES (gint64);
3481 #undef COMPARE_ENUM_VALUES
3482 /* indicates that the enum was of an unsupported unerlying type */
3487 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3489 gpointer data = (char *)eobj + sizeof (MonoObject);
3490 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3491 g_assert (basetype);
3493 switch (basetype->type) {
3494 case MONO_TYPE_I1: {
3495 gint8 value = *((gint8*)data);
3496 return ((int)value ^ (int)value << 8);
3499 return *((guint8*)data);
3500 case MONO_TYPE_CHAR:
3502 return *((guint16*)data);
3504 case MONO_TYPE_I2: {
3505 gint16 value = *((gint16*)data);
3506 return ((int)(guint16)value | (((int)value) << 16));
3509 return *((guint32*)data);
3511 return *((gint32*)data);
3513 case MONO_TYPE_I8: {
3514 gint64 value = *((gint64*)data);
3515 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3518 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3523 ICALL_EXPORT MonoBoolean
3524 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3527 MonoDomain *domain = mono_object_domain (type);
3528 MonoClass *enumc = mono_class_from_mono_type (type->type);
3529 guint j = 0, nvalues;
3531 MonoClassField *field;
3533 guint64 field_value, previous_value = 0;
3534 gboolean sorted = TRUE;
3536 mono_class_init_checked (enumc, &error);
3537 mono_error_raise_exception (&error);
3539 if (!enumc->enumtype) {
3540 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3544 base_type = mono_class_enum_basetype (enumc)->type;
3546 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3547 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3548 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3551 while ((field = mono_class_get_fields (enumc, &iter))) {
3553 MonoTypeEnum def_type;
3555 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3557 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3559 if (mono_field_is_deleted (field))
3561 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3563 p = mono_class_get_field_default_value (field, &def_type);
3564 /* len = */ mono_metadata_decode_blob_size (p, &p);
3566 field_value = read_enum_value (p, base_type);
3567 mono_array_set (*values, guint64, j, field_value);
3569 if (previous_value > field_value)
3572 previous_value = field_value;
3580 BFLAGS_IgnoreCase = 1,
3581 BFLAGS_DeclaredOnly = 2,
3582 BFLAGS_Instance = 4,
3584 BFLAGS_Public = 0x10,
3585 BFLAGS_NonPublic = 0x20,
3586 BFLAGS_FlattenHierarchy = 0x40,
3587 BFLAGS_InvokeMethod = 0x100,
3588 BFLAGS_CreateInstance = 0x200,
3589 BFLAGS_GetField = 0x400,
3590 BFLAGS_SetField = 0x800,
3591 BFLAGS_GetProperty = 0x1000,
3592 BFLAGS_SetProperty = 0x2000,
3593 BFLAGS_ExactBinding = 0x10000,
3594 BFLAGS_SuppressChangeType = 0x20000,
3595 BFLAGS_OptionalParamBinding = 0x40000
3598 ICALL_EXPORT MonoArray*
3599 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3603 MonoClass *startklass, *klass, *refklass;
3608 char *utf8_name = NULL;
3609 int (*compare_func) (const char *s1, const char *s2) = NULL;
3610 MonoClassField *field;
3611 MonoPtrArray tmp_array;
3613 domain = ((MonoObject *)type)->vtable->domain;
3614 if (type->type->byref)
3615 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3617 klass = startklass = mono_class_from_mono_type (type->type);
3618 refklass = mono_class_from_mono_type (reftype->type);
3620 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3623 if (mono_class_has_failure (klass)) {
3624 mono_ptr_array_destroy (tmp_array);
3625 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3630 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3631 guint32 flags = mono_field_get_flags (field);
3633 if (mono_field_is_deleted_with_flags (field, flags))
3635 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3636 if (bflags & BFLAGS_Public)
3638 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3639 if (bflags & BFLAGS_NonPublic) {
3646 if (flags & FIELD_ATTRIBUTE_STATIC) {
3647 if (bflags & BFLAGS_Static)
3648 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3651 if (bflags & BFLAGS_Instance)
3659 if (utf8_name == NULL) {
3660 utf8_name = mono_string_to_utf8 (name);
3661 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3664 if (compare_func (mono_field_get_name (field), utf8_name))
3668 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3669 if (!mono_error_ok (&error))
3671 mono_ptr_array_append (tmp_array, member);
3673 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3676 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3678 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3679 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3681 mono_ptr_array_destroy (tmp_array);
3683 if (utf8_name != NULL)
3688 mono_ptr_array_destroy (tmp_array);
3689 mono_error_raise_exception (&error);
3690 g_assert_not_reached ();
3694 method_nonpublic (MonoMethod* method, gboolean start_klass)
3696 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3697 case METHOD_ATTRIBUTE_ASSEM:
3698 return (start_klass || mono_defaults.generic_ilist_class);
3699 case METHOD_ATTRIBUTE_PRIVATE:
3701 case METHOD_ATTRIBUTE_PUBLIC:
3709 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3712 MonoClass *startklass;
3716 /*FIXME, use MonoBitSet*/
3717 guint32 method_slots_default [8];
3718 guint32 *method_slots = NULL;
3719 int (*compare_func) (const char *s1, const char *s2) = NULL;
3721 array = g_ptr_array_new ();
3726 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3728 /* An optimization for calls made from Delegate:CreateDelegate () */
3729 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3730 method = mono_get_delegate_invoke (klass);
3731 if (mono_loader_get_last_error ())
3734 g_ptr_array_add (array, method);
3738 mono_class_setup_methods (klass);
3739 mono_class_setup_vtable (klass);
3740 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3743 if (is_generic_parameter (&klass->byval_arg))
3744 nslots = mono_class_get_vtable_size (klass->parent);
3746 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3747 if (nslots >= sizeof (method_slots_default) * 8) {
3748 method_slots = g_new0 (guint32, nslots / 32 + 1);
3750 method_slots = method_slots_default;
3751 memset (method_slots, 0, sizeof (method_slots_default));
3754 mono_class_setup_methods (klass);
3755 mono_class_setup_vtable (klass);
3756 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3760 while ((method = mono_class_get_methods (klass, &iter))) {
3762 if (method->slot != -1) {
3763 g_assert (method->slot < nslots);
3764 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3766 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3767 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3770 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3772 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3773 if (bflags & BFLAGS_Public)
3775 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3781 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3782 if (bflags & BFLAGS_Static)
3783 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3786 if (bflags & BFLAGS_Instance)
3794 if (compare_func (name, method->name))
3799 g_ptr_array_add (array, method);
3801 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3803 if (method_slots != method_slots_default)
3804 g_free (method_slots);
3809 if (method_slots != method_slots_default)
3810 g_free (method_slots);
3811 g_ptr_array_free (array, TRUE);
3813 if (mono_class_has_failure (klass)) {
3814 *ex = mono_class_get_exception_for_failure (klass);
3816 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3817 mono_loader_clear_error ();
3822 ICALL_EXPORT MonoArray*
3823 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3825 static MonoClass *MethodInfo_array;
3829 MonoVTable *array_vtable;
3830 MonoException *ex = NULL;
3831 const char *mname = NULL;
3832 GPtrArray *method_array;
3833 MonoClass *klass, *refklass;
3836 mono_error_init (&error);
3838 if (!MethodInfo_array) {
3839 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3840 mono_memory_barrier ();
3841 MethodInfo_array = klass;
3844 klass = mono_class_from_mono_type (type->type);
3845 refklass = mono_class_from_mono_type (reftype->type);
3846 domain = ((MonoObject *)type)->vtable->domain;
3847 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3848 if (!is_ok (&error)) {
3849 mono_error_set_pending_exception (&error);
3852 if (type->type->byref) {
3853 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3854 mono_error_set_pending_exception (&error);
3860 mname = mono_string_to_utf8 (name);
3862 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3863 g_free ((char*)mname);
3865 mono_set_pending_exception (ex);
3869 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3870 if (!mono_error_ok (&error)) {
3871 mono_error_set_pending_exception (&error);
3875 for (i = 0; i < method_array->len; ++i) {
3876 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3877 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3878 if (!mono_error_ok (&error))
3880 mono_array_setref (res, i, rm);
3884 g_ptr_array_free (method_array, TRUE);
3885 if (!mono_error_ok (&error))
3886 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3890 ICALL_EXPORT MonoArray*
3891 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3894 MonoClass *startklass, *klass, *refklass;
3899 gpointer iter = NULL;
3900 MonoPtrArray tmp_array;
3903 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3905 domain = ((MonoObject *)type)->vtable->domain;
3906 if (type->type->byref)
3907 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3908 klass = startklass = mono_class_from_mono_type (type->type);
3909 refklass = mono_class_from_mono_type (reftype->type);
3911 mono_class_setup_methods (klass);
3912 if (mono_class_has_failure (klass)) {
3913 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3918 while ((method = mono_class_get_methods (klass, &iter))) {
3920 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3922 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3923 if (bflags & BFLAGS_Public)
3926 if (bflags & BFLAGS_NonPublic)
3932 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3933 if (bflags & BFLAGS_Static)
3934 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3937 if (bflags & BFLAGS_Instance)
3943 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3944 if (!mono_error_ok (&error)) {
3945 mono_error_set_pending_exception (&error);
3949 mono_ptr_array_append (tmp_array, member);
3952 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3954 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3955 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3957 mono_ptr_array_destroy (tmp_array);
3963 property_hash (gconstpointer data)
3965 MonoProperty *prop = (MonoProperty*)data;
3967 return g_str_hash (prop->name);
3971 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3973 if (method1->is_inflated)
3974 method1 = ((MonoMethodInflated*) method1)->declaring;
3975 if (method2->is_inflated)
3976 method2 = ((MonoMethodInflated*) method2)->declaring;
3978 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3982 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3984 // Properties are hide-by-name-and-signature
3985 if (!g_str_equal (prop1->name, prop2->name))
3988 /* If we see a property in a generic method, we want to
3989 compare the generic signatures, not the inflated signatures
3990 because we might conflate two properties that were
3994 public T this[T t] { getter { return t; } } // method 1
3995 public U this[U u] { getter { return u; } } // method 2
3998 If we see int Foo<int,int>::Item[int] we need to know if
3999 the indexer came from method 1 or from method 2, and we
4000 shouldn't conflate them. (Bugzilla 36283)
4002 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4005 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4012 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4017 return method_nonpublic (accessor, start_klass);
4020 ICALL_EXPORT MonoArray*
4021 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4025 MonoClass *startklass, *klass;
4031 gchar *propname = NULL;
4032 int (*compare_func) (const char *s1, const char *s2) = NULL;
4034 GHashTable *properties = NULL;
4035 MonoPtrArray tmp_array;
4037 mono_error_init (&error);
4039 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4041 domain = ((MonoObject *)type)->vtable->domain;
4042 if (type->type->byref)
4043 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4044 klass = startklass = mono_class_from_mono_type (type->type);
4047 propname = mono_string_to_utf8 (name);
4048 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4051 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4053 mono_class_setup_methods (klass);
4054 mono_class_setup_vtable (klass);
4055 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4059 while ((prop = mono_class_get_properties (klass, &iter))) {
4065 flags = method->flags;
4068 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4069 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4070 if (bflags & BFLAGS_Public)
4072 } else if (bflags & BFLAGS_NonPublic) {
4073 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4074 property_accessor_nonpublic(prop->set, startklass == klass)) {
4081 if (flags & METHOD_ATTRIBUTE_STATIC) {
4082 if (bflags & BFLAGS_Static)
4083 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4086 if (bflags & BFLAGS_Instance)
4095 if (compare_func (propname, prop->name))
4099 if (g_hash_table_lookup (properties, prop))
4102 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4105 mono_ptr_array_append (tmp_array, pr);
4107 g_hash_table_insert (properties, prop, prop);
4109 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4112 g_hash_table_destroy (properties);
4115 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4116 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4117 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4119 mono_ptr_array_destroy (tmp_array);
4126 if (mono_class_has_failure (klass)) {
4127 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4129 mono_error_set_from_loader_error (&error);
4130 mono_loader_clear_error ();
4135 g_hash_table_destroy (properties);
4138 mono_ptr_array_destroy (tmp_array);
4140 mono_error_set_pending_exception (&error);
4146 event_hash (gconstpointer data)
4148 MonoEvent *event = (MonoEvent*)data;
4150 return g_str_hash (event->name);
4154 event_equal (MonoEvent *event1, MonoEvent *event2)
4156 // Events are hide-by-name
4157 return g_str_equal (event1->name, event2->name);
4160 ICALL_EXPORT MonoArray*
4161 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4165 MonoClass *startklass, *klass;
4171 char *utf8_name = NULL;
4172 int (*compare_func) (const char *s1, const char *s2) = NULL;
4173 GHashTable *events = NULL;
4174 MonoPtrArray tmp_array;
4176 mono_error_init (&error);
4178 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4180 domain = mono_object_domain (type);
4181 if (type->type->byref)
4182 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4183 klass = startklass = mono_class_from_mono_type (type->type);
4185 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4187 mono_class_setup_methods (klass);
4188 mono_class_setup_vtable (klass);
4189 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4193 while ((event = mono_class_get_events (klass, &iter))) {
4195 method = event->add;
4197 method = event->remove;
4199 method = event->raise;
4201 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4202 if (bflags & BFLAGS_Public)
4204 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4205 if (bflags & BFLAGS_NonPublic)
4210 if (bflags & BFLAGS_NonPublic)
4216 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4217 if (bflags & BFLAGS_Static)
4218 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4221 if (bflags & BFLAGS_Instance)
4226 if (bflags & BFLAGS_Instance)
4232 if (utf8_name == NULL) {
4233 utf8_name = mono_string_to_utf8 (name);
4234 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4237 if (compare_func (event->name, utf8_name))
4241 if (g_hash_table_lookup (events, event))
4244 MonoReflectionEvent *ev_obj;
4245 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4248 mono_ptr_array_append (tmp_array, ev_obj);
4250 g_hash_table_insert (events, event, event);
4252 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4255 g_hash_table_destroy (events);
4257 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4259 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4260 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4262 mono_ptr_array_destroy (tmp_array);
4264 if (utf8_name != NULL)
4270 if (mono_class_has_failure (klass)) {
4271 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4273 mono_error_set_from_loader_error (&error);
4274 mono_loader_clear_error ();
4280 g_hash_table_destroy (events);
4281 if (utf8_name != NULL)
4284 mono_ptr_array_destroy (tmp_array);
4286 mono_error_set_pending_exception (&error);
4290 ICALL_EXPORT MonoArray*
4291 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4294 MonoReflectionType *rt;
4302 MonoPtrArray tmp_array;
4304 domain = ((MonoObject *)type)->vtable->domain;
4305 if (type->type->byref)
4306 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4307 klass = mono_class_from_mono_type (type->type);
4310 * If a nested type is generic, return its generic type definition.
4311 * Note that this means that the return value is essentially the set
4312 * of nested types of the generic type definition of @klass.
4314 * A note in MSDN claims that a generic type definition can have
4315 * nested types that aren't generic. In any case, the container of that
4316 * nested type would be the generic type definition.
4318 if (klass->generic_class)
4319 klass = klass->generic_class->container_class;
4321 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4323 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4325 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4326 if (bflags & BFLAGS_Public)
4329 if (bflags & BFLAGS_NonPublic)
4337 str = mono_string_to_utf8 (name);
4338 mono_identifier_unescape_type_name_chars (str);
4341 if (strcmp (nested->name, str))
4345 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4346 mono_error_raise_exception (&error);
4348 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4351 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4353 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4354 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4356 mono_ptr_array_destroy (tmp_array);
4364 ICALL_EXPORT MonoReflectionType*
4365 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4368 MonoReflectionType *ret;
4370 MonoType *type = NULL;
4371 MonoTypeNameParse info;
4372 gboolean type_resolve;
4374 /* On MS.NET, this does not fire a TypeResolve event */
4375 type_resolve = TRUE;
4376 str = mono_string_to_utf8 (name);
4377 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4378 if (!mono_reflection_parse_type (str, &info)) {
4380 mono_reflection_free_type_info (&info);
4382 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4385 /*g_print ("failed parse\n");*/
4389 if (info.assembly.name) {
4391 mono_reflection_free_type_info (&info);
4393 /* 1.0 and 2.0 throw different exceptions */
4394 if (mono_defaults.generic_ilist_class)
4395 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4397 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4403 if (module != NULL) {
4404 if (module->image) {
4405 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4406 if (!is_ok (&error)) {
4408 mono_reflection_free_type_info (&info);
4409 mono_error_set_pending_exception (&error);
4416 if (assembly_is_dynamic (assembly->assembly)) {
4417 /* Enumerate all modules */
4418 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4422 if (abuilder->modules) {
4423 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4424 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4425 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4426 if (!is_ok (&error)) {
4428 mono_reflection_free_type_info (&info);
4429 mono_error_set_pending_exception (&error);
4437 if (!type && abuilder->loaded_modules) {
4438 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4439 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4440 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4441 if (!is_ok (&error)) {
4443 mono_reflection_free_type_info (&info);
4444 mono_error_set_pending_exception (&error);
4453 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4454 if (!is_ok (&error)) {
4456 mono_reflection_free_type_info (&info);
4457 mono_error_set_pending_exception (&error);
4462 mono_reflection_free_type_info (&info);
4464 MonoException *e = NULL;
4467 e = mono_get_exception_type_load (name, NULL);
4469 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4470 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4472 mono_loader_clear_error ();
4475 mono_set_pending_exception (e);
4477 } else if (mono_loader_get_last_error ()) {
4479 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4482 mono_loader_clear_error ();
4485 if (type->type == MONO_TYPE_CLASS) {
4486 MonoClass *klass = mono_type_get_class (type);
4488 /* need to report exceptions ? */
4489 if (throwOnError && mono_class_has_failure (klass)) {
4490 /* report SecurityException (or others) that occured when loading the assembly */
4491 MonoException *exc = mono_class_get_exception_for_failure (klass);
4492 mono_loader_clear_error ();
4493 mono_set_pending_exception (exc);
4498 /* g_print ("got it\n"); */
4499 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4500 mono_error_set_pending_exception (&error);
4506 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4509 gchar *shadow_ini_file;
4512 /* Check for shadow-copied assembly */
4513 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4514 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4516 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4517 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4523 g_free (shadow_ini_file);
4524 if (content != NULL) {
4527 *filename = content;
4534 ICALL_EXPORT MonoString *
4535 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4537 MonoDomain *domain = mono_object_domain (assembly);
4538 MonoAssembly *mass = assembly->assembly;
4539 MonoString *res = NULL;
4544 if (g_path_is_absolute (mass->image->name)) {
4545 absolute = g_strdup (mass->image->name);
4546 dirname = g_path_get_dirname (absolute);
4548 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4549 dirname = g_strdup (mass->basedir);
4552 replace_shadow_path (domain, dirname, &absolute);
4557 for (i = strlen (absolute) - 1; i >= 0; i--)
4558 if (absolute [i] == '\\')
4563 uri = g_filename_to_uri (absolute, NULL, NULL);
4565 const char *prepend = "file://";
4567 if (*absolute == '/' && *(absolute + 1) == '/') {
4570 prepend = "file:///";
4573 uri = g_strconcat (prepend, absolute, NULL);
4577 res = mono_string_new (domain, uri);
4584 ICALL_EXPORT MonoBoolean
4585 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4587 MonoAssembly *mass = assembly->assembly;
4589 return mass->in_gac;
4592 ICALL_EXPORT MonoReflectionAssembly*
4593 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4598 MonoImageOpenStatus status;
4599 MonoReflectionAssembly* result = NULL;
4601 name = mono_string_to_utf8 (mname);
4602 res = mono_assembly_load_with_partial_name (name, &status);
4608 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4610 mono_error_set_pending_exception (&error);
4614 ICALL_EXPORT MonoString *
4615 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4617 MonoDomain *domain = mono_object_domain (assembly);
4620 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4625 ICALL_EXPORT MonoBoolean
4626 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4628 return assembly->assembly->ref_only;
4631 ICALL_EXPORT MonoString *
4632 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4634 MonoDomain *domain = mono_object_domain (assembly);
4636 return mono_string_new (domain, assembly->assembly->image->version);
4639 ICALL_EXPORT MonoReflectionMethod*
4640 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4643 MonoReflectionMethod *res = NULL;
4646 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4650 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4651 if (!mono_error_ok (&error))
4654 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4657 if (!mono_error_ok (&error))
4658 mono_error_set_pending_exception (&error);
4662 ICALL_EXPORT MonoReflectionModule*
4663 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4666 MonoReflectionModule *result = NULL;
4667 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4668 if (!mono_error_ok (&error))
4669 mono_error_set_pending_exception (&error);
4673 ICALL_EXPORT MonoArray*
4674 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4676 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4677 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4681 for (i = 0; i < table->rows; ++i) {
4682 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4683 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4689 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4691 static MonoMethod *create_version = NULL;
4695 mono_error_init (error);
4698 if (!create_version) {
4699 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4700 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4701 g_assert (create_version);
4702 mono_method_desc_free (desc);
4708 args [3] = &revision;
4709 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4710 return_val_if_nok (error, NULL);
4712 mono_runtime_invoke_checked (create_version, result, args, error);
4713 return_val_if_nok (error, NULL);
4718 ICALL_EXPORT MonoArray*
4719 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4723 MonoDomain *domain = mono_object_domain (assembly);
4725 static MonoMethod *create_culture = NULL;
4726 MonoImage *image = assembly->assembly->image;
4730 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4733 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4735 if (count > 0 && !create_culture) {
4736 MonoMethodDesc *desc = mono_method_desc_new (
4737 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4738 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4739 g_assert (create_culture);
4740 mono_method_desc_free (desc);
4743 for (i = 0; i < count; i++) {
4744 MonoObject *version;
4745 MonoReflectionAssemblyName *aname;
4746 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4748 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4750 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4751 domain, mono_class_get_assembly_name_class (), &error);
4752 mono_error_raise_exception (&error);
4754 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4756 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4757 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4758 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4759 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4760 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4761 aname->versioncompat = 1; /* SameMachine (default) */
4762 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4764 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4765 mono_error_raise_exception (&error);
4767 MONO_OBJECT_SETREF (aname, version, version);
4769 if (create_culture) {
4771 MonoBoolean assembly_ref = 1;
4772 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4773 args [1] = &assembly_ref;
4775 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4776 mono_error_raise_exception (&error);
4778 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4781 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4782 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4783 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4785 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4786 /* public key token isn't copied - the class library will
4787 automatically generate it from the public key if required */
4788 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4789 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4791 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4792 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4795 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4798 /* note: this function doesn't return the codebase on purpose (i.e. it can
4799 be used under partial trust as path information isn't present). */
4801 mono_array_setref (result, i, aname);
4806 /* move this in some file in mono/util/ */
4808 g_concat_dir_and_file (const char *dir, const char *file)
4810 g_return_val_if_fail (dir != NULL, NULL);
4811 g_return_val_if_fail (file != NULL, NULL);
4814 * If the directory name doesn't have a / on the end, we need
4815 * to add one so we get a proper path to the file
4817 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4818 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4820 return g_strconcat (dir, file, NULL);
4824 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4827 char *n = mono_string_to_utf8 (name);
4828 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4830 guint32 cols [MONO_MANIFEST_SIZE];
4831 guint32 impl, file_idx;
4835 for (i = 0; i < table->rows; ++i) {
4836 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4837 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4838 if (strcmp (val, n) == 0)
4842 if (i == table->rows)
4845 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4848 * this code should only be called after obtaining the
4849 * ResourceInfo and handling the other cases.
4851 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4852 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4854 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4859 module = assembly->assembly->image;
4862 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4863 mono_error_raise_exception (&error);
4864 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4866 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4869 ICALL_EXPORT gboolean
4870 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4873 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4875 guint32 cols [MONO_MANIFEST_SIZE];
4876 guint32 file_cols [MONO_FILE_SIZE];
4880 n = mono_string_to_utf8 (name);
4881 for (i = 0; i < table->rows; ++i) {
4882 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4883 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4884 if (strcmp (val, n) == 0)
4888 if (i == table->rows)
4891 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4892 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4895 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4896 case MONO_IMPLEMENTATION_FILE:
4897 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4898 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4899 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4900 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4901 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4902 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4905 info->location = RESOURCE_LOCATION_EMBEDDED;
4908 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4909 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4910 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4911 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4912 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4913 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4915 mono_set_pending_exception (ex);
4918 MonoReflectionAssembly *assm_obj;
4919 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4921 mono_error_set_pending_exception (&error);
4924 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4926 /* Obtain info recursively */
4927 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4928 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4931 case MONO_IMPLEMENTATION_EXP_TYPE:
4932 g_assert_not_reached ();
4940 ICALL_EXPORT MonoObject*
4941 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4943 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4944 MonoArray *result = NULL;
4949 /* check hash if needed */
4951 n = mono_string_to_utf8 (name);
4952 for (i = 0; i < table->rows; ++i) {
4953 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4954 if (strcmp (val, n) == 0) {
4957 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4958 fn = mono_string_new (mono_object_domain (assembly), n);
4960 return (MonoObject*)fn;
4968 for (i = 0; i < table->rows; ++i) {
4969 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4973 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4976 for (i = 0; i < table->rows; ++i) {
4977 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4978 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4979 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4980 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4985 return (MonoObject*)result;
4988 ICALL_EXPORT MonoArray*
4989 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4992 MonoDomain *domain = mono_domain_get();
4995 int i, j, file_count = 0;
4996 MonoImage **modules;
4997 guint32 module_count, real_module_count;
4998 MonoTableInfo *table;
4999 guint32 cols [MONO_FILE_SIZE];
5000 MonoImage *image = assembly->assembly->image;
5002 g_assert (image != NULL);
5003 g_assert (!assembly_is_dynamic (assembly->assembly));
5005 table = &image->tables [MONO_TABLE_FILE];
5006 file_count = table->rows;
5008 modules = image->modules;
5009 module_count = image->module_count;
5011 real_module_count = 0;
5012 for (i = 0; i < module_count; ++i)
5014 real_module_count ++;
5016 klass = mono_class_get_module_class ();
5017 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5019 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5020 mono_error_raise_exception (&error);
5021 mono_array_setref (res, 0, image_obj);
5023 for (i = 0; i < module_count; ++i)
5025 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5026 mono_error_raise_exception (&error);
5027 mono_array_setref (res, j, rm);
5031 for (i = 0; i < file_count; ++i, ++j) {
5032 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5033 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5034 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5035 mono_error_raise_exception (&error);
5036 mono_array_setref (res, j, rm);
5039 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5041 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5042 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5045 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5046 mono_error_raise_exception (&error);
5047 mono_array_setref (res, j, rm);
5054 ICALL_EXPORT MonoReflectionMethod*
5055 ves_icall_GetCurrentMethod (void)
5057 MonoReflectionMethod *res = NULL;
5060 MonoMethod *m = mono_method_get_last_managed ();
5063 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5067 while (m->is_inflated)
5068 m = ((MonoMethodInflated*)m)->declaring;
5070 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5071 mono_error_raise_exception (&error);
5077 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5080 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5083 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5084 //method is inflated, we should inflate it on the other class
5085 MonoGenericContext ctx;
5086 ctx.method_inst = inflated->context.method_inst;
5087 ctx.class_inst = inflated->context.class_inst;
5088 if (klass->generic_class)
5089 ctx.class_inst = klass->generic_class->context.class_inst;
5090 else if (klass->generic_container)
5091 ctx.class_inst = klass->generic_container->context.class_inst;
5092 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5093 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5097 mono_class_setup_methods (method->klass);
5098 if (mono_class_has_failure (method->klass))
5100 for (i = 0; i < method->klass->method.count; ++i) {
5101 if (method->klass->methods [i] == method) {
5106 mono_class_setup_methods (klass);
5107 if (mono_class_has_failure (klass))
5109 g_assert (offset >= 0 && offset < klass->method.count);
5110 return klass->methods [offset];
5113 ICALL_EXPORT MonoReflectionMethod*
5114 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5116 MonoReflectionMethod *res = NULL;
5120 klass = mono_class_from_mono_type (type);
5121 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5123 if (method->klass != klass) {
5124 method = mono_method_get_equivalent_method (method, klass);
5129 klass = method->klass;
5130 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5131 mono_error_raise_exception (&error);
5135 ICALL_EXPORT MonoReflectionMethodBody*
5136 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5139 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5140 mono_error_set_pending_exception (&error);
5144 ICALL_EXPORT MonoReflectionAssembly*
5145 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5148 MonoReflectionAssembly *result;
5149 MonoMethod *dest = NULL;
5151 mono_stack_walk_no_il (get_executing, &dest);
5153 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5155 mono_error_set_pending_exception (&error);
5160 ICALL_EXPORT MonoReflectionAssembly*
5161 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5164 MonoReflectionAssembly *result;
5165 MonoDomain* domain = mono_domain_get ();
5167 if (!domain->entry_assembly)
5170 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5172 mono_error_set_pending_exception (&error);
5176 ICALL_EXPORT MonoReflectionAssembly*
5177 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5182 MonoReflectionAssembly *result;
5185 mono_stack_walk_no_il (get_executing, &dest);
5187 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5191 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5194 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5196 mono_error_set_pending_exception (&error);
5200 ICALL_EXPORT MonoString *
5201 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5202 gboolean assembly_qualified)
5204 MonoDomain *domain = mono_object_domain (object);
5205 MonoTypeNameFormat format;
5210 format = assembly_qualified ?
5211 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5212 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5214 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5216 name = mono_type_get_name_full (object->type, format);
5220 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5225 res = mono_string_new (domain, name);
5232 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5235 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5237 mono_class_init_checked (klass, &error);
5238 mono_error_raise_exception (&error);
5239 return mono_security_core_clr_class_level (klass);
5243 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5245 MonoClassField *field = rfield->field;
5246 return mono_security_core_clr_field_level (field, TRUE);
5250 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5252 MonoMethod *method = rfield->method;
5253 return mono_security_core_clr_method_level (method, TRUE);
5257 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)
5259 static MonoMethod *create_culture = NULL;
5263 const char *pkey_ptr;
5265 MonoBoolean assembly_ref = 0;
5267 mono_error_init (error);
5269 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5270 aname->major = name->major;
5271 aname->minor = name->minor;
5272 aname->build = name->build;
5273 aname->flags = name->flags;
5274 aname->revision = name->revision;
5275 aname->hashalg = name->hash_alg;
5276 aname->versioncompat = 1; /* SameMachine (default) */
5277 aname->processor_architecture = name->arch;
5279 if (by_default_version) {
5280 MonoObject *version;
5282 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5283 return_if_nok (error);
5285 MONO_OBJECT_SETREF (aname, version, version);
5289 if (absolute != NULL && *absolute != '\0') {
5290 const gchar *prepend = "file://";
5293 codebase = g_strdup (absolute);
5298 for (i = strlen (codebase) - 1; i >= 0; i--)
5299 if (codebase [i] == '\\')
5302 if (*codebase == '/' && *(codebase + 1) == '/') {
5305 prepend = "file:///";
5309 result = g_strconcat (prepend, codebase, NULL);
5315 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5319 if (!create_culture) {
5320 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5321 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5322 g_assert (create_culture);
5323 mono_method_desc_free (desc);
5326 if (name->culture) {
5327 args [0] = mono_string_new (domain, name->culture);
5328 args [1] = &assembly_ref;
5330 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5331 return_if_nok (error);
5333 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5336 if (name->public_key) {
5337 pkey_ptr = (char*)name->public_key;
5338 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5340 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5341 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5342 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5343 } else if (default_publickey) {
5344 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5345 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5348 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5349 if (name->public_key_token [0]) {
5353 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5354 p = mono_array_addr (aname->keyToken, char, 0);
5356 for (i = 0, j = 0; i < 8; i++) {
5357 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5358 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5361 } else if (default_token) {
5362 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5366 ICALL_EXPORT MonoString *
5367 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5369 MonoDomain *domain = mono_object_domain (assembly);
5370 MonoAssembly *mass = assembly->assembly;
5374 name = mono_stringify_assembly_name (&mass->aname);
5375 res = mono_string_new (domain, name);
5382 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5386 MonoAssembly *mass = assembly->assembly;
5388 if (g_path_is_absolute (mass->image->name)) {
5389 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5390 mono_error_set_pending_exception (&error);
5393 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5395 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5396 mono_error_set_pending_exception (&error);
5402 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5406 MonoImageOpenStatus status = MONO_IMAGE_OK;
5409 MonoAssemblyName name;
5412 filename = mono_string_to_utf8 (fname);
5414 dirname = g_path_get_dirname (filename);
5415 replace_shadow_path (mono_domain_get (), dirname, &filename);
5418 image = mono_image_open (filename, &status);
5424 if (status == MONO_IMAGE_IMAGE_INVALID)
5425 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5427 exc = mono_get_exception_file_not_found2 (NULL, fname);
5428 mono_set_pending_exception (exc);
5432 res = mono_assembly_fill_assembly_name (image, &name);
5434 mono_image_close (image);
5436 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5440 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5441 mono_error_set_pending_exception (&error);
5443 mono_image_close (image);
5447 ICALL_EXPORT MonoBoolean
5448 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5449 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5451 MonoBoolean result = FALSE;
5452 MonoDeclSecurityEntry entry;
5454 /* SecurityAction.RequestMinimum */
5455 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5456 *minimum = entry.blob;
5457 *minLength = entry.size;
5460 /* SecurityAction.RequestOptional */
5461 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5462 *optional = entry.blob;
5463 *optLength = entry.size;
5466 /* SecurityAction.RequestRefuse */
5467 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5468 *refused = entry.blob;
5469 *refLength = entry.size;
5477 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5479 guint32 attrs, visibility;
5481 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5482 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5483 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5486 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5492 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5494 MonoReflectionType *rt;
5497 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5500 mono_error_init (error);
5502 /* we start the count from 1 because we skip the special type <Module> */
5505 for (i = 1; i < tdef->rows; ++i) {
5506 if (mono_module_type_is_visible (tdef, image, i + 1))
5510 count = tdef->rows - 1;
5512 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5513 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5515 for (i = 1; i < tdef->rows; ++i) {
5516 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5517 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5518 mono_loader_assert_no_error (); /* Plug any leaks */
5519 mono_error_assert_ok (error);
5522 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5523 return_val_if_nok (error, NULL);
5525 mono_array_setref (res, count, rt);
5527 MonoException *ex = mono_error_convert_to_exception (error);
5528 mono_array_setref (*exceptions, count, ex);
5537 ICALL_EXPORT MonoArray*
5538 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5541 MonoArray *res = NULL;
5542 MonoArray *exceptions = NULL;
5543 MonoImage *image = NULL;
5544 MonoTableInfo *table = NULL;
5547 int i, len, ex_count;
5549 domain = mono_object_domain (assembly);
5551 g_assert (!assembly_is_dynamic (assembly->assembly));
5552 image = assembly->assembly->image;
5553 table = &image->tables [MONO_TABLE_FILE];
5554 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5555 mono_error_raise_exception (&error);
5557 /* Append data from all modules in the assembly */
5558 for (i = 0; i < table->rows; ++i) {
5559 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5560 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5565 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5566 mono_error_raise_exception (&error);
5568 /* Append the new types to the end of the array */
5569 if (mono_array_length (res2) > 0) {
5571 MonoArray *res3, *ex3;
5573 len1 = mono_array_length (res);
5574 len2 = mono_array_length (res2);
5576 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5577 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5578 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5581 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5582 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5583 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5590 /* the ReflectionTypeLoadException must have all the types (Types property),
5591 * NULL replacing types which throws an exception. The LoaderException must
5592 * contain all exceptions for NULL items.
5595 len = mono_array_length (res);
5598 for (i = 0; i < len; i++) {
5599 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5603 klass = mono_type_get_class (t->type);
5604 if ((klass != NULL) && mono_class_has_failure (klass)) {
5605 /* keep the class in the list */
5606 list = g_list_append (list, klass);
5607 /* and replace Type with NULL */
5608 mono_array_setref (res, i, NULL);
5615 if (list || ex_count) {
5617 MonoException *exc = NULL;
5618 MonoArray *exl = NULL;
5619 int j, length = g_list_length (list) + ex_count;
5621 mono_loader_clear_error ();
5623 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5624 /* Types for which mono_class_get_checked () succeeded */
5625 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5626 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5627 mono_array_setref (exl, i, exc);
5629 /* Types for which it don't */
5630 for (j = 0; j < mono_array_length (exceptions); ++j) {
5631 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5633 g_assert (i < length);
5634 mono_array_setref (exl, i, exc);
5641 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5642 if (!is_ok (&error)) {
5643 mono_error_set_pending_exception (&error);
5646 mono_loader_clear_error ();
5647 mono_set_pending_exception (exc);
5654 ICALL_EXPORT gboolean
5655 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5658 MonoAssemblyName aname;
5659 MonoDomain *domain = mono_object_domain (name);
5661 gboolean is_version_defined;
5662 gboolean is_token_defined;
5664 aname.public_key = NULL;
5665 val = mono_string_to_utf8 (assname);
5666 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5667 g_free ((guint8*) aname.public_key);
5672 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5673 mono_error_set_pending_exception (&error);
5675 mono_assembly_name_free (&aname);
5676 g_free ((guint8*) aname.public_key);
5682 ICALL_EXPORT MonoReflectionType*
5683 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5686 MonoReflectionType *ret;
5687 MonoDomain *domain = mono_object_domain (module);
5690 g_assert (module->image);
5692 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5693 /* These images do not have a global type */
5696 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5697 if (!mono_error_ok (&error)) {
5698 mono_error_set_pending_exception (&error);
5702 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5703 if (!mono_error_ok (&error)) {
5704 mono_error_set_pending_exception (&error);
5712 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5714 /*if (module->image)
5715 mono_image_close (module->image);*/
5718 ICALL_EXPORT MonoString*
5719 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5721 MonoDomain *domain = mono_object_domain (module);
5723 g_assert (module->image);
5724 return mono_string_new (domain, module->image->guid);
5727 ICALL_EXPORT gpointer
5728 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5731 if (module->image && module->image->is_module_handle)
5732 return module->image->raw_data;
5735 return (gpointer) (-1);
5739 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5741 if (image_is_dynamic (image)) {
5742 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5743 *pe_kind = dyn->pe_kind;
5744 *machine = dyn->machine;
5747 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5748 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5753 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5755 return (image->md_version_major << 16) | (image->md_version_minor);
5758 ICALL_EXPORT MonoArray*
5759 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5762 MonoArray *exceptions;
5766 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5770 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5771 mono_error_raise_exception (&error);
5773 for (i = 0; i < mono_array_length (exceptions); ++i) {
5774 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5776 mono_set_pending_exception (ex);
5785 mono_memberref_is_method (MonoImage *image, guint32 token)
5787 if (!image_is_dynamic (image)) {
5788 guint32 cols [MONO_MEMBERREF_SIZE];
5790 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5791 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5792 mono_metadata_decode_blob_size (sig, &sig);
5793 return (*sig != 0x6);
5795 MonoClass *handle_class;
5797 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5800 return mono_defaults.methodhandle_class == handle_class;
5805 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5808 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5809 mono_array_addr (type_args, MonoType*, 0));
5811 context->class_inst = NULL;
5813 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5814 mono_array_addr (method_args, MonoType*, 0));
5816 context->method_inst = NULL;
5819 ICALL_EXPORT MonoType*
5820 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5823 int table = mono_metadata_token_table (token);
5824 int index = mono_metadata_token_index (token);
5825 MonoGenericContext context;
5828 *resolve_error = ResolveTokenError_Other;
5830 /* Validate token */
5831 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5832 (table != MONO_TABLE_TYPESPEC)) {
5833 *resolve_error = ResolveTokenError_BadTable;
5837 if (image_is_dynamic (image)) {
5838 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5839 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5840 return klass ? &klass->byval_arg : NULL;
5843 init_generic_context_from_args (&context, type_args, method_args);
5844 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5845 return klass ? &klass->byval_arg : NULL;
5848 if ((index <= 0) || (index > image->tables [table].rows)) {
5849 *resolve_error = ResolveTokenError_OutOfRange;
5853 init_generic_context_from_args (&context, type_args, method_args);
5854 klass = mono_class_get_checked (image, token, &error);
5856 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5857 if (!mono_error_ok (&error)) {
5858 mono_error_set_pending_exception (&error);
5863 return &klass->byval_arg;
5868 ICALL_EXPORT MonoMethod*
5869 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5872 int table = mono_metadata_token_table (token);
5873 int index = mono_metadata_token_index (token);
5874 MonoGenericContext context;
5877 *resolve_error = ResolveTokenError_Other;
5879 /* Validate token */
5880 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5881 (table != MONO_TABLE_MEMBERREF)) {
5882 *resolve_error = ResolveTokenError_BadTable;
5886 if (image_is_dynamic (image)) {
5887 if (table == MONO_TABLE_METHOD)
5888 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5890 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5891 *resolve_error = ResolveTokenError_BadTable;
5895 init_generic_context_from_args (&context, type_args, method_args);
5896 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5899 if ((index <= 0) || (index > image->tables [table].rows)) {
5900 *resolve_error = ResolveTokenError_OutOfRange;
5903 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5904 *resolve_error = ResolveTokenError_BadTable;
5908 init_generic_context_from_args (&context, type_args, method_args);
5909 method = mono_get_method_checked (image, token, NULL, &context, &error);
5910 mono_error_set_pending_exception (&error);
5915 ICALL_EXPORT MonoString*
5916 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5918 int index = mono_metadata_token_index (token);
5920 *error = ResolveTokenError_Other;
5922 /* Validate token */
5923 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5924 *error = ResolveTokenError_BadTable;
5928 if (image_is_dynamic (image))
5929 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5931 if ((index <= 0) || (index >= image->heap_us.size)) {
5932 *error = ResolveTokenError_OutOfRange;
5936 /* FIXME: What to do if the index points into the middle of a string ? */
5938 return mono_ldstr (mono_domain_get (), image, index);
5941 ICALL_EXPORT MonoClassField*
5942 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5946 int table = mono_metadata_token_table (token);
5947 int index = mono_metadata_token_index (token);
5948 MonoGenericContext context;
5949 MonoClassField *field;
5951 *resolve_error = ResolveTokenError_Other;
5953 /* Validate token */
5954 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5955 *resolve_error = ResolveTokenError_BadTable;
5959 if (image_is_dynamic (image)) {
5960 if (table == MONO_TABLE_FIELD)
5961 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5963 if (mono_memberref_is_method (image, token)) {
5964 *resolve_error = ResolveTokenError_BadTable;
5968 init_generic_context_from_args (&context, type_args, method_args);
5969 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5972 if ((index <= 0) || (index > image->tables [table].rows)) {
5973 *resolve_error = ResolveTokenError_OutOfRange;
5976 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5977 *resolve_error = ResolveTokenError_BadTable;
5981 init_generic_context_from_args (&context, type_args, method_args);
5982 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5983 mono_error_set_pending_exception (&error);
5989 ICALL_EXPORT MonoObject*
5990 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5994 int table = mono_metadata_token_table (token);
5996 *error = ResolveTokenError_Other;
5999 case MONO_TABLE_TYPEDEF:
6000 case MONO_TABLE_TYPEREF:
6001 case MONO_TABLE_TYPESPEC: {
6002 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6004 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6005 mono_error_raise_exception (&merror);
6012 case MONO_TABLE_METHOD:
6013 case MONO_TABLE_METHODSPEC: {
6014 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6016 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6017 mono_error_raise_exception (&merror);
6023 case MONO_TABLE_FIELD: {
6024 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6026 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6027 mono_error_raise_exception (&merror);
6033 case MONO_TABLE_MEMBERREF:
6034 if (mono_memberref_is_method (image, token)) {
6035 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6037 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6038 mono_error_raise_exception (&merror);
6045 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6047 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6048 mono_error_raise_exception (&merror);
6057 *error = ResolveTokenError_BadTable;
6063 ICALL_EXPORT MonoArray*
6064 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6066 int table = mono_metadata_token_table (token);
6067 int idx = mono_metadata_token_index (token);
6068 MonoTableInfo *tables = image->tables;
6073 *error = ResolveTokenError_OutOfRange;
6075 /* FIXME: Support other tables ? */
6076 if (table != MONO_TABLE_STANDALONESIG)
6079 if (image_is_dynamic (image))
6082 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6085 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6087 ptr = mono_metadata_blob_heap (image, sig);
6088 len = mono_metadata_decode_blob_size (ptr, &ptr);
6090 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6091 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6095 ICALL_EXPORT MonoReflectionType*
6096 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6099 MonoReflectionType *ret;
6101 int isbyref = 0, rank;
6102 char *str = mono_string_to_utf8 (smodifiers);
6105 klass = mono_class_from_mono_type (tb->type.type);
6107 /* logic taken from mono_reflection_parse_type(): keep in sync */
6111 if (isbyref) { /* only one level allowed by the spec */
6120 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6121 mono_error_raise_exception (&error);
6125 klass = mono_ptr_class_get (&klass->byval_arg);
6126 mono_class_init (klass);
6137 else if (*p != '*') { /* '*' means unknown lower bound */
6148 klass = mono_array_class_get (klass, rank);
6149 mono_class_init (klass);
6158 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6159 mono_error_raise_exception (&error);
6164 ICALL_EXPORT MonoBoolean
6165 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6171 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6177 check_for_invalid_type (MonoClass *klass, MonoError *error)
6182 mono_error_init (error);
6184 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6187 name = mono_type_get_full_name (klass);
6188 str = mono_string_new (mono_domain_get (), name);
6190 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6193 ICALL_EXPORT MonoReflectionType *
6194 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6197 MonoReflectionType *ret;
6198 MonoClass *klass, *aklass;
6200 klass = mono_class_from_mono_type (type->type);
6201 check_for_invalid_type (klass, &error);
6202 mono_error_raise_exception (&error);
6204 if (rank == 0) //single dimentional array
6205 aklass = mono_array_class_get (klass, 1);
6207 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6209 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6210 mono_error_raise_exception (&error);
6215 ICALL_EXPORT MonoReflectionType *
6216 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6219 MonoReflectionType *ret;
6222 klass = mono_class_from_mono_type (type->type);
6223 mono_class_init_checked (klass, &error);
6224 mono_error_raise_exception (&error);
6225 check_for_invalid_type (klass, &error);
6226 mono_error_raise_exception (&error);
6228 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6229 mono_error_raise_exception (&error);
6234 ICALL_EXPORT MonoReflectionType *
6235 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6238 MonoReflectionType *ret;
6239 MonoClass *klass, *pklass;
6241 klass = mono_class_from_mono_type (type->type);
6242 mono_class_init_checked (klass, &error);
6243 mono_error_raise_exception (&error);
6244 check_for_invalid_type (klass, &error);
6245 mono_error_raise_exception (&error);
6247 pklass = mono_ptr_class_get (type->type);
6249 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6250 mono_error_raise_exception (&error);
6255 ICALL_EXPORT MonoObject *
6256 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6257 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6260 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6261 MonoObject *delegate;
6263 MonoMethod *method = info->method;
6265 mono_class_init_checked (delegate_class, &error);
6266 mono_error_raise_exception (&error);
6268 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6270 if (mono_security_core_clr_enabled ()) {
6271 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6275 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6276 mono_error_raise_exception (&error);
6278 if (method_is_dynamic (method)) {
6279 /* Creating a trampoline would leak memory */
6280 func = mono_compile_method (method);
6282 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6283 method = mono_object_get_virtual_method (target, method);
6284 func = mono_create_ftnptr (mono_domain_get (),
6285 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6288 mono_delegate_ctor_with_method (delegate, target, func, method);
6293 ICALL_EXPORT MonoMulticastDelegate *
6294 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6297 MonoMulticastDelegate *ret;
6299 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6301 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6302 mono_error_raise_exception (&error);
6303 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6308 ICALL_EXPORT MonoReflectionMethod*
6309 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6311 MonoReflectionMethod *ret = NULL;
6313 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6314 mono_error_raise_exception (&error);
6320 static inline gint32
6321 mono_array_get_byte_length (MonoArray *array)
6327 klass = array->obj.vtable->klass;
6329 if (array->bounds == NULL)
6330 length = array->max_length;
6333 for (i = 0; i < klass->rank; ++ i)
6334 length *= array->bounds [i].length;
6337 switch (klass->element_class->byval_arg.type) {
6340 case MONO_TYPE_BOOLEAN:
6344 case MONO_TYPE_CHAR:
6352 return length * sizeof (gpointer);
6363 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6365 return mono_array_get_byte_length (array);
6369 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6371 return mono_array_get (array, gint8, idx);
6375 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6377 mono_array_set (array, gint8, idx, value);
6380 ICALL_EXPORT MonoBoolean
6381 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6383 guint8 *src_buf, *dest_buf;
6386 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6390 g_assert (count >= 0);
6392 /* This is called directly from the class libraries without going through the managed wrapper */
6393 MONO_CHECK_ARG_NULL (src, FALSE);
6394 MONO_CHECK_ARG_NULL (dest, FALSE);
6396 /* watch out for integer overflow */
6397 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6400 src_buf = (guint8 *)src->vector + src_offset;
6401 dest_buf = (guint8 *)dest->vector + dest_offset;
6404 memcpy (dest_buf, src_buf, count);
6406 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6411 #ifndef DISABLE_REMOTING
6412 ICALL_EXPORT MonoObject *
6413 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6416 MonoDomain *domain = mono_object_domain (this_obj);
6418 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6419 MonoTransparentProxy *tp;
6423 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6424 mono_error_raise_exception (&error);
6425 tp = (MonoTransparentProxy*) res;
6427 MONO_OBJECT_SETREF (tp, rp, rp);
6428 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6429 klass = mono_class_from_mono_type (type);
6431 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6432 mono_class_setup_vtable (klass);
6433 if (mono_class_has_failure (klass)) {
6434 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6438 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6439 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6440 if (!is_ok (&error)) {
6441 mono_error_set_pending_exception (&error);
6445 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6449 ICALL_EXPORT MonoReflectionType *
6450 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6453 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6454 mono_error_raise_exception (&error);
6460 /* System.Environment */
6463 ves_icall_System_Environment_get_UserName (void)
6465 /* using glib is more portable */
6466 return mono_string_new (mono_domain_get (), g_get_user_name ());
6470 ICALL_EXPORT MonoString *
6471 ves_icall_System_Environment_get_MachineName (void)
6473 #if defined (HOST_WIN32)
6478 len = MAX_COMPUTERNAME_LENGTH + 1;
6479 buf = g_new (gunichar2, len);
6482 if (GetComputerName (buf, (PDWORD) &len)) {
6484 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6485 mono_error_raise_exception (&error);
6490 #elif !defined(DISABLE_SOCKETS)
6494 #if defined _SC_HOST_NAME_MAX
6495 n = sysconf (_SC_HOST_NAME_MAX);
6499 buf = g_malloc (n+1);
6501 if (gethostname (buf, n) == 0){
6503 result = mono_string_new (mono_domain_get (), buf);
6510 return mono_string_new (mono_domain_get (), "mono");
6515 ves_icall_System_Environment_get_Platform (void)
6517 #if defined (TARGET_WIN32)
6520 #elif defined(__MACH__)
6523 // Notice that the value is hidden from user code, and only exposed
6524 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6525 // define and making assumptions based on Unix/128/4 values before there
6526 // was a MacOS define. Lots of code would assume that not-Unix meant
6527 // Windows, but in this case, it would be OSX.
6536 ICALL_EXPORT MonoString *
6537 ves_icall_System_Environment_get_NewLine (void)
6539 #if defined (HOST_WIN32)
6540 return mono_string_new (mono_domain_get (), "\r\n");
6542 return mono_string_new (mono_domain_get (), "\n");
6546 ICALL_EXPORT MonoBoolean
6547 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6549 #if SIZEOF_VOID_P == 8
6553 gboolean isWow64Process = FALSE;
6554 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6555 return (MonoBoolean)isWow64Process;
6557 #elif defined(HAVE_SYS_UTSNAME_H)
6558 struct utsname name;
6560 if (uname (&name) >= 0) {
6561 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6568 ICALL_EXPORT MonoString *
6569 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6577 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6578 value = g_getenv (utf8_name);
6585 return mono_string_new (mono_domain_get (), value);
6589 * There is no standard way to get at environ.
6592 #ifndef __MINGW32_VERSION
6593 #if defined(__APPLE__)
6594 #if defined (TARGET_OSX)
6595 /* Apple defines this in crt_externs.h but doesn't provide that header for
6596 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6597 * in fact exist on all implementations (so far)
6599 gchar ***_NSGetEnviron(void);
6600 #define environ (*_NSGetEnviron())
6602 static char *mono_environ[1] = { NULL };
6603 #define environ mono_environ
6604 #endif /* defined (TARGET_OSX) */
6612 ICALL_EXPORT MonoArray *
6613 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6624 env_strings = GetEnvironmentStrings();
6627 env_string = env_strings;
6628 while (*env_string != '\0') {
6629 /* weird case that MS seems to skip */
6630 if (*env_string != '=')
6632 while (*env_string != '\0')
6638 domain = mono_domain_get ();
6639 names = mono_array_new (domain, mono_defaults.string_class, n);
6643 env_string = env_strings;
6644 while (*env_string != '\0') {
6645 /* weird case that MS seems to skip */
6646 if (*env_string != '=') {
6647 equal_str = wcschr(env_string, '=');
6648 g_assert(equal_str);
6650 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6651 mono_error_raise_exception (&error);
6652 mono_array_setref (names, n, str);
6655 while (*env_string != '\0')
6660 FreeEnvironmentStrings (env_strings);
6673 for (e = environ; *e != 0; ++ e)
6676 domain = mono_domain_get ();
6677 names = mono_array_new (domain, mono_defaults.string_class, n);
6680 for (e = environ; *e != 0; ++ e) {
6681 parts = g_strsplit (*e, "=", 2);
6683 str = mono_string_new (domain, *parts);
6684 mono_array_setref (names, n, str);
6697 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6699 #if !GLIB_CHECK_VERSION(2,4,0)
6700 #define g_setenv(a,b,c) setenv(a,b,c)
6701 #define g_unsetenv(a) unsetenv(a)
6705 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6708 gunichar2 *utf16_name, *utf16_value;
6710 gchar *utf8_name, *utf8_value;
6715 utf16_name = mono_string_to_utf16 (name);
6716 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6717 SetEnvironmentVariable (utf16_name, NULL);
6718 g_free (utf16_name);
6722 utf16_value = mono_string_to_utf16 (value);
6724 SetEnvironmentVariable (utf16_name, utf16_value);
6726 g_free (utf16_name);
6727 g_free (utf16_value);
6729 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6731 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6732 g_unsetenv (utf8_name);
6737 utf8_value = mono_string_to_utf8_checked (value, &error);
6738 if (!mono_error_ok (&error)) {
6740 mono_error_set_pending_exception (&error);
6743 g_setenv (utf8_name, utf8_value, TRUE);
6746 g_free (utf8_value);
6751 ves_icall_System_Environment_Exit (int result)
6753 mono_environment_exitcode_set (result);
6755 /* FIXME: There are some cleanup hangs that should be worked out, but
6756 * if the program is going to exit, everything will be cleaned up when
6757 * NaCl exits anyway.
6759 #ifndef __native_client__
6760 if (!mono_runtime_try_shutdown ())
6761 mono_thread_exit ();
6763 /* Suspend all managed threads since the runtime is going away */
6764 mono_thread_suspend_all_other_threads ();
6766 mono_runtime_quit ();
6769 /* we may need to do some cleanup here... */
6773 ICALL_EXPORT MonoString*
6774 ves_icall_System_Environment_GetGacPath (void)
6776 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6779 ICALL_EXPORT MonoString*
6780 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6782 #if defined (HOST_WIN32)
6783 #ifndef CSIDL_FLAG_CREATE
6784 #define CSIDL_FLAG_CREATE 0x8000
6787 WCHAR path [MAX_PATH];
6788 /* Create directory if no existing */
6789 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6794 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6795 mono_error_raise_exception (&error);
6799 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6801 return mono_string_new (mono_domain_get (), "");
6804 ICALL_EXPORT MonoArray *
6805 ves_icall_System_Environment_GetLogicalDrives (void)
6808 gunichar2 buf [256], *ptr, *dname;
6810 guint initial_size = 127, size = 128;
6813 MonoString *drivestr;
6814 MonoDomain *domain = mono_domain_get ();
6820 while (size > initial_size) {
6821 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6822 if (size > initial_size) {
6825 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6826 initial_size = size;
6840 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6845 while (*u16) { u16++; len ++; }
6846 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6847 mono_error_raise_exception (&error);
6848 mono_array_setref (result, ndrives++, drivestr);
6858 ICALL_EXPORT MonoString *
6859 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6861 gunichar2 volume_name [MAX_PATH + 1];
6863 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6865 return mono_string_from_utf16 (volume_name);
6868 ICALL_EXPORT MonoString *
6869 ves_icall_System_Environment_InternalGetHome (void)
6871 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6874 static const char *encodings [] = {
6876 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6877 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6878 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6880 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6881 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6882 "x_unicode_2_0_utf_7",
6884 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6885 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6887 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6890 "unicodefffe", "utf_16be",
6897 * Returns the internal codepage, if the value of "int_code_page" is
6898 * 1 at entry, and we can not compute a suitable code page number,
6899 * returns the code page as a string
6901 ICALL_EXPORT MonoString*
6902 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6907 char *codepage = NULL;
6909 int want_name = *int_code_page;
6912 *int_code_page = -1;
6914 g_get_charset (&cset);
6915 c = codepage = strdup (cset);
6916 for (c = codepage; *c; c++){
6917 if (isascii (*c) && isalpha (*c))
6922 /* g_print ("charset: %s\n", cset); */
6924 /* handle some common aliases */
6927 for (i = 0; p != 0; ){
6930 p = encodings [++i];
6933 if (strcmp (p, codepage) == 0){
6934 *int_code_page = code;
6937 p = encodings [++i];
6940 if (strstr (codepage, "utf_8") != NULL)
6941 *int_code_page |= 0x10000000;
6944 if (want_name && *int_code_page == -1)
6945 return mono_string_new (mono_domain_get (), cset);
6950 ICALL_EXPORT MonoBoolean
6951 ves_icall_System_Environment_get_HasShutdownStarted (void)
6953 if (mono_runtime_is_shutting_down ())
6956 if (mono_domain_is_unloading (mono_domain_get ()))
6963 ves_icall_System_Environment_BroadcastSettingChange (void)
6966 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6971 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6977 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6978 MonoReflectionMethod *method,
6979 MonoArray *out_args)
6981 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6984 #ifndef DISABLE_REMOTING
6985 ICALL_EXPORT MonoBoolean
6986 ves_icall_IsTransparentProxy (MonoObject *proxy)
6991 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6997 ICALL_EXPORT MonoReflectionMethod *
6998 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6999 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7001 MonoReflectionMethod *ret = NULL;
7006 MonoMethod **vtable;
7007 MonoMethod *res = NULL;
7009 MONO_CHECK_ARG_NULL (rtype, NULL);
7010 MONO_CHECK_ARG_NULL (rmethod, NULL);
7012 method = rmethod->method;
7013 klass = mono_class_from_mono_type (rtype->type);
7014 mono_class_init_checked (klass, &error);
7015 mono_error_raise_exception (&error);
7017 if (MONO_CLASS_IS_INTERFACE (klass))
7020 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7023 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7024 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7030 mono_class_setup_vtable (klass);
7031 vtable = klass->vtable;
7033 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7034 gboolean variance_used = FALSE;
7035 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7036 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7038 res = vtable [offs + method->slot];
7040 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7043 if (method->slot != -1)
7044 res = vtable [method->slot];
7050 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7051 mono_error_raise_exception (&error);
7056 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7062 klass = mono_class_from_mono_type (type->type);
7063 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7064 if (!is_ok (&error)) {
7065 mono_error_set_pending_exception (&error);
7069 mono_vtable_set_is_remote (vtable, enable);
7072 #else /* DISABLE_REMOTING */
7075 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7077 g_assert_not_reached ();
7082 ICALL_EXPORT MonoObject *
7083 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7090 domain = mono_object_domain (type);
7091 klass = mono_class_from_mono_type (type->type);
7092 mono_class_init_checked (klass, &error);
7093 mono_error_raise_exception (&error);
7095 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7096 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7100 if (klass->rank >= 1) {
7101 g_assert (klass->rank == 1);
7102 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7104 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7105 if (!is_ok (&error)) {
7106 mono_error_set_pending_exception (&error);
7109 /* Bypass remoting object creation check */
7110 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7111 mono_error_set_pending_exception (&error);
7117 ICALL_EXPORT MonoString *
7118 ves_icall_System_IO_get_temp_path (void)
7120 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7123 #ifndef PLATFORM_NO_DRIVEINFO
7124 ICALL_EXPORT MonoBoolean
7125 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7126 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7130 ULARGE_INTEGER wapi_free_bytes_avail;
7131 ULARGE_INTEGER wapi_total_number_of_bytes;
7132 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7134 *error = ERROR_SUCCESS;
7135 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7136 &wapi_total_number_of_free_bytes);
7139 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7140 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7141 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7143 *free_bytes_avail = 0;
7144 *total_number_of_bytes = 0;
7145 *total_number_of_free_bytes = 0;
7146 *error = GetLastError ();
7152 ICALL_EXPORT guint32
7153 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7155 return GetDriveType (mono_string_chars (root_path_name));
7159 ICALL_EXPORT gpointer
7160 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7162 return mono_compile_method (method);
7165 ICALL_EXPORT MonoString *
7166 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7171 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7173 #if defined (HOST_WIN32)
7174 /* Avoid mixing '/' and '\\' */
7177 for (i = strlen (path) - 1; i >= 0; i--)
7178 if (path [i] == '/')
7182 mcpath = mono_string_new (mono_domain_get (), path);
7189 get_bundled_app_config (void)
7191 const gchar *app_config;
7194 gchar *config_file_name, *config_file_path;
7195 gsize len, config_file_path_length, config_ext_length;
7198 domain = mono_domain_get ();
7199 file = domain->setup->configuration_file;
7200 if (!file || file->length == 0)
7203 // Retrieve config file and remove the extension
7204 config_file_name = mono_string_to_utf8 (file);
7205 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7206 if (!config_file_path)
7207 config_file_path = config_file_name;
7209 config_file_path_length = strlen (config_file_path);
7210 config_ext_length = strlen (".config");
7211 if (config_file_path_length <= config_ext_length)
7214 len = config_file_path_length - config_ext_length;
7215 module = (gchar *)g_malloc0 (len + 1);
7216 memcpy (module, config_file_path, len);
7217 // Get the config file from the module name
7218 app_config = mono_config_string_for_assembly_file (module);
7221 if (config_file_name != config_file_path)
7222 g_free (config_file_name);
7223 g_free (config_file_path);
7228 return mono_string_new (mono_domain_get (), app_config);
7232 get_bundled_machine_config (void)
7234 const gchar *machine_config;
7236 machine_config = mono_get_machine_config ();
7238 if (!machine_config)
7241 return mono_string_new (mono_domain_get (), machine_config);
7244 ICALL_EXPORT MonoString *
7245 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7250 path = g_path_get_dirname (mono_get_config_dir ());
7252 #if defined (HOST_WIN32)
7253 /* Avoid mixing '/' and '\\' */
7256 for (i = strlen (path) - 1; i >= 0; i--)
7257 if (path [i] == '/')
7261 ipath = mono_string_new (mono_domain_get (), path);
7267 ICALL_EXPORT gboolean
7268 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7270 MonoPEResourceDataEntry *entry;
7273 if (!assembly || !result || !size)
7278 image = assembly->assembly->image;
7279 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7283 *result = mono_image_rva_map (image, entry->rde_data_offset);
7288 *size = entry->rde_size;
7293 ICALL_EXPORT MonoBoolean
7294 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7296 return mono_is_debugger_attached ();
7299 ICALL_EXPORT MonoBoolean
7300 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7302 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7303 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7309 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7311 if (mono_get_runtime_callbacks ()->debug_log)
7312 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7316 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7318 #if defined (HOST_WIN32)
7319 OutputDebugString (mono_string_chars (message));
7321 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7325 /* Only used for value types */
7326 ICALL_EXPORT MonoObject *
7327 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7334 domain = mono_object_domain (type);
7335 klass = mono_class_from_mono_type (type->type);
7336 mono_class_init_checked (klass, &error);
7337 mono_error_raise_exception (&error);
7339 if (mono_class_is_nullable (klass))
7340 /* No arguments -> null */
7343 result = mono_object_new_checked (domain, klass, &error);
7344 mono_error_raise_exception (&error);
7348 ICALL_EXPORT MonoReflectionMethod *
7349 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7351 MonoReflectionMethod *ret = NULL;
7354 MonoClass *klass, *parent;
7355 MonoGenericContext *generic_inst = NULL;
7356 MonoMethod *method = m->method;
7357 MonoMethod *result = NULL;
7360 if (method->klass == NULL)
7363 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7364 MONO_CLASS_IS_INTERFACE (method->klass) ||
7365 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7368 slot = mono_method_get_vtable_slot (method);
7372 klass = method->klass;
7373 if (klass->generic_class) {
7374 generic_inst = mono_class_get_context (klass);
7375 klass = klass->generic_class->container_class;
7379 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7380 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7381 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7382 or klass is the generic container class and generic_inst is the instantiation.
7384 when we go to the parent, if the parent is an open constructed type, we need to
7385 replace the type parameters by the definitions from the generic_inst, and then take it
7386 apart again into the klass and the generic_inst.
7388 For cases like this:
7389 class C<T> : B<T, int> {
7390 public override void Foo () { ... }
7392 class B<U,V> : A<HashMap<U,V>> {
7393 public override void Foo () { ... }
7396 public virtual void Foo () { ... }
7399 if at each iteration the parent isn't open, we can skip inflating it. if at some
7400 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7403 MonoGenericContext *parent_inst = NULL;
7404 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7406 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7407 if (!mono_error_ok (&error)) {
7408 mono_error_set_pending_exception (&error);
7412 if (parent->generic_class) {
7413 parent_inst = mono_class_get_context (parent);
7414 parent = parent->generic_class->container_class;
7417 mono_class_setup_vtable (parent);
7418 if (parent->vtable_size <= slot)
7421 generic_inst = parent_inst;
7424 klass = klass->parent;
7427 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7428 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7429 if (!mono_error_ok (&error)) {
7430 mono_error_set_pending_exception (&error);
7434 generic_inst = NULL;
7436 if (klass->generic_class) {
7437 generic_inst = mono_class_get_context (klass);
7438 klass = klass->generic_class->container_class;
7444 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7445 if (!mono_error_ok (&error)) {
7446 mono_error_set_pending_exception (&error);
7451 if (klass == method->klass)
7454 /*This is possible if definition == FALSE.
7455 * Do it here to be really sure we don't read invalid memory.
7457 if (slot >= klass->vtable_size)
7460 mono_class_setup_vtable (klass);
7462 result = klass->vtable [slot];
7463 if (result == NULL) {
7464 /* It is an abstract method */
7465 gpointer iter = NULL;
7466 while ((result = mono_class_get_methods (klass, &iter)))
7467 if (result->slot == slot)
7474 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7475 mono_error_raise_exception (&error);
7479 ICALL_EXPORT MonoString*
7480 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7482 MonoMethod *method = m->method;
7484 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7489 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7491 iter->sig = *(MonoMethodSignature**)argsp;
7493 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7494 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7497 /* FIXME: it's not documented what start is exactly... */
7501 iter->args = argsp + sizeof (gpointer);
7503 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7505 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7508 ICALL_EXPORT MonoTypedRef
7509 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7511 guint32 i, arg_size;
7515 i = iter->sig->sentinelpos + iter->next_arg;
7517 g_assert (i < iter->sig->param_count);
7519 res.type = iter->sig->params [i];
7520 res.klass = mono_class_from_mono_type (res.type);
7521 arg_size = mono_type_stack_size (res.type, &align);
7522 #if defined(__arm__) || defined(__mips__)
7523 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7525 res.value = iter->args;
7526 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7527 /* Values are stored as 8 byte register sized objects, but 'value'
7528 * is dereferenced as a pointer in other routines.
7530 res.value = (char*)res.value + 4;
7532 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7533 if (arg_size <= sizeof (gpointer)) {
7535 int padding = arg_size - mono_type_size (res.type, &dummy);
7536 res.value = (guint8*)res.value + padding;
7539 iter->args = (char*)iter->args + arg_size;
7542 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7547 ICALL_EXPORT MonoTypedRef
7548 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7550 guint32 i, arg_size;
7554 i = iter->sig->sentinelpos + iter->next_arg;
7556 g_assert (i < iter->sig->param_count);
7558 while (i < iter->sig->param_count) {
7559 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7561 res.type = iter->sig->params [i];
7562 res.klass = mono_class_from_mono_type (res.type);
7563 /* FIXME: endianess issue... */
7564 arg_size = mono_type_stack_size (res.type, &align);
7565 #if defined(__arm__) || defined(__mips__)
7566 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7568 res.value = iter->args;
7569 iter->args = (char*)iter->args + arg_size;
7571 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7574 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7582 ICALL_EXPORT MonoType*
7583 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7587 i = iter->sig->sentinelpos + iter->next_arg;
7589 g_assert (i < iter->sig->param_count);
7591 return iter->sig->params [i];
7594 ICALL_EXPORT MonoObject*
7595 mono_TypedReference_ToObject (MonoTypedRef* tref)
7597 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7598 MonoObject** objp = (MonoObject **)tref->value;
7602 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7605 ICALL_EXPORT MonoTypedRef
7606 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7609 MonoReflectionField *f;
7611 MonoType *ftype = NULL;
7615 memset (&res, 0, sizeof (res));
7618 g_assert (mono_array_length (fields) > 0);
7620 klass = target->vtable->klass;
7622 for (i = 0; i < mono_array_length (fields); ++i) {
7623 f = mono_array_get (fields, MonoReflectionField*, i);
7625 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7628 if (f->field->parent != klass) {
7629 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7633 p = (guint8*)target + f->field->offset;
7635 p += f->field->offset - sizeof (MonoObject);
7636 klass = mono_class_from_mono_type (f->field->type);
7637 ftype = f->field->type;
7641 res.klass = mono_class_from_mono_type (ftype);
7648 prelink_method (MonoMethod *method, MonoError *error)
7650 const char *exc_class, *exc_arg;
7652 mono_error_init (error);
7653 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7655 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7657 mono_error_set_exception_instance (error,
7658 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7661 /* create the wrapper, too? */
7665 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7669 prelink_method (method->method, &error);
7670 mono_error_raise_exception (&error);
7674 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7677 MonoClass *klass = mono_class_from_mono_type (type->type);
7679 gpointer iter = NULL;
7681 mono_class_init_checked (klass, &error);
7682 mono_error_raise_exception (&error);
7684 while ((m = mono_class_get_methods (klass, &iter))) {
7685 prelink_method (m, &error);
7686 mono_error_raise_exception (&error);
7690 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7692 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7693 gint32 const **exponents,
7694 gunichar2 const **digitLowerTable,
7695 gunichar2 const **digitUpperTable,
7696 gint64 const **tenPowersList,
7697 gint32 const **decHexDigits)
7699 *mantissas = Formatter_MantissaBitsTable;
7700 *exponents = Formatter_TensExponentTable;
7701 *digitLowerTable = Formatter_DigitLowerTable;
7702 *digitUpperTable = Formatter_DigitUpperTable;
7703 *tenPowersList = Formatter_TenPowersList;
7704 *decHexDigits = Formatter_DecHexDigits;
7708 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7709 * and avoid useless allocations.
7712 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7714 MonoReflectionType *rt;
7718 mono_error_init (error);
7719 for (i = 0; i < type->num_mods; ++i) {
7720 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7725 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7727 for (i = 0; i < type->num_mods; ++i) {
7728 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7729 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7730 return_val_if_nok (error, NULL);
7732 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7733 return_val_if_nok (error, NULL);
7735 mono_array_setref (res, count, rt);
7742 ICALL_EXPORT MonoArray*
7743 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7746 MonoType *type = param->ClassImpl->type;
7747 MonoClass *member_class = mono_object_class (param->MemberImpl);
7748 MonoMethod *method = NULL;
7751 MonoMethodSignature *sig;
7754 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7755 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7756 method = rmethod->method;
7757 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7758 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7759 if (!(method = prop->property->get))
7760 method = prop->property->set;
7763 char *type_name = mono_type_get_full_name (member_class);
7764 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7765 MonoException *ex = mono_get_exception_not_supported (msg);
7768 mono_set_pending_exception (ex);
7772 image = method->klass->image;
7773 pos = param->PositionImpl;
7774 sig = mono_method_signature (method);
7778 type = sig->params [pos];
7780 res = type_array_from_modifiers (image, type, optional, &error);
7781 mono_error_raise_exception (&error);
7786 get_property_type (MonoProperty *prop)
7788 MonoMethodSignature *sig;
7790 sig = mono_method_signature (prop->get);
7792 } else if (prop->set) {
7793 sig = mono_method_signature (prop->set);
7794 return sig->params [sig->param_count - 1];
7799 ICALL_EXPORT MonoArray*
7800 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7803 MonoType *type = get_property_type (property->property);
7804 MonoImage *image = property->klass->image;
7809 res = type_array_from_modifiers (image, type, optional, &error);
7810 mono_error_raise_exception (&error);
7815 *Construct a MonoType suited to be used to decode a constant blob object.
7817 * @type is the target type which will be constructed
7818 * @blob_type is the blob type, for example, that comes from the constant table
7819 * @real_type is the expected constructed type.
7822 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7824 type->type = blob_type;
7825 type->data.klass = NULL;
7826 if (blob_type == MONO_TYPE_CLASS)
7827 type->data.klass = mono_defaults.object_class;
7828 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7829 /* For enums, we need to use the base type */
7830 type->type = MONO_TYPE_VALUETYPE;
7831 type->data.klass = mono_class_from_mono_type (real_type);
7833 type->data.klass = mono_class_from_mono_type (real_type);
7836 ICALL_EXPORT MonoObject*
7837 property_info_get_default_value (MonoReflectionProperty *property)
7841 MonoProperty *prop = property->property;
7842 MonoType *type = get_property_type (prop);
7843 MonoDomain *domain = mono_object_domain (property);
7844 MonoTypeEnum def_type;
7845 const char *def_value;
7848 mono_class_init (prop->parent);
7850 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7851 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7855 def_value = mono_class_get_property_default_value (prop, &def_type);
7857 mono_type_from_blob_type (&blob_type, def_type, type);
7858 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7860 mono_error_set_pending_exception (&error);
7864 ICALL_EXPORT MonoBoolean
7865 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7868 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7869 MonoCustomAttrInfo *cinfo;
7872 mono_class_init_checked (attr_class, &error);
7873 mono_error_raise_exception (&error);
7875 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7876 if (!is_ok (&error)) {
7877 mono_error_set_pending_exception (&error);
7882 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7884 mono_custom_attrs_free (cinfo);
7888 ICALL_EXPORT MonoArray*
7889 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7891 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7896 mono_class_init_checked (attr_class, &error);
7897 mono_error_raise_exception (&error);
7900 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7901 if (!mono_error_ok (&error)) {
7902 mono_error_set_pending_exception (&error);
7906 if (mono_loader_get_last_error ()) {
7907 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7914 ICALL_EXPORT MonoArray*
7915 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7919 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7920 mono_error_set_pending_exception (&error);
7925 ICALL_EXPORT MonoString*
7926 ves_icall_Mono_Runtime_GetDisplayName (void)
7929 MonoString *display_name;
7931 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7932 display_name = mono_string_new (mono_domain_get (), info);
7934 return display_name;
7937 ICALL_EXPORT MonoString*
7938 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7941 MonoString *message;
7945 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7946 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7949 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7951 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7952 mono_error_raise_exception (&error);
7959 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7962 char *path_str = mono_string_to_utf8 (path);
7964 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7972 ICALL_EXPORT gpointer
7973 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7975 return GetCurrentProcess ();
7978 ICALL_EXPORT MonoBoolean
7979 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7981 return GetExitCodeProcess (handle, (guint32*) exitcode);
7984 ICALL_EXPORT MonoBoolean
7985 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7987 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7988 return CloseHandle (handle);
7990 return CloseProcess (handle);
7994 ICALL_EXPORT MonoBoolean
7995 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
7997 return TerminateProcess (handle, exitcode);
8001 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8003 return WaitForInputIdle (handle, milliseconds);
8006 ICALL_EXPORT MonoBoolean
8007 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8009 return GetProcessWorkingSetSize (handle, min, max);
8012 ICALL_EXPORT MonoBoolean
8013 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8015 return SetProcessWorkingSetSize (handle, min, max);
8018 ICALL_EXPORT MonoBoolean
8019 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8021 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8025 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8027 return mono_process_current_pid ();
8031 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8033 return GetPriorityClass (handle);
8036 ICALL_EXPORT MonoBoolean
8037 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8039 return SetPriorityClass (handle, priorityClass);
8042 #ifndef DISABLE_ICALL_TABLES
8044 #define ICALL_TYPE(id,name,first)
8045 #define ICALL(id,name,func) Icall_ ## id,
8048 #include "metadata/icall-def.h"
8054 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8055 #define ICALL(id,name,func)
8057 #include "metadata/icall-def.h"
8063 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8064 #define ICALL(id,name,func)
8066 guint16 first_icall;
8069 static const IcallTypeDesc
8070 icall_type_descs [] = {
8071 #include "metadata/icall-def.h"
8075 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8078 #define ICALL_TYPE(id,name,first)
8081 #ifdef HAVE_ARRAY_ELEM_INIT
8082 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8083 #define MSGSTRFIELD1(line) str##line
8085 static const struct msgstrtn_t {
8086 #define ICALL(id,name,func)
8088 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8089 #include "metadata/icall-def.h"
8091 } icall_type_names_str = {
8092 #define ICALL_TYPE(id,name,first) (name),
8093 #include "metadata/icall-def.h"
8096 static const guint16 icall_type_names_idx [] = {
8097 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8098 #include "metadata/icall-def.h"
8101 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8103 static const struct msgstr_t {
8105 #define ICALL_TYPE(id,name,first)
8106 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8107 #include "metadata/icall-def.h"
8109 } icall_names_str = {
8110 #define ICALL(id,name,func) (name),
8111 #include "metadata/icall-def.h"
8114 static const guint16 icall_names_idx [] = {
8115 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8116 #include "metadata/icall-def.h"
8119 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8125 #define ICALL_TYPE(id,name,first) name,
8126 #define ICALL(id,name,func)
8127 static const char* const
8128 icall_type_names [] = {
8129 #include "metadata/icall-def.h"
8133 #define icall_type_name_get(id) (icall_type_names [(id)])
8137 #define ICALL_TYPE(id,name,first)
8138 #define ICALL(id,name,func) name,
8139 static const char* const
8141 #include "metadata/icall-def.h"
8144 #define icall_name_get(id) icall_names [(id)]
8146 #endif /* !HAVE_ARRAY_ELEM_INIT */
8150 #define ICALL_TYPE(id,name,first)
8151 #define ICALL(id,name,func) func,
8152 static const gconstpointer
8153 icall_functions [] = {
8154 #include "metadata/icall-def.h"
8158 #ifdef ENABLE_ICALL_SYMBOL_MAP
8161 #define ICALL_TYPE(id,name,first)
8162 #define ICALL(id,name,func) #func,
8163 static const gconstpointer
8164 icall_symbols [] = {
8165 #include "metadata/icall-def.h"
8170 #endif /* DISABLE_ICALL_TABLES */
8172 static mono_mutex_t icall_mutex;
8173 static GHashTable *icall_hash = NULL;
8174 static GHashTable *jit_icall_hash_name = NULL;
8175 static GHashTable *jit_icall_hash_addr = NULL;
8178 mono_icall_init (void)
8180 #ifndef DISABLE_ICALL_TABLES
8183 /* check that tables are sorted: disable in release */
8186 const char *prev_class = NULL;
8187 const char *prev_method;
8189 for (i = 0; i < Icall_type_num; ++i) {
8190 const IcallTypeDesc *desc;
8193 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8194 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8195 prev_class = icall_type_name_get (i);
8196 desc = &icall_type_descs [i];
8197 num_icalls = icall_desc_num_icalls (desc);
8198 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8199 for (j = 0; j < num_icalls; ++j) {
8200 const char *methodn = icall_name_get (desc->first_icall + j);
8201 if (prev_method && strcmp (prev_method, methodn) >= 0)
8202 g_print ("method %s should come before method %s\n", methodn, prev_method);
8203 prev_method = methodn;
8209 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8210 mono_os_mutex_init (&icall_mutex);
8214 mono_icall_lock (void)
8216 mono_locks_os_acquire (&icall_mutex, IcallLock);
8220 mono_icall_unlock (void)
8222 mono_locks_os_release (&icall_mutex, IcallLock);
8226 mono_icall_cleanup (void)
8228 g_hash_table_destroy (icall_hash);
8229 g_hash_table_destroy (jit_icall_hash_name);
8230 g_hash_table_destroy (jit_icall_hash_addr);
8231 mono_os_mutex_destroy (&icall_mutex);
8235 * mono_add_internal_call:
8236 * @name: method specification to surface to the managed world
8237 * @method: pointer to a C method to invoke when the method is called
8239 * This method surfaces the C function pointed by @method as a method
8240 * that has been surfaced in managed code with the method specified in
8241 * @name as an internal call.
8243 * Internal calls are surfaced to all app domains loaded and they are
8244 * accessibly by a type with the specified name.
8246 * You must provide a fully qualified type name, that is namespaces
8247 * and type name, followed by a colon and the method name, with an
8248 * optional signature to bind.
8250 * For example, the following are all valid declarations:
8252 * "MyApp.Services.ScriptService:Accelerate"
8253 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8255 * You use method parameters in cases where there might be more than
8256 * one surface method to managed code. That way you can register different
8257 * internal calls for different method overloads.
8259 * The internal calls are invoked with no marshalling. This means that .NET
8260 * types like System.String are exposed as `MonoString *` parameters. This is
8261 * different than the way that strings are surfaced in P/Invoke.
8263 * For more information on how the parameters are marshalled, see the
8264 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8267 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8268 * reference for more information on the format of method descriptions.
8271 mono_add_internal_call (const char *name, gconstpointer method)
8275 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8277 mono_icall_unlock ();
8280 #ifndef DISABLE_ICALL_TABLES
8282 #ifdef HAVE_ARRAY_ELEM_INIT
8284 compare_method_imap (const void *key, const void *elem)
8286 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8287 return strcmp (key, method_name);
8291 find_method_icall (const IcallTypeDesc *imap, const char *name)
8293 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);
8296 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8300 compare_class_imap (const void *key, const void *elem)
8302 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8303 return strcmp (key, class_name);
8306 static const IcallTypeDesc*
8307 find_class_icalls (const char *name)
8309 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);
8312 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8315 #else /* HAVE_ARRAY_ELEM_INIT */
8318 compare_method_imap (const void *key, const void *elem)
8320 const char** method_name = (const char**)elem;
8321 return strcmp (key, *method_name);
8325 find_method_icall (const IcallTypeDesc *imap, const char *name)
8327 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8330 return (gpointer)icall_functions [(nameslot - icall_names)];
8334 compare_class_imap (const void *key, const void *elem)
8336 const char** class_name = (const char**)elem;
8337 return strcmp (key, *class_name);
8340 static const IcallTypeDesc*
8341 find_class_icalls (const char *name)
8343 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8346 return &icall_type_descs [nameslot - icall_type_names];
8349 #endif /* HAVE_ARRAY_ELEM_INIT */
8351 #endif /* DISABLE_ICALL_TABLES */
8354 * we should probably export this as an helper (handle nested types).
8355 * Returns the number of chars written in buf.
8358 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8360 int nspacelen, cnamelen;
8361 nspacelen = strlen (klass->name_space);
8362 cnamelen = strlen (klass->name);
8363 if (nspacelen + cnamelen + 2 > bufsize)
8366 memcpy (buf, klass->name_space, nspacelen);
8367 buf [nspacelen ++] = '.';
8369 memcpy (buf + nspacelen, klass->name, cnamelen);
8370 buf [nspacelen + cnamelen] = 0;
8371 return nspacelen + cnamelen;
8374 #ifdef DISABLE_ICALL_TABLES
8376 no_icall_table (void)
8378 g_assert_not_reached ();
8383 mono_lookup_internal_call (MonoMethod *method)
8388 int typelen = 0, mlen, siglen;
8390 #ifndef DISABLE_ICALL_TABLES
8391 const IcallTypeDesc *imap = NULL;
8394 g_assert (method != NULL);
8396 if (method->is_inflated)
8397 method = ((MonoMethodInflated *) method)->declaring;
8399 if (method->klass->nested_in) {
8400 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8404 mname [pos++] = '/';
8407 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8413 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8418 #ifndef DISABLE_ICALL_TABLES
8419 imap = find_class_icalls (mname);
8422 mname [typelen] = ':';
8423 mname [typelen + 1] = ':';
8425 mlen = strlen (method->name);
8426 memcpy (mname + typelen + 2, method->name, mlen);
8427 sigstart = mname + typelen + 2 + mlen;
8430 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8431 siglen = strlen (tmpsig);
8432 if (typelen + mlen + siglen + 6 > sizeof (mname))
8435 memcpy (sigstart + 1, tmpsig, siglen);
8436 sigstart [siglen + 1] = ')';
8437 sigstart [siglen + 2] = 0;
8442 res = g_hash_table_lookup (icall_hash, mname);
8444 mono_icall_unlock ();;
8447 /* try without signature */
8449 res = g_hash_table_lookup (icall_hash, mname);
8451 mono_icall_unlock ();
8455 #ifdef DISABLE_ICALL_TABLES
8456 mono_icall_unlock ();
8457 /* Fail only when the result is actually used */
8458 /* mono_marshal_get_native_wrapper () depends on this */
8459 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8460 return ves_icall_System_String_ctor_RedirectToCreateString;
8462 return no_icall_table;
8464 /* it wasn't found in the static call tables */
8466 mono_icall_unlock ();
8469 res = find_method_icall (imap, sigstart - mlen);
8471 mono_icall_unlock ();
8474 /* try _with_ signature */
8476 res = find_method_icall (imap, sigstart - mlen);
8478 mono_icall_unlock ();
8482 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8483 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8484 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8485 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8486 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");
8487 g_print ("If you see other errors or faults after this message they are probably related\n");
8488 g_print ("and you need to fix your mono install first.\n");
8490 mono_icall_unlock ();
8496 #ifdef ENABLE_ICALL_SYMBOL_MAP
8498 func_cmp (gconstpointer key, gconstpointer p)
8500 return (gsize)key - (gsize)*(gsize*)p;
8505 * mono_lookup_icall_symbol:
8507 * Given the icall METHOD, returns its C symbol.
8510 mono_lookup_icall_symbol (MonoMethod *m)
8512 #ifdef DISABLE_ICALL_TABLES
8513 g_assert_not_reached ();
8516 #ifdef ENABLE_ICALL_SYMBOL_MAP
8520 static gconstpointer *functions_sorted;
8521 static const char**symbols_sorted;
8522 static gboolean inited;
8527 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8528 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8529 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8530 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8531 /* Bubble sort the two arrays */
8535 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8536 if (functions_sorted [i] > functions_sorted [i + 1]) {
8539 tmp = functions_sorted [i];
8540 functions_sorted [i] = functions_sorted [i + 1];
8541 functions_sorted [i + 1] = tmp;
8542 tmp = symbols_sorted [i];
8543 symbols_sorted [i] = symbols_sorted [i + 1];
8544 symbols_sorted [i + 1] = tmp;
8551 func = mono_lookup_internal_call (m);
8554 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8558 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8560 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8561 g_assert_not_reached ();
8568 type_from_typename (char *type_name)
8570 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8572 if (!strcmp (type_name, "int"))
8573 klass = mono_defaults.int_class;
8574 else if (!strcmp (type_name, "ptr"))
8575 klass = mono_defaults.int_class;
8576 else if (!strcmp (type_name, "void"))
8577 klass = mono_defaults.void_class;
8578 else if (!strcmp (type_name, "int32"))
8579 klass = mono_defaults.int32_class;
8580 else if (!strcmp (type_name, "uint32"))
8581 klass = mono_defaults.uint32_class;
8582 else if (!strcmp (type_name, "int8"))
8583 klass = mono_defaults.sbyte_class;
8584 else if (!strcmp (type_name, "uint8"))
8585 klass = mono_defaults.byte_class;
8586 else if (!strcmp (type_name, "int16"))
8587 klass = mono_defaults.int16_class;
8588 else if (!strcmp (type_name, "uint16"))
8589 klass = mono_defaults.uint16_class;
8590 else if (!strcmp (type_name, "long"))
8591 klass = mono_defaults.int64_class;
8592 else if (!strcmp (type_name, "ulong"))
8593 klass = mono_defaults.uint64_class;
8594 else if (!strcmp (type_name, "float"))
8595 klass = mono_defaults.single_class;
8596 else if (!strcmp (type_name, "double"))
8597 klass = mono_defaults.double_class;
8598 else if (!strcmp (type_name, "object"))
8599 klass = mono_defaults.object_class;
8600 else if (!strcmp (type_name, "obj"))
8601 klass = mono_defaults.object_class;
8602 else if (!strcmp (type_name, "string"))
8603 klass = mono_defaults.string_class;
8604 else if (!strcmp (type_name, "bool"))
8605 klass = mono_defaults.boolean_class;
8606 else if (!strcmp (type_name, "boolean"))
8607 klass = mono_defaults.boolean_class;
8609 g_error ("%s", type_name);
8610 g_assert_not_reached ();
8612 return &klass->byval_arg;
8616 * LOCKING: Take the corlib image lock.
8618 MonoMethodSignature*
8619 mono_create_icall_signature (const char *sigstr)
8624 MonoMethodSignature *res, *res2;
8625 MonoImage *corlib = mono_defaults.corlib;
8627 mono_image_lock (corlib);
8628 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8629 mono_image_unlock (corlib);
8634 parts = g_strsplit (sigstr, " ", 256);
8643 res = mono_metadata_signature_alloc (corlib, len - 1);
8648 * Under windows, the default pinvoke calling convention is STDCALL but
8651 res->call_convention = MONO_CALL_C;
8654 res->ret = type_from_typename (parts [0]);
8655 for (i = 1; i < len; ++i) {
8656 res->params [i - 1] = type_from_typename (parts [i]);
8661 mono_image_lock (corlib);
8662 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8664 res = res2; /*Value is allocated in the image pool*/
8666 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8667 mono_image_unlock (corlib);
8673 mono_find_jit_icall_by_name (const char *name)
8675 MonoJitICallInfo *info;
8676 g_assert (jit_icall_hash_name);
8679 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8680 mono_icall_unlock ();
8685 mono_find_jit_icall_by_addr (gconstpointer addr)
8687 MonoJitICallInfo *info;
8688 g_assert (jit_icall_hash_addr);
8691 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8692 mono_icall_unlock ();
8698 * mono_get_jit_icall_info:
8700 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8701 * caller should access it while holding the icall lock.
8704 mono_get_jit_icall_info (void)
8706 return jit_icall_hash_name;
8710 * mono_lookup_jit_icall_symbol:
8712 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8715 mono_lookup_jit_icall_symbol (const char *name)
8717 MonoJitICallInfo *info;
8718 const char *res = NULL;
8721 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8723 res = info->c_symbol;
8724 mono_icall_unlock ();
8729 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8732 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8733 mono_icall_unlock ();
8737 * 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
8738 * icalls without wrappers in some cases.
8741 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8743 MonoJitICallInfo *info;
8750 if (!jit_icall_hash_name) {
8751 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8752 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8755 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8756 g_warning ("jit icall already defined \"%s\"\n", name);
8757 g_assert_not_reached ();
8760 info = g_new0 (MonoJitICallInfo, 1);
8765 info->c_symbol = c_symbol;
8766 info->no_raise = no_raise;
8769 info->wrapper = func;
8771 info->wrapper = NULL;
8774 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8775 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8777 mono_icall_unlock ();
8782 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8784 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);