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);
1259 ICALL_EXPORT MonoArray*
1260 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1263 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1264 mono_error_set_pending_exception (&error);
1269 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1271 MonoMethod **dest = (MonoMethod **)data;
1273 /* skip unmanaged frames */
1289 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1291 MonoMethod **dest = (MonoMethod **)data;
1293 /* skip unmanaged frames */
1298 if (!strcmp (m->klass->name_space, "System.Reflection"))
1307 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1309 MonoMethod **dest = (MonoMethod **)data;
1311 /* skip unmanaged frames */
1315 if (m->wrapper_type != MONO_WRAPPER_NONE)
1318 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1332 static MonoReflectionType *
1333 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1335 MonoMethod *m, *dest;
1337 MonoType *type = NULL;
1338 MonoAssembly *assembly = NULL;
1339 gboolean type_resolve = FALSE;
1341 mono_error_init (error);
1344 * We must compute the calling assembly as type loading must happen under a metadata context.
1345 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1346 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1348 m = mono_method_get_last_managed ();
1351 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1356 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1357 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1358 * to crash. This only seems to happen in some strange remoting
1359 * scenarios and I was unable to figure out what's happening there.
1360 * Dec 10, 2005 - Martin.
1364 assembly = dest->klass->image->assembly;
1365 type_resolve = TRUE;
1367 g_warning (G_STRLOC);
1370 if (info->assembly.name)
1371 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1375 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1376 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1377 return_val_if_nok (error, NULL);
1380 if (!info->assembly.name && !type) {
1382 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1383 return_val_if_nok (error, NULL);
1385 if (assembly && !type && type_resolve) {
1386 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1387 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1388 return_val_if_nok (error, NULL);
1394 return mono_type_get_object_checked (mono_domain_get (), type, error);
1397 ICALL_EXPORT MonoReflectionType*
1398 ves_icall_System_Type_internal_from_name (MonoString *name,
1399 MonoBoolean throwOnError,
1400 MonoBoolean ignoreCase)
1403 char *str = mono_string_to_utf8 (name);
1404 MonoTypeNameParse info;
1405 MonoReflectionType *type;
1408 parsedOk = mono_reflection_parse_type (str, &info);
1410 /* mono_reflection_parse_type() mangles the string */
1412 mono_reflection_free_type_info (&info);
1415 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1420 type = type_from_parsed_name (&info, ignoreCase, &error);
1422 mono_reflection_free_type_info (&info);
1425 if (!mono_error_ok (&error)) {
1427 mono_error_set_pending_exception (&error);
1429 mono_error_cleanup (&error);
1434 MonoException *e = NULL;
1437 e = mono_get_exception_type_load (name, NULL);
1439 mono_loader_clear_error ();
1441 mono_set_pending_exception (e);
1450 ICALL_EXPORT MonoReflectionType*
1451 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1454 MonoReflectionType *ret;
1455 MonoDomain *domain = mono_domain_get ();
1457 ret = mono_type_get_object_checked (domain, handle, &error);
1458 mono_error_raise_exception (&error);
1463 /* System.TypeCode */
1482 TYPECODE_STRING = 18
1485 ICALL_EXPORT guint32
1486 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1488 int t = type->type->type;
1490 if (type->type->byref)
1491 return TYPECODE_OBJECT;
1495 case MONO_TYPE_VOID:
1496 return TYPECODE_OBJECT;
1497 case MONO_TYPE_BOOLEAN:
1498 return TYPECODE_BOOLEAN;
1500 return TYPECODE_BYTE;
1502 return TYPECODE_SBYTE;
1504 return TYPECODE_UINT16;
1506 return TYPECODE_INT16;
1507 case MONO_TYPE_CHAR:
1508 return TYPECODE_CHAR;
1512 return TYPECODE_OBJECT;
1514 return TYPECODE_UINT32;
1516 return TYPECODE_INT32;
1518 return TYPECODE_UINT64;
1520 return TYPECODE_INT64;
1522 return TYPECODE_SINGLE;
1524 return TYPECODE_DOUBLE;
1525 case MONO_TYPE_VALUETYPE: {
1526 MonoClass *klass = type->type->data.klass;
1528 if (klass->enumtype) {
1529 t = mono_class_enum_basetype (klass)->type;
1531 } else if (mono_is_corlib_image (klass->image)) {
1532 if (strcmp (klass->name_space, "System") == 0) {
1533 if (strcmp (klass->name, "Decimal") == 0)
1534 return TYPECODE_DECIMAL;
1535 else if (strcmp (klass->name, "DateTime") == 0)
1536 return TYPECODE_DATETIME;
1539 return TYPECODE_OBJECT;
1541 case MONO_TYPE_STRING:
1542 return TYPECODE_STRING;
1543 case MONO_TYPE_SZARRAY:
1544 case MONO_TYPE_ARRAY:
1545 case MONO_TYPE_OBJECT:
1547 case MONO_TYPE_MVAR:
1548 case MONO_TYPE_TYPEDBYREF:
1549 return TYPECODE_OBJECT;
1550 case MONO_TYPE_CLASS:
1552 MonoClass *klass = type->type->data.klass;
1553 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1554 if (strcmp (klass->name, "DBNull") == 0)
1555 return TYPECODE_DBNULL;
1558 return TYPECODE_OBJECT;
1559 case MONO_TYPE_GENERICINST:
1560 return TYPECODE_OBJECT;
1562 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1568 mono_type_is_primitive (MonoType *type)
1570 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1571 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1575 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1577 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1578 return mono_class_enum_basetype (type->data.klass);
1579 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1580 return mono_class_enum_basetype (type->data.generic_class->container_class);
1584 ICALL_EXPORT guint32
1585 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1590 g_assert (type != NULL);
1592 klass = mono_class_from_mono_type (type->type);
1593 klassc = mono_class_from_mono_type (c->type);
1595 if (type->type->byref ^ c->type->byref)
1598 if (type->type->byref) {
1599 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1600 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1602 klass = mono_class_from_mono_type (t);
1603 klassc = mono_class_from_mono_type (ot);
1605 if (mono_type_is_primitive (t)) {
1606 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1607 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1608 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1609 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1610 return t->type == ot->type;
1612 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1615 if (klass->valuetype)
1616 return klass == klassc;
1617 return klass->valuetype == klassc->valuetype;
1620 return mono_class_is_assignable_from (klass, klassc);
1623 ICALL_EXPORT guint32
1624 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1627 MonoClass *klass = mono_class_from_mono_type (type->type);
1628 mono_class_init_checked (klass, &error);
1629 mono_error_raise_exception (&error);
1630 return mono_object_isinst (obj, klass) != NULL;
1633 ICALL_EXPORT guint32
1634 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1636 MonoClass *klass = mono_class_from_mono_type (type->type);
1637 return klass->flags;
1640 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1641 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1644 MonoClass *klass = field->field->parent;
1645 MonoMarshalType *info;
1649 if (klass->generic_container ||
1650 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1653 ftype = mono_field_get_type (field->field);
1654 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1657 info = mono_marshal_load_type_info (klass);
1659 for (i = 0; i < info->num_fields; ++i) {
1660 if (info->fields [i].field == field->field) {
1661 if (!info->fields [i].mspec)
1664 MonoReflectionMarshalAsAttribute* obj;
1665 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1666 if (!mono_error_ok (&error))
1667 mono_error_set_pending_exception (&error);
1676 ICALL_EXPORT MonoReflectionField*
1677 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1680 gboolean found = FALSE;
1687 klass = handle->parent;
1689 klass = mono_class_from_mono_type (type);
1691 /* Check that the field belongs to the class */
1692 for (k = klass; k; k = k->parent) {
1693 if (k == handle->parent) {
1700 /* The managed code will throw the exception */
1704 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1705 mono_error_raise_exception (&error);
1709 ICALL_EXPORT MonoArray*
1710 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1713 MonoType *type = mono_field_get_type_checked (field->field, &error);
1716 if (!mono_error_ok (&error)) {
1717 mono_error_set_pending_exception (&error);
1721 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1722 mono_error_raise_exception (&error);
1727 vell_icall_get_method_attributes (MonoMethod *method)
1729 return method->flags;
1733 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1736 MonoReflectionType *rt;
1737 MonoDomain *domain = mono_domain_get ();
1738 MonoMethodSignature* sig;
1740 sig = mono_method_signature_checked (method, &error);
1741 if (!mono_error_ok (&error)) {
1742 mono_error_set_pending_exception (&error);
1746 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1747 if (!mono_error_ok (&error)) {
1748 mono_error_set_pending_exception (&error);
1752 MONO_STRUCT_SETREF (info, parent, rt);
1754 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1755 if (!mono_error_ok (&error)) {
1756 mono_error_set_pending_exception (&error);
1760 MONO_STRUCT_SETREF (info, ret, rt);
1762 info->attrs = method->flags;
1763 info->implattrs = method->iflags;
1764 if (sig->call_convention == MONO_CALL_DEFAULT)
1765 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1767 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1772 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1775 ICALL_EXPORT MonoArray*
1776 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1779 MonoDomain *domain = mono_domain_get ();
1781 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1782 mono_error_set_pending_exception (&error);
1786 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1787 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1790 MonoDomain *domain = mono_domain_get ();
1791 MonoReflectionMarshalAsAttribute* res = NULL;
1792 MonoMarshalSpec **mspecs;
1795 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1796 mono_method_get_marshal_info (method, mspecs);
1799 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1800 if (!mono_error_ok (&error)) {
1801 mono_error_set_pending_exception (&error);
1806 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1808 mono_metadata_free_marshal_spec (mspecs [i]);
1815 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1817 MonoClass *parent = field->field->parent;
1818 if (!parent->size_inited)
1819 mono_class_init (parent);
1820 mono_class_setup_fields_locking (parent);
1822 return field->field->offset - sizeof (MonoObject);
1825 ICALL_EXPORT MonoReflectionType*
1826 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1829 MonoReflectionType *ret;
1832 parent = declaring? field->field->parent: field->klass;
1834 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1835 mono_error_raise_exception (&error);
1841 ICALL_EXPORT MonoObject *
1842 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1845 MonoClass *fklass = field->klass;
1846 MonoClassField *cf = field->field;
1847 MonoDomain *domain = mono_object_domain (field);
1849 if (fklass->image->assembly->ref_only) {
1850 mono_set_pending_exception (mono_get_exception_invalid_operation (
1851 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1855 if (mono_security_core_clr_enabled ())
1856 mono_security_core_clr_ensure_reflection_access_field (cf);
1858 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1859 mono_error_set_pending_exception (&error);
1864 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1867 MonoClassField *cf = field->field;
1871 if (field->klass->image->assembly->ref_only) {
1872 mono_set_pending_exception (mono_get_exception_invalid_operation (
1873 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1877 if (mono_security_core_clr_enabled ())
1878 mono_security_core_clr_ensure_reflection_access_field (cf);
1880 type = mono_field_get_type_checked (cf, &error);
1881 if (!mono_error_ok (&error)) {
1882 mono_error_set_pending_exception (&error);
1886 v = (gchar *) value;
1888 switch (type->type) {
1891 case MONO_TYPE_BOOLEAN:
1894 case MONO_TYPE_CHAR:
1903 case MONO_TYPE_VALUETYPE:
1906 v += sizeof (MonoObject);
1908 case MONO_TYPE_STRING:
1909 case MONO_TYPE_OBJECT:
1910 case MONO_TYPE_CLASS:
1911 case MONO_TYPE_ARRAY:
1912 case MONO_TYPE_SZARRAY:
1915 case MONO_TYPE_GENERICINST: {
1916 MonoGenericClass *gclass = type->data.generic_class;
1917 g_assert (!gclass->context.class_inst->is_open);
1919 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1920 MonoClass *nklass = mono_class_from_mono_type (type);
1921 MonoObject *nullable;
1924 * Convert the boxed vtype into a Nullable structure.
1925 * This is complicated by the fact that Nullables have
1926 * a variable structure.
1928 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1929 if (!mono_error_ok (&error)) {
1930 mono_error_set_pending_exception (&error);
1934 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1936 v = (gchar *)mono_object_unbox (nullable);
1939 if (gclass->container_class->valuetype && (v != NULL))
1940 v += sizeof (MonoObject);
1944 g_error ("type 0x%x not handled in "
1945 "ves_icall_FieldInfo_SetValueInternal", type->type);
1950 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1951 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1952 if (!is_ok (&error)) {
1953 mono_error_set_pending_exception (&error);
1956 if (!vtable->initialized) {
1957 if (!mono_runtime_class_init_full (vtable, &error)) {
1958 mono_error_set_pending_exception (&error);
1962 mono_field_static_set_value (vtable, cf, v);
1964 mono_field_set_value (obj, cf, v);
1969 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1978 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1979 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1983 if (MONO_TYPE_IS_REFERENCE (f->type))
1984 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1986 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1989 ICALL_EXPORT MonoObject *
1990 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1992 MonoObject *o = NULL;
1993 MonoClassField *field = rfield->field;
1995 MonoDomain *domain = mono_object_domain (rfield);
1997 MonoTypeEnum def_type;
1998 const char *def_value;
2002 mono_class_init (field->parent);
2004 t = mono_field_get_type_checked (field, &error);
2005 if (!mono_error_ok (&error)) {
2006 mono_error_set_pending_exception (&error);
2010 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2011 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2015 if (image_is_dynamic (field->parent->image)) {
2016 MonoClass *klass = field->parent;
2017 int fidx = field - klass->fields;
2019 g_assert (fidx >= 0 && fidx < klass->field.count);
2020 g_assert (klass->ext);
2021 g_assert (klass->ext->field_def_values);
2022 def_type = klass->ext->field_def_values [fidx].def_type;
2023 def_value = klass->ext->field_def_values [fidx].data;
2024 if (def_type == MONO_TYPE_END) {
2025 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2029 def_value = mono_class_get_field_default_value (field, &def_type);
2030 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2032 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2037 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2041 case MONO_TYPE_BOOLEAN:
2044 case MONO_TYPE_CHAR:
2052 case MONO_TYPE_R8: {
2055 /* boxed value type */
2056 t = g_new0 (MonoType, 1);
2058 klass = mono_class_from_mono_type (t);
2060 o = mono_object_new_checked (domain, klass, &error);
2061 if (!mono_error_ok (&error)) {
2062 mono_error_set_pending_exception (&error);
2065 v = ((gchar *) o) + sizeof (MonoObject);
2066 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2069 case MONO_TYPE_STRING:
2070 case MONO_TYPE_CLASS:
2071 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2074 g_assert_not_reached ();
2080 ICALL_EXPORT MonoReflectionType*
2081 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2084 MonoReflectionType *ret;
2087 type = mono_field_get_type_checked (ref_field->field, &error);
2088 if (!mono_error_ok (&error)) {
2089 mono_error_set_pending_exception (&error);
2093 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2094 if (!mono_error_ok (&error)) {
2095 mono_error_set_pending_exception (&error);
2102 /* From MonoProperty.cs */
2104 PInfo_Attributes = 1,
2105 PInfo_GetMethod = 1 << 1,
2106 PInfo_SetMethod = 1 << 2,
2107 PInfo_ReflectedType = 1 << 3,
2108 PInfo_DeclaringType = 1 << 4,
2113 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2116 MonoReflectionType *rt;
2117 MonoReflectionMethod *rm;
2118 MonoDomain *domain = mono_object_domain (property);
2119 const MonoProperty *pproperty = property->property;
2121 if ((req_info & PInfo_ReflectedType) != 0) {
2122 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2123 mono_error_raise_exception (&error);
2125 MONO_STRUCT_SETREF (info, parent, rt);
2127 if ((req_info & PInfo_DeclaringType) != 0) {
2128 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2129 mono_error_raise_exception (&error);
2131 MONO_STRUCT_SETREF (info, declaring_type, rt);
2134 if ((req_info & PInfo_Name) != 0)
2135 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2137 if ((req_info & PInfo_Attributes) != 0)
2138 info->attrs = pproperty->attrs;
2140 if ((req_info & PInfo_GetMethod) != 0) {
2141 if (pproperty->get &&
2142 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2143 pproperty->get->klass == property->klass)) {
2144 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2145 mono_error_raise_exception (&error);
2150 MONO_STRUCT_SETREF (info, get, rm);
2152 if ((req_info & PInfo_SetMethod) != 0) {
2153 if (pproperty->set &&
2154 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2155 pproperty->set->klass == property->klass)) {
2156 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2157 mono_error_raise_exception (&error);
2162 MONO_STRUCT_SETREF (info, set, rm);
2165 * There may be other methods defined for properties, though, it seems they are not exposed
2166 * in the reflection API
2171 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2174 MonoReflectionType *rt;
2175 MonoReflectionMethod *rm;
2176 MonoDomain *domain = mono_object_domain (event);
2178 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2179 mono_error_raise_exception (&error);
2181 MONO_STRUCT_SETREF (info, reflected_type, rt);
2183 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2184 mono_error_raise_exception (&error);
2186 MONO_STRUCT_SETREF (info, declaring_type, rt);
2188 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2189 info->attrs = event->event->attrs;
2191 if (event->event->add) {
2192 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2193 mono_error_raise_exception (&error);
2198 MONO_STRUCT_SETREF (info, add_method, rm);
2200 if (event->event->remove) {
2201 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2202 mono_error_raise_exception (&error);
2207 MONO_STRUCT_SETREF (info, remove_method, rm);
2209 if (event->event->raise) {
2210 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2211 mono_error_raise_exception (&error);
2216 MONO_STRUCT_SETREF (info, raise_method, rm);
2218 #ifndef MONO_SMALL_CONFIG
2219 if (event->event->other) {
2221 while (event->event->other [n])
2223 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2225 for (i = 0; i < n; i++) {
2226 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2227 mono_error_raise_exception (&error);
2228 mono_array_setref (info->other_methods, i, rm);
2235 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2240 mono_class_setup_interfaces (klass, error);
2241 if (!mono_error_ok (error))
2244 for (i = 0; i < klass->interface_count; i++) {
2245 ic = klass->interfaces [i];
2246 g_hash_table_insert (ifaces, ic, ic);
2248 collect_interfaces (ic, ifaces, error);
2249 if (!mono_error_ok (error))
2255 MonoArray *iface_array;
2256 MonoGenericContext *context;
2260 } FillIfaceArrayData;
2263 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2265 MonoReflectionType *rt;
2266 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2267 MonoClass *ic = (MonoClass *)key;
2268 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2270 if (!mono_error_ok (data->error))
2273 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2274 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2275 if (!mono_error_ok (data->error))
2279 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2280 if (!mono_error_ok (data->error))
2283 mono_array_setref (data->iface_array, data->next_idx++, rt);
2286 mono_metadata_free_type (inflated);
2290 get_interfaces_hash (gconstpointer v1)
2292 MonoClass *k = (MonoClass*)v1;
2294 return k->type_token;
2297 ICALL_EXPORT MonoArray*
2298 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2301 MonoClass *klass = mono_class_from_mono_type (type->type);
2303 FillIfaceArrayData data = { 0 };
2306 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2308 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2309 data.context = mono_class_get_context (klass);
2310 klass = klass->generic_class->container_class;
2313 for (parent = klass; parent; parent = parent->parent) {
2314 mono_class_setup_interfaces (parent, &error);
2315 if (!mono_error_ok (&error))
2317 collect_interfaces (parent, iface_hash, &error);
2318 if (!mono_error_ok (&error))
2322 data.error = &error;
2323 data.domain = mono_object_domain (type);
2325 len = g_hash_table_size (iface_hash);
2327 g_hash_table_destroy (iface_hash);
2328 if (!data.domain->empty_types)
2329 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2330 return data.domain->empty_types;
2333 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2334 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2335 if (!mono_error_ok (&error))
2338 g_hash_table_destroy (iface_hash);
2339 return data.iface_array;
2342 g_hash_table_destroy (iface_hash);
2343 mono_error_set_pending_exception (&error);
2348 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2350 gboolean variance_used;
2351 MonoClass *klass = mono_class_from_mono_type (type->type);
2352 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2353 MonoReflectionMethod *member;
2356 int i = 0, len, ioffset;
2360 mono_class_init_checked (klass, &error);
2361 mono_error_raise_exception (&error);
2362 mono_class_init_checked (iclass, &error);
2363 mono_error_raise_exception (&error);
2365 mono_class_setup_vtable (klass);
2367 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2371 len = mono_class_num_methods (iclass);
2372 domain = mono_object_domain (type);
2373 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2374 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2376 while ((method = mono_class_get_methods (iclass, &iter))) {
2377 member = mono_method_get_object_checked (domain, method, iclass, &error);
2378 mono_error_raise_exception (&error);
2379 mono_array_setref (*methods, i, member);
2380 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2381 mono_error_raise_exception (&error);
2382 mono_array_setref (*targets, i, member);
2389 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2392 MonoClass *klass = mono_class_from_mono_type (type->type);
2394 mono_class_init_checked (klass, &error);
2395 mono_error_raise_exception (&error);
2397 if (image_is_dynamic (klass->image)) {
2398 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2399 *packing = tb->packing_size;
2400 *size = tb->class_size;
2402 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2406 ICALL_EXPORT MonoReflectionType*
2407 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2410 MonoReflectionType *ret;
2413 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2414 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2415 mono_error_raise_exception (&error);
2420 klass = mono_class_from_mono_type (type->type);
2421 mono_class_init_checked (klass, &error);
2422 mono_error_raise_exception (&error);
2424 // GetElementType should only return a type for:
2425 // Array Pointer PassedByRef
2426 if (type->type->byref)
2427 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2428 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2429 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2430 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2431 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2435 mono_error_raise_exception (&error);
2440 ICALL_EXPORT MonoReflectionType*
2441 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2444 MonoReflectionType *ret;
2446 if (type->type->byref)
2449 MonoClass *klass = mono_class_from_mono_type (type->type);
2453 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2454 mono_error_raise_exception (&error);
2459 ICALL_EXPORT MonoBoolean
2460 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2462 return type->type->type == MONO_TYPE_PTR;
2465 ICALL_EXPORT MonoBoolean
2466 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2468 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)));
2471 ICALL_EXPORT MonoBoolean
2472 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2474 return type->type->byref;
2477 ICALL_EXPORT MonoBoolean
2478 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2481 MonoClass *klass = mono_class_from_mono_type (type->type);
2482 mono_class_init_checked (klass, &error);
2483 mono_error_raise_exception (&error);
2485 return mono_class_is_com_object (klass);
2488 ICALL_EXPORT guint32
2489 ves_icall_reflection_get_token (MonoObject* obj)
2492 guint32 result = mono_reflection_get_token_checked (obj, &error);
2493 mono_error_set_pending_exception (&error);
2497 ICALL_EXPORT MonoReflectionModule*
2498 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2501 MonoReflectionModule *result = NULL;
2502 MonoClass *klass = mono_class_from_mono_type (type->type);
2503 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2504 if (!mono_error_ok (&error))
2505 mono_error_set_pending_exception (&error);
2509 ICALL_EXPORT MonoReflectionAssembly*
2510 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2513 MonoDomain *domain = mono_domain_get ();
2514 MonoClass *klass = mono_class_from_mono_type (type->type);
2515 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2517 mono_error_set_pending_exception (&error);
2521 ICALL_EXPORT MonoReflectionType*
2522 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2525 MonoReflectionType *ret;
2526 MonoDomain *domain = mono_domain_get ();
2529 if (type->type->byref)
2531 if (type->type->type == MONO_TYPE_VAR) {
2532 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2533 klass = param ? param->owner.klass : NULL;
2534 } else if (type->type->type == MONO_TYPE_MVAR) {
2535 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2536 klass = param ? param->owner.method->klass : NULL;
2538 klass = mono_class_from_mono_type (type->type)->nested_in;
2544 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2545 mono_error_raise_exception (&error);
2550 ICALL_EXPORT MonoString*
2551 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2553 MonoDomain *domain = mono_domain_get ();
2554 MonoClass *klass = mono_class_from_mono_type (type->type);
2556 if (type->type->byref) {
2557 char *n = g_strdup_printf ("%s&", klass->name);
2558 MonoString *res = mono_string_new (domain, n);
2564 return mono_string_new (domain, klass->name);
2568 ICALL_EXPORT MonoString*
2569 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2571 MonoDomain *domain = mono_domain_get ();
2572 MonoClass *klass = mono_class_from_mono_type (type->type);
2574 while (klass->nested_in)
2575 klass = klass->nested_in;
2577 if (klass->name_space [0] == '\0')
2580 return mono_string_new (domain, klass->name_space);
2584 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2588 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2589 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2593 klass = mono_class_from_mono_type (type->type);
2599 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2602 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2606 ICALL_EXPORT MonoArray*
2607 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2610 MonoReflectionType *rt;
2612 MonoClass *klass, *pklass;
2613 MonoDomain *domain = mono_object_domain (type);
2616 klass = mono_class_from_mono_type (type->type);
2618 if (klass->generic_container) {
2619 MonoGenericContainer *container = klass->generic_container;
2620 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2621 for (i = 0; i < container->type_argc; ++i) {
2622 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2624 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2625 mono_error_raise_exception (&error);
2627 mono_array_setref (res, i, rt);
2629 } else if (klass->generic_class) {
2630 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2631 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2632 for (i = 0; i < inst->type_argc; ++i) {
2633 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2634 mono_error_raise_exception (&error);
2636 mono_array_setref (res, i, rt);
2644 ICALL_EXPORT gboolean
2645 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2649 if (!IS_MONOTYPE (type))
2652 if (type->type->byref)
2655 klass = mono_class_from_mono_type (type->type);
2656 return klass->generic_container != NULL;
2659 ICALL_EXPORT MonoReflectionType*
2660 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2663 MonoReflectionType *ret;
2666 if (type->type->byref)
2669 klass = mono_class_from_mono_type (type->type);
2671 if (klass->generic_container) {
2672 return type; /* check this one */
2674 if (klass->generic_class) {
2675 MonoClass *generic_class = klass->generic_class->container_class;
2678 tb = mono_class_get_ref_info (generic_class);
2680 if (generic_class->wastypebuilder && tb)
2681 return (MonoReflectionType *)tb;
2683 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2684 mono_error_raise_exception (&error);
2692 ICALL_EXPORT MonoReflectionType*
2693 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2696 MonoReflectionType *ret;
2698 MonoType *geninst, **types;
2701 g_assert (IS_MONOTYPE (type));
2702 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2703 mono_error_raise_exception (&error);
2705 count = mono_array_length (type_array);
2706 types = g_new0 (MonoType *, count);
2708 for (i = 0; i < count; i++) {
2709 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2710 types [i] = t->type;
2713 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2716 mono_error_set_pending_exception (&error);
2720 klass = mono_class_from_mono_type (geninst);
2722 /*we might inflate to the GTD*/
2723 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2724 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2728 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2729 mono_error_raise_exception (&error);
2734 ICALL_EXPORT gboolean
2735 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2739 if (!IS_MONOTYPE (type))
2742 if (type->type->byref)
2745 klass = mono_class_from_mono_type (type->type);
2746 return klass->generic_class != NULL || klass->generic_container != NULL;
2750 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2752 if (!IS_MONOTYPE (type))
2755 if (is_generic_parameter (type->type))
2756 return mono_type_get_generic_param_num (type->type);
2760 ICALL_EXPORT GenericParameterAttributes
2761 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2763 g_assert (IS_MONOTYPE (type));
2764 g_assert (is_generic_parameter (type->type));
2765 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2768 ICALL_EXPORT MonoArray *
2769 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2772 MonoReflectionType *rt;
2773 MonoGenericParamInfo *param_info;
2779 g_assert (IS_MONOTYPE (type));
2781 domain = mono_object_domain (type);
2782 param_info = mono_generic_param_info (type->type->data.generic_param);
2783 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2786 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2787 for (i = 0; i < count; i++) {
2788 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2789 mono_error_raise_exception (&error);
2791 mono_array_setref (res, i, rt);
2798 ICALL_EXPORT MonoBoolean
2799 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2801 return is_generic_parameter (type->type);
2804 ICALL_EXPORT MonoBoolean
2805 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2807 return is_generic_parameter (tb->type.type);
2811 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2812 MonoReflectionType *t)
2814 enumtype->type = t->type;
2817 ICALL_EXPORT MonoReflectionMethod*
2818 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2819 MonoReflectionMethod* generic)
2826 MonoReflectionMethod *ret = NULL;
2828 domain = ((MonoObject *)type)->vtable->domain;
2830 klass = mono_class_from_mono_type (type->type);
2831 mono_class_init_checked (klass, &error);
2832 mono_error_raise_exception (&error);
2835 while ((method = mono_class_get_methods (klass, &iter))) {
2836 if (method->token == generic->method->token) {
2837 ret = mono_method_get_object_checked (domain, method, klass, &error);
2838 mono_error_raise_exception (&error);
2845 ICALL_EXPORT MonoReflectionMethod *
2846 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2849 MonoType *type = ref_type->type;
2851 MonoReflectionMethod *ret = NULL;
2853 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2854 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2857 if (type->type == MONO_TYPE_VAR)
2860 method = mono_type_get_generic_param_owner (type)->owner.method;
2863 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2864 if (!mono_error_ok (&error))
2865 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2869 ICALL_EXPORT MonoBoolean
2870 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2872 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2876 ICALL_EXPORT MonoBoolean
2877 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2879 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2884 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2886 MonoDomain *domain = mono_domain_get ();
2887 MonoImage *image = method->method->klass->image;
2888 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2889 MonoTableInfo *tables = image->tables;
2890 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2891 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2892 guint32 im_cols [MONO_IMPLMAP_SIZE];
2893 guint32 scope_token;
2894 const char *import = NULL;
2895 const char *scope = NULL;
2897 if (image_is_dynamic (image)) {
2898 MonoReflectionMethodAux *method_aux =
2899 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2901 import = method_aux->dllentry;
2902 scope = method_aux->dll;
2905 if (!import || !scope) {
2906 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2911 if (piinfo->implmap_idx) {
2912 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2914 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2915 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2916 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2917 scope = mono_metadata_string_heap (image, scope_token);
2921 *flags = piinfo->piflags;
2922 *entry_point = mono_string_new (domain, import);
2923 *dll_name = mono_string_new (domain, scope);
2926 ICALL_EXPORT MonoReflectionMethod *
2927 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2929 MonoMethodInflated *imethod;
2931 MonoReflectionMethod *ret = NULL;
2934 if (method->method->is_generic)
2937 if (!method->method->is_inflated)
2940 imethod = (MonoMethodInflated *) method->method;
2942 result = imethod->declaring;
2943 /* Not a generic method. */
2944 if (!result->is_generic)
2947 if (image_is_dynamic (method->method->klass->image)) {
2948 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2949 MonoReflectionMethod *res;
2952 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2953 * the dynamic case as well ?
2955 mono_image_lock ((MonoImage*)image);
2956 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2957 mono_image_unlock ((MonoImage*)image);
2963 if (imethod->context.class_inst) {
2964 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2965 /*Generic methods gets the context of the GTD.*/
2966 if (mono_class_get_context (klass)) {
2967 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2968 if (!mono_error_ok (&error))
2973 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2975 if (!mono_error_ok (&error))
2976 mono_error_set_pending_exception (&error);
2980 ICALL_EXPORT gboolean
2981 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2983 return mono_method_signature (method->method)->generic_param_count != 0;
2986 ICALL_EXPORT gboolean
2987 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2989 return method->method->is_generic;
2992 ICALL_EXPORT MonoArray*
2993 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2996 MonoReflectionType *rt;
3001 domain = mono_object_domain (method);
3003 if (method->method->is_inflated) {
3004 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3007 count = inst->type_argc;
3008 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3010 for (i = 0; i < count; i++) {
3011 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3012 mono_error_raise_exception (&error);
3014 mono_array_setref (res, i, rt);
3021 count = mono_method_signature (method->method)->generic_param_count;
3022 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3024 for (i = 0; i < count; i++) {
3025 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3026 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3027 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3029 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3030 mono_error_raise_exception (&error);
3032 mono_array_setref (res, i, rt);
3038 ICALL_EXPORT MonoObject *
3039 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3043 * Invoke from reflection is supposed to always be a virtual call (the API
3044 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3045 * greater flexibility.
3047 MonoMethod *m = method->method;
3048 MonoMethodSignature *sig = mono_method_signature (m);
3051 void *obj = this_arg;
3055 if (mono_security_core_clr_enabled ())
3056 mono_security_core_clr_ensure_reflection_access_method (m);
3058 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3059 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3060 mono_error_cleanup (&error); /* FIXME does this make sense? */
3061 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3066 if (!mono_object_isinst (this_arg, m->klass)) {
3067 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3068 char *target_name = mono_type_get_full_name (m->klass);
3069 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3070 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3072 g_free (target_name);
3076 m = mono_object_get_virtual_method (this_arg, m);
3077 /* must pass the pointer to the value for valuetype methods */
3078 if (m->klass->valuetype)
3079 obj = mono_object_unbox (this_arg);
3080 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3081 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3086 if (sig->ret->byref) {
3087 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"));
3091 pcount = params? mono_array_length (params): 0;
3092 if (pcount != sig->param_count) {
3093 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3097 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3098 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."));
3102 image = m->klass->image;
3103 if (image->assembly->ref_only) {
3104 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."));
3108 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3109 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3113 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3117 intptr_t *lower_bounds;
3118 pcount = mono_array_length (params);
3119 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3120 /* Note: the synthetized array .ctors have int32 as argument type */
3121 for (i = 0; i < pcount; ++i)
3122 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3124 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3125 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3126 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3127 if (!mono_error_ok (&error)) {
3128 mono_error_set_pending_exception (&error);
3132 for (i = 0; i < mono_array_length (arr); ++i) {
3133 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3134 if (!mono_error_ok (&error)) {
3135 mono_error_set_pending_exception (&error);
3138 mono_array_setref_fast (arr, i, subarray);
3140 return (MonoObject*)arr;
3143 if (m->klass->rank == pcount) {
3144 /* Only lengths provided. */
3145 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3146 if (!mono_error_ok (&error)) {
3147 mono_error_set_pending_exception (&error);
3151 return (MonoObject*)arr;
3153 g_assert (pcount == (m->klass->rank * 2));
3154 /* The arguments are lower-bound-length pairs */
3155 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3157 for (i = 0; i < pcount / 2; ++i) {
3158 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3159 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3162 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3163 if (!mono_error_ok (&error)) {
3164 mono_error_set_pending_exception (&error);
3168 return (MonoObject*)arr;
3171 return mono_runtime_invoke_array (m, obj, params, NULL);
3174 #ifndef DISABLE_REMOTING
3175 ICALL_EXPORT MonoObject *
3176 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3178 MonoDomain *domain = mono_object_domain (method);
3179 MonoMethod *m = method->method;
3180 MonoMethodSignature *sig = mono_method_signature (m);
3181 MonoArray *out_args;
3183 int i, j, outarg_count = 0;
3185 if (m->klass == mono_defaults.object_class) {
3186 if (!strcmp (m->name, "FieldGetter")) {
3187 MonoClass *k = this_arg->vtable->klass;
3191 /* If this is a proxy, then it must be a CBO */
3192 if (k == mono_defaults.transparent_proxy_class) {
3193 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3194 this_arg = tp->rp->unwrapped_server;
3195 g_assert (this_arg);
3196 k = this_arg->vtable->klass;
3199 name = mono_array_get (params, MonoString *, 1);
3200 str = mono_string_to_utf8 (name);
3203 MonoClassField* field = mono_class_get_field_from_name (k, str);
3205 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3206 if (field_klass->valuetype)
3207 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
3209 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3211 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3212 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3213 mono_array_setref (out_args, 0, result);
3221 g_assert_not_reached ();
3223 } else if (!strcmp (m->name, "FieldSetter")) {
3224 MonoClass *k = this_arg->vtable->klass;
3230 /* If this is a proxy, then it must be a CBO */
3231 if (k == mono_defaults.transparent_proxy_class) {
3232 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3233 this_arg = tp->rp->unwrapped_server;
3234 g_assert (this_arg);
3235 k = this_arg->vtable->klass;
3238 name = mono_array_get (params, MonoString *, 1);
3239 str = mono_string_to_utf8 (name);
3242 MonoClassField* field = mono_class_get_field_from_name (k, str);
3244 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3245 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3247 if (field_klass->valuetype) {
3248 size = mono_type_size (field->type, &align);
3249 g_assert (size == mono_class_value_size (field_klass, NULL));
3250 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3252 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3255 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3256 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3266 g_assert_not_reached ();
3271 for (i = 0; i < mono_array_length (params); i++) {
3272 if (sig->params [i]->byref)
3276 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3278 /* handle constructors only for objects already allocated */
3279 if (!strcmp (method->method->name, ".ctor"))
3280 g_assert (this_arg);
3282 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3283 g_assert (!method->method->klass->valuetype);
3284 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3286 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3287 if (sig->params [i]->byref) {
3289 arg = mono_array_get (params, gpointer, i);
3290 mono_array_setref (out_args, j, arg);
3295 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3302 read_enum_value (const char *mem, int type)
3305 case MONO_TYPE_BOOLEAN:
3307 return *(guint8*)mem;
3309 return *(gint8*)mem;
3310 case MONO_TYPE_CHAR:
3312 return read16 (mem);
3314 return (gint16) read16 (mem);
3316 return read32 (mem);
3318 return (gint32) read32 (mem);
3321 return read64 (mem);
3323 g_assert_not_reached ();
3329 write_enum_value (char *mem, int type, guint64 value)
3333 case MONO_TYPE_I1: {
3334 guint8 *p = (guint8*)mem;
3339 case MONO_TYPE_I2: {
3340 guint16 *p = (guint16 *)mem;
3345 case MONO_TYPE_I4: {
3346 guint32 *p = (guint32 *)mem;
3351 case MONO_TYPE_I8: {
3352 guint64 *p = (guint64 *)mem;
3357 g_assert_not_reached ();
3362 ICALL_EXPORT MonoObject *
3363 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3371 domain = mono_object_domain (enumType);
3372 enumc = mono_class_from_mono_type (enumType->type);
3374 mono_class_init_checked (enumc, &error);
3375 mono_error_raise_exception (&error);
3377 etype = mono_class_enum_basetype (enumc);
3379 res = mono_object_new_checked (domain, enumc, &error);
3380 mono_error_raise_exception (&error);
3381 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3386 ICALL_EXPORT MonoBoolean
3387 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3389 int size = mono_class_value_size (a->vtable->klass, NULL);
3390 guint64 a_val = 0, b_val = 0;
3392 memcpy (&a_val, mono_object_unbox (a), size);
3393 memcpy (&b_val, mono_object_unbox (b), size);
3395 return (a_val & b_val) == b_val;
3398 ICALL_EXPORT MonoObject *
3399 ves_icall_System_Enum_get_value (MonoObject *eobj)
3411 g_assert (eobj->vtable->klass->enumtype);
3413 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3414 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3415 mono_error_raise_exception (&error);
3416 dst = (char *)res + sizeof (MonoObject);
3417 src = (char *)eobj + sizeof (MonoObject);
3418 size = mono_class_value_size (enumc, NULL);
3420 memcpy (dst, src, size);
3425 ICALL_EXPORT MonoReflectionType *
3426 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3429 MonoReflectionType *ret;
3433 klass = mono_class_from_mono_type (type->type);
3434 mono_class_init_checked (klass, &error);
3435 mono_error_raise_exception (&error);
3437 etype = mono_class_enum_basetype (klass);
3439 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3443 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3444 mono_error_raise_exception (&error);
3450 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3452 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3453 gpointer odata = (char *)other + sizeof (MonoObject);
3454 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3455 g_assert (basetype);
3460 if (eobj->vtable->klass != other->vtable->klass)
3463 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3464 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3465 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3468 return me > other ? 1 : -1; \
3471 switch (basetype->type) {
3473 COMPARE_ENUM_VALUES (guint8);
3475 COMPARE_ENUM_VALUES (gint8);
3476 case MONO_TYPE_CHAR:
3478 COMPARE_ENUM_VALUES (guint16);
3480 COMPARE_ENUM_VALUES (gint16);
3482 COMPARE_ENUM_VALUES (guint32);
3484 COMPARE_ENUM_VALUES (gint32);
3486 COMPARE_ENUM_VALUES (guint64);
3488 COMPARE_ENUM_VALUES (gint64);
3492 #undef COMPARE_ENUM_VALUES
3493 /* indicates that the enum was of an unsupported unerlying type */
3498 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3500 gpointer data = (char *)eobj + sizeof (MonoObject);
3501 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3502 g_assert (basetype);
3504 switch (basetype->type) {
3505 case MONO_TYPE_I1: {
3506 gint8 value = *((gint8*)data);
3507 return ((int)value ^ (int)value << 8);
3510 return *((guint8*)data);
3511 case MONO_TYPE_CHAR:
3513 return *((guint16*)data);
3515 case MONO_TYPE_I2: {
3516 gint16 value = *((gint16*)data);
3517 return ((int)(guint16)value | (((int)value) << 16));
3520 return *((guint32*)data);
3522 return *((gint32*)data);
3524 case MONO_TYPE_I8: {
3525 gint64 value = *((gint64*)data);
3526 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3529 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3534 ICALL_EXPORT MonoBoolean
3535 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3538 MonoDomain *domain = mono_object_domain (type);
3539 MonoClass *enumc = mono_class_from_mono_type (type->type);
3540 guint j = 0, nvalues;
3542 MonoClassField *field;
3544 guint64 field_value, previous_value = 0;
3545 gboolean sorted = TRUE;
3547 mono_class_init_checked (enumc, &error);
3548 mono_error_raise_exception (&error);
3550 if (!enumc->enumtype) {
3551 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3555 base_type = mono_class_enum_basetype (enumc)->type;
3557 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3558 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3559 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3562 while ((field = mono_class_get_fields (enumc, &iter))) {
3564 MonoTypeEnum def_type;
3566 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3568 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3570 if (mono_field_is_deleted (field))
3572 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3574 p = mono_class_get_field_default_value (field, &def_type);
3575 /* len = */ mono_metadata_decode_blob_size (p, &p);
3577 field_value = read_enum_value (p, base_type);
3578 mono_array_set (*values, guint64, j, field_value);
3580 if (previous_value > field_value)
3583 previous_value = field_value;
3591 BFLAGS_IgnoreCase = 1,
3592 BFLAGS_DeclaredOnly = 2,
3593 BFLAGS_Instance = 4,
3595 BFLAGS_Public = 0x10,
3596 BFLAGS_NonPublic = 0x20,
3597 BFLAGS_FlattenHierarchy = 0x40,
3598 BFLAGS_InvokeMethod = 0x100,
3599 BFLAGS_CreateInstance = 0x200,
3600 BFLAGS_GetField = 0x400,
3601 BFLAGS_SetField = 0x800,
3602 BFLAGS_GetProperty = 0x1000,
3603 BFLAGS_SetProperty = 0x2000,
3604 BFLAGS_ExactBinding = 0x10000,
3605 BFLAGS_SuppressChangeType = 0x20000,
3606 BFLAGS_OptionalParamBinding = 0x40000
3609 ICALL_EXPORT MonoArray*
3610 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3614 MonoClass *startklass, *klass, *refklass;
3619 char *utf8_name = NULL;
3620 int (*compare_func) (const char *s1, const char *s2) = NULL;
3621 MonoClassField *field;
3622 MonoPtrArray tmp_array;
3624 domain = ((MonoObject *)type)->vtable->domain;
3625 if (type->type->byref)
3626 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3628 klass = startklass = mono_class_from_mono_type (type->type);
3629 refklass = mono_class_from_mono_type (reftype->type);
3631 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3634 if (mono_class_has_failure (klass)) {
3635 mono_ptr_array_destroy (tmp_array);
3636 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3641 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3642 guint32 flags = mono_field_get_flags (field);
3644 if (mono_field_is_deleted_with_flags (field, flags))
3646 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3647 if (bflags & BFLAGS_Public)
3649 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3650 if (bflags & BFLAGS_NonPublic) {
3657 if (flags & FIELD_ATTRIBUTE_STATIC) {
3658 if (bflags & BFLAGS_Static)
3659 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3662 if (bflags & BFLAGS_Instance)
3670 if (utf8_name == NULL) {
3671 utf8_name = mono_string_to_utf8 (name);
3672 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3675 if (compare_func (mono_field_get_name (field), utf8_name))
3679 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3680 if (!mono_error_ok (&error))
3682 mono_ptr_array_append (tmp_array, member);
3684 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3687 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3689 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3690 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3692 mono_ptr_array_destroy (tmp_array);
3694 if (utf8_name != NULL)
3699 mono_ptr_array_destroy (tmp_array);
3700 mono_error_raise_exception (&error);
3701 g_assert_not_reached ();
3705 method_nonpublic (MonoMethod* method, gboolean start_klass)
3707 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3708 case METHOD_ATTRIBUTE_ASSEM:
3709 return (start_klass || mono_defaults.generic_ilist_class);
3710 case METHOD_ATTRIBUTE_PRIVATE:
3712 case METHOD_ATTRIBUTE_PUBLIC:
3720 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3723 MonoClass *startklass;
3727 /*FIXME, use MonoBitSet*/
3728 guint32 method_slots_default [8];
3729 guint32 *method_slots = NULL;
3730 int (*compare_func) (const char *s1, const char *s2) = NULL;
3732 array = g_ptr_array_new ();
3737 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3739 /* An optimization for calls made from Delegate:CreateDelegate () */
3740 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3741 method = mono_get_delegate_invoke (klass);
3742 if (mono_loader_get_last_error ())
3745 g_ptr_array_add (array, method);
3749 mono_class_setup_methods (klass);
3750 mono_class_setup_vtable (klass);
3751 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3754 if (is_generic_parameter (&klass->byval_arg))
3755 nslots = mono_class_get_vtable_size (klass->parent);
3757 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3758 if (nslots >= sizeof (method_slots_default) * 8) {
3759 method_slots = g_new0 (guint32, nslots / 32 + 1);
3761 method_slots = method_slots_default;
3762 memset (method_slots, 0, sizeof (method_slots_default));
3765 mono_class_setup_methods (klass);
3766 mono_class_setup_vtable (klass);
3767 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3771 while ((method = mono_class_get_methods (klass, &iter))) {
3773 if (method->slot != -1) {
3774 g_assert (method->slot < nslots);
3775 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3777 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3778 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3781 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3783 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3784 if (bflags & BFLAGS_Public)
3786 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3792 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3793 if (bflags & BFLAGS_Static)
3794 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3797 if (bflags & BFLAGS_Instance)
3805 if (compare_func (name, method->name))
3810 g_ptr_array_add (array, method);
3812 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3814 if (method_slots != method_slots_default)
3815 g_free (method_slots);
3820 if (method_slots != method_slots_default)
3821 g_free (method_slots);
3822 g_ptr_array_free (array, TRUE);
3824 if (mono_class_has_failure (klass)) {
3825 *ex = mono_class_get_exception_for_failure (klass);
3827 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3828 mono_loader_clear_error ();
3833 ICALL_EXPORT MonoArray*
3834 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3836 static MonoClass *MethodInfo_array;
3840 MonoVTable *array_vtable;
3841 MonoException *ex = NULL;
3842 const char *mname = NULL;
3843 GPtrArray *method_array;
3844 MonoClass *klass, *refklass;
3847 mono_error_init (&error);
3849 if (!MethodInfo_array) {
3850 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3851 mono_memory_barrier ();
3852 MethodInfo_array = klass;
3855 klass = mono_class_from_mono_type (type->type);
3856 refklass = mono_class_from_mono_type (reftype->type);
3857 domain = ((MonoObject *)type)->vtable->domain;
3858 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3859 if (!is_ok (&error)) {
3860 mono_error_set_pending_exception (&error);
3863 if (type->type->byref) {
3864 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3865 mono_error_set_pending_exception (&error);
3871 mname = mono_string_to_utf8 (name);
3873 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3874 g_free ((char*)mname);
3876 mono_set_pending_exception (ex);
3880 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3881 if (!mono_error_ok (&error)) {
3882 mono_error_set_pending_exception (&error);
3886 for (i = 0; i < method_array->len; ++i) {
3887 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3888 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3889 if (!mono_error_ok (&error))
3891 mono_array_setref (res, i, rm);
3895 g_ptr_array_free (method_array, TRUE);
3896 if (!mono_error_ok (&error))
3897 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3901 ICALL_EXPORT MonoArray*
3902 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3905 MonoClass *startklass, *klass, *refklass;
3910 gpointer iter = NULL;
3911 MonoPtrArray tmp_array;
3914 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3916 domain = ((MonoObject *)type)->vtable->domain;
3917 if (type->type->byref)
3918 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3919 klass = startklass = mono_class_from_mono_type (type->type);
3920 refklass = mono_class_from_mono_type (reftype->type);
3922 mono_class_setup_methods (klass);
3923 if (mono_class_has_failure (klass)) {
3924 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3929 while ((method = mono_class_get_methods (klass, &iter))) {
3931 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3933 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3934 if (bflags & BFLAGS_Public)
3937 if (bflags & BFLAGS_NonPublic)
3943 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3944 if (bflags & BFLAGS_Static)
3945 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3948 if (bflags & BFLAGS_Instance)
3954 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3955 if (!mono_error_ok (&error)) {
3956 mono_error_set_pending_exception (&error);
3960 mono_ptr_array_append (tmp_array, member);
3963 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3965 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3966 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3968 mono_ptr_array_destroy (tmp_array);
3974 property_hash (gconstpointer data)
3976 MonoProperty *prop = (MonoProperty*)data;
3978 return g_str_hash (prop->name);
3982 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3984 if (method1->is_inflated)
3985 method1 = ((MonoMethodInflated*) method1)->declaring;
3986 if (method2->is_inflated)
3987 method2 = ((MonoMethodInflated*) method2)->declaring;
3989 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3993 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3995 // Properties are hide-by-name-and-signature
3996 if (!g_str_equal (prop1->name, prop2->name))
3999 /* If we see a property in a generic method, we want to
4000 compare the generic signatures, not the inflated signatures
4001 because we might conflate two properties that were
4005 public T this[T t] { getter { return t; } } // method 1
4006 public U this[U u] { getter { return u; } } // method 2
4009 If we see int Foo<int,int>::Item[int] we need to know if
4010 the indexer came from method 1 or from method 2, and we
4011 shouldn't conflate them. (Bugzilla 36283)
4013 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4016 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4023 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4028 return method_nonpublic (accessor, start_klass);
4031 ICALL_EXPORT MonoArray*
4032 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4036 MonoClass *startklass, *klass;
4042 gchar *propname = NULL;
4043 int (*compare_func) (const char *s1, const char *s2) = NULL;
4045 GHashTable *properties = NULL;
4046 MonoPtrArray tmp_array;
4048 mono_error_init (&error);
4050 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4052 domain = ((MonoObject *)type)->vtable->domain;
4053 if (type->type->byref)
4054 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4055 klass = startklass = mono_class_from_mono_type (type->type);
4058 propname = mono_string_to_utf8 (name);
4059 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4062 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4064 mono_class_setup_methods (klass);
4065 mono_class_setup_vtable (klass);
4066 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4070 while ((prop = mono_class_get_properties (klass, &iter))) {
4076 flags = method->flags;
4079 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4080 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4081 if (bflags & BFLAGS_Public)
4083 } else if (bflags & BFLAGS_NonPublic) {
4084 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4085 property_accessor_nonpublic(prop->set, startklass == klass)) {
4092 if (flags & METHOD_ATTRIBUTE_STATIC) {
4093 if (bflags & BFLAGS_Static)
4094 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4097 if (bflags & BFLAGS_Instance)
4106 if (compare_func (propname, prop->name))
4110 if (g_hash_table_lookup (properties, prop))
4113 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4116 mono_ptr_array_append (tmp_array, pr);
4118 g_hash_table_insert (properties, prop, prop);
4120 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4123 g_hash_table_destroy (properties);
4126 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4127 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4128 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4130 mono_ptr_array_destroy (tmp_array);
4137 if (mono_class_has_failure (klass)) {
4138 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4140 mono_error_set_from_loader_error (&error);
4141 mono_loader_clear_error ();
4146 g_hash_table_destroy (properties);
4149 mono_ptr_array_destroy (tmp_array);
4151 mono_error_set_pending_exception (&error);
4157 event_hash (gconstpointer data)
4159 MonoEvent *event = (MonoEvent*)data;
4161 return g_str_hash (event->name);
4165 event_equal (MonoEvent *event1, MonoEvent *event2)
4167 // Events are hide-by-name
4168 return g_str_equal (event1->name, event2->name);
4171 ICALL_EXPORT MonoArray*
4172 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4176 MonoClass *startklass, *klass;
4182 char *utf8_name = NULL;
4183 int (*compare_func) (const char *s1, const char *s2) = NULL;
4184 GHashTable *events = NULL;
4185 MonoPtrArray tmp_array;
4187 mono_error_init (&error);
4189 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4191 domain = mono_object_domain (type);
4192 if (type->type->byref)
4193 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4194 klass = startklass = mono_class_from_mono_type (type->type);
4196 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4198 mono_class_setup_methods (klass);
4199 mono_class_setup_vtable (klass);
4200 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4204 while ((event = mono_class_get_events (klass, &iter))) {
4206 method = event->add;
4208 method = event->remove;
4210 method = event->raise;
4212 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4213 if (bflags & BFLAGS_Public)
4215 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4216 if (bflags & BFLAGS_NonPublic)
4221 if (bflags & BFLAGS_NonPublic)
4227 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4228 if (bflags & BFLAGS_Static)
4229 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4232 if (bflags & BFLAGS_Instance)
4237 if (bflags & BFLAGS_Instance)
4243 if (utf8_name == NULL) {
4244 utf8_name = mono_string_to_utf8 (name);
4245 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4248 if (compare_func (event->name, utf8_name))
4252 if (g_hash_table_lookup (events, event))
4255 MonoReflectionEvent *ev_obj;
4256 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4259 mono_ptr_array_append (tmp_array, ev_obj);
4261 g_hash_table_insert (events, event, event);
4263 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4266 g_hash_table_destroy (events);
4268 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4270 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4271 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4273 mono_ptr_array_destroy (tmp_array);
4275 if (utf8_name != NULL)
4281 if (mono_class_has_failure (klass)) {
4282 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4284 mono_error_set_from_loader_error (&error);
4285 mono_loader_clear_error ();
4291 g_hash_table_destroy (events);
4292 if (utf8_name != NULL)
4295 mono_ptr_array_destroy (tmp_array);
4297 mono_error_set_pending_exception (&error);
4301 ICALL_EXPORT MonoArray*
4302 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4305 MonoReflectionType *rt;
4313 MonoPtrArray tmp_array;
4315 domain = ((MonoObject *)type)->vtable->domain;
4316 if (type->type->byref)
4317 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4318 klass = mono_class_from_mono_type (type->type);
4321 * If a nested type is generic, return its generic type definition.
4322 * Note that this means that the return value is essentially the set
4323 * of nested types of the generic type definition of @klass.
4325 * A note in MSDN claims that a generic type definition can have
4326 * nested types that aren't generic. In any case, the container of that
4327 * nested type would be the generic type definition.
4329 if (klass->generic_class)
4330 klass = klass->generic_class->container_class;
4332 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4334 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4336 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4337 if (bflags & BFLAGS_Public)
4340 if (bflags & BFLAGS_NonPublic)
4348 str = mono_string_to_utf8 (name);
4349 mono_identifier_unescape_type_name_chars (str);
4352 if (strcmp (nested->name, str))
4356 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4357 mono_error_raise_exception (&error);
4359 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4362 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4364 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4365 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4367 mono_ptr_array_destroy (tmp_array);
4375 ICALL_EXPORT MonoReflectionType*
4376 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4379 MonoReflectionType *ret;
4381 MonoType *type = NULL;
4382 MonoTypeNameParse info;
4383 gboolean type_resolve;
4385 /* On MS.NET, this does not fire a TypeResolve event */
4386 type_resolve = TRUE;
4387 str = mono_string_to_utf8 (name);
4388 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4389 if (!mono_reflection_parse_type (str, &info)) {
4391 mono_reflection_free_type_info (&info);
4393 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4396 /*g_print ("failed parse\n");*/
4400 if (info.assembly.name) {
4402 mono_reflection_free_type_info (&info);
4404 /* 1.0 and 2.0 throw different exceptions */
4405 if (mono_defaults.generic_ilist_class)
4406 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4408 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4414 if (module != NULL) {
4415 if (module->image) {
4416 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4417 if (!is_ok (&error)) {
4419 mono_reflection_free_type_info (&info);
4420 mono_error_set_pending_exception (&error);
4427 if (assembly_is_dynamic (assembly->assembly)) {
4428 /* Enumerate all modules */
4429 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4433 if (abuilder->modules) {
4434 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4435 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4436 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4437 if (!is_ok (&error)) {
4439 mono_reflection_free_type_info (&info);
4440 mono_error_set_pending_exception (&error);
4448 if (!type && abuilder->loaded_modules) {
4449 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4450 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4451 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4452 if (!is_ok (&error)) {
4454 mono_reflection_free_type_info (&info);
4455 mono_error_set_pending_exception (&error);
4464 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4465 if (!is_ok (&error)) {
4467 mono_reflection_free_type_info (&info);
4468 mono_error_set_pending_exception (&error);
4473 mono_reflection_free_type_info (&info);
4475 MonoException *e = NULL;
4478 e = mono_get_exception_type_load (name, NULL);
4480 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4481 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4483 mono_loader_clear_error ();
4486 mono_set_pending_exception (e);
4488 } else if (mono_loader_get_last_error ()) {
4490 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4493 mono_loader_clear_error ();
4496 if (type->type == MONO_TYPE_CLASS) {
4497 MonoClass *klass = mono_type_get_class (type);
4499 /* need to report exceptions ? */
4500 if (throwOnError && mono_class_has_failure (klass)) {
4501 /* report SecurityException (or others) that occured when loading the assembly */
4502 MonoException *exc = mono_class_get_exception_for_failure (klass);
4503 mono_loader_clear_error ();
4504 mono_set_pending_exception (exc);
4509 /* g_print ("got it\n"); */
4510 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4511 mono_error_set_pending_exception (&error);
4517 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4520 gchar *shadow_ini_file;
4523 /* Check for shadow-copied assembly */
4524 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4525 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4527 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4528 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4534 g_free (shadow_ini_file);
4535 if (content != NULL) {
4538 *filename = content;
4545 ICALL_EXPORT MonoString *
4546 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4548 MonoDomain *domain = mono_object_domain (assembly);
4549 MonoAssembly *mass = assembly->assembly;
4550 MonoString *res = NULL;
4555 if (g_path_is_absolute (mass->image->name)) {
4556 absolute = g_strdup (mass->image->name);
4557 dirname = g_path_get_dirname (absolute);
4559 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4560 dirname = g_strdup (mass->basedir);
4563 replace_shadow_path (domain, dirname, &absolute);
4568 for (i = strlen (absolute) - 1; i >= 0; i--)
4569 if (absolute [i] == '\\')
4574 uri = g_filename_to_uri (absolute, NULL, NULL);
4576 const char *prepend = "file://";
4578 if (*absolute == '/' && *(absolute + 1) == '/') {
4581 prepend = "file:///";
4584 uri = g_strconcat (prepend, absolute, NULL);
4588 res = mono_string_new (domain, uri);
4595 ICALL_EXPORT MonoBoolean
4596 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4598 MonoAssembly *mass = assembly->assembly;
4600 return mass->in_gac;
4603 ICALL_EXPORT MonoReflectionAssembly*
4604 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4609 MonoImageOpenStatus status;
4610 MonoReflectionAssembly* result = NULL;
4612 name = mono_string_to_utf8 (mname);
4613 res = mono_assembly_load_with_partial_name (name, &status);
4619 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4621 mono_error_set_pending_exception (&error);
4625 ICALL_EXPORT MonoString *
4626 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4628 MonoDomain *domain = mono_object_domain (assembly);
4631 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4636 ICALL_EXPORT MonoBoolean
4637 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4639 return assembly->assembly->ref_only;
4642 ICALL_EXPORT MonoString *
4643 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4645 MonoDomain *domain = mono_object_domain (assembly);
4647 return mono_string_new (domain, assembly->assembly->image->version);
4650 ICALL_EXPORT MonoReflectionMethod*
4651 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4654 MonoReflectionMethod *res = NULL;
4657 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4661 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4662 if (!mono_error_ok (&error))
4665 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4668 if (!mono_error_ok (&error))
4669 mono_error_set_pending_exception (&error);
4673 ICALL_EXPORT MonoReflectionModule*
4674 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4677 MonoReflectionModule *result = NULL;
4678 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4679 if (!mono_error_ok (&error))
4680 mono_error_set_pending_exception (&error);
4684 ICALL_EXPORT MonoArray*
4685 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4687 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4688 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4692 for (i = 0; i < table->rows; ++i) {
4693 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4694 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4700 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4702 static MonoMethod *create_version = NULL;
4706 mono_error_init (error);
4709 if (!create_version) {
4710 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4711 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4712 g_assert (create_version);
4713 mono_method_desc_free (desc);
4719 args [3] = &revision;
4720 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4721 return_val_if_nok (error, NULL);
4723 mono_runtime_invoke_checked (create_version, result, args, error);
4724 return_val_if_nok (error, NULL);
4729 ICALL_EXPORT MonoArray*
4730 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4734 MonoDomain *domain = mono_object_domain (assembly);
4736 static MonoMethod *create_culture = NULL;
4737 MonoImage *image = assembly->assembly->image;
4741 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4744 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4746 if (count > 0 && !create_culture) {
4747 MonoMethodDesc *desc = mono_method_desc_new (
4748 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4749 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4750 g_assert (create_culture);
4751 mono_method_desc_free (desc);
4754 for (i = 0; i < count; i++) {
4755 MonoObject *version;
4756 MonoReflectionAssemblyName *aname;
4757 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4759 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4761 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4762 domain, mono_class_get_assembly_name_class (), &error);
4763 mono_error_raise_exception (&error);
4765 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4767 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4768 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4769 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4770 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4771 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4772 aname->versioncompat = 1; /* SameMachine (default) */
4773 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4775 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4776 mono_error_raise_exception (&error);
4778 MONO_OBJECT_SETREF (aname, version, version);
4780 if (create_culture) {
4782 MonoBoolean assembly_ref = 1;
4783 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4784 args [1] = &assembly_ref;
4786 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4787 mono_error_raise_exception (&error);
4789 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4792 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4793 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4794 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4796 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4797 /* public key token isn't copied - the class library will
4798 automatically generate it from the public key if required */
4799 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4800 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4802 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4803 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4806 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4809 /* note: this function doesn't return the codebase on purpose (i.e. it can
4810 be used under partial trust as path information isn't present). */
4812 mono_array_setref (result, i, aname);
4817 /* move this in some file in mono/util/ */
4819 g_concat_dir_and_file (const char *dir, const char *file)
4821 g_return_val_if_fail (dir != NULL, NULL);
4822 g_return_val_if_fail (file != NULL, NULL);
4825 * If the directory name doesn't have a / on the end, we need
4826 * to add one so we get a proper path to the file
4828 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4829 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4831 return g_strconcat (dir, file, NULL);
4835 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4838 char *n = mono_string_to_utf8 (name);
4839 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4841 guint32 cols [MONO_MANIFEST_SIZE];
4842 guint32 impl, file_idx;
4846 for (i = 0; i < table->rows; ++i) {
4847 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4848 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4849 if (strcmp (val, n) == 0)
4853 if (i == table->rows)
4856 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4859 * this code should only be called after obtaining the
4860 * ResourceInfo and handling the other cases.
4862 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4863 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4865 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4870 module = assembly->assembly->image;
4873 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4874 mono_error_raise_exception (&error);
4875 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4877 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4880 ICALL_EXPORT gboolean
4881 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4884 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4886 guint32 cols [MONO_MANIFEST_SIZE];
4887 guint32 file_cols [MONO_FILE_SIZE];
4891 n = mono_string_to_utf8 (name);
4892 for (i = 0; i < table->rows; ++i) {
4893 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4894 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4895 if (strcmp (val, n) == 0)
4899 if (i == table->rows)
4902 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4903 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4906 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4907 case MONO_IMPLEMENTATION_FILE:
4908 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4909 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4910 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4911 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4912 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4913 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4916 info->location = RESOURCE_LOCATION_EMBEDDED;
4919 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4920 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4921 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4922 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4923 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4924 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4926 mono_set_pending_exception (ex);
4929 MonoReflectionAssembly *assm_obj;
4930 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4932 mono_error_set_pending_exception (&error);
4935 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4937 /* Obtain info recursively */
4938 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4939 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4942 case MONO_IMPLEMENTATION_EXP_TYPE:
4943 g_assert_not_reached ();
4951 ICALL_EXPORT MonoObject*
4952 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4954 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4955 MonoArray *result = NULL;
4960 /* check hash if needed */
4962 n = mono_string_to_utf8 (name);
4963 for (i = 0; i < table->rows; ++i) {
4964 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4965 if (strcmp (val, n) == 0) {
4968 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4969 fn = mono_string_new (mono_object_domain (assembly), n);
4971 return (MonoObject*)fn;
4979 for (i = 0; i < table->rows; ++i) {
4980 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4984 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4987 for (i = 0; i < table->rows; ++i) {
4988 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4989 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4990 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4991 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4996 return (MonoObject*)result;
4999 ICALL_EXPORT MonoArray*
5000 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5003 MonoDomain *domain = mono_domain_get();
5006 int i, j, file_count = 0;
5007 MonoImage **modules;
5008 guint32 module_count, real_module_count;
5009 MonoTableInfo *table;
5010 guint32 cols [MONO_FILE_SIZE];
5011 MonoImage *image = assembly->assembly->image;
5013 g_assert (image != NULL);
5014 g_assert (!assembly_is_dynamic (assembly->assembly));
5016 table = &image->tables [MONO_TABLE_FILE];
5017 file_count = table->rows;
5019 modules = image->modules;
5020 module_count = image->module_count;
5022 real_module_count = 0;
5023 for (i = 0; i < module_count; ++i)
5025 real_module_count ++;
5027 klass = mono_class_get_module_class ();
5028 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5030 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5031 mono_error_raise_exception (&error);
5032 mono_array_setref (res, 0, image_obj);
5034 for (i = 0; i < module_count; ++i)
5036 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5037 mono_error_raise_exception (&error);
5038 mono_array_setref (res, j, rm);
5042 for (i = 0; i < file_count; ++i, ++j) {
5043 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5044 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5045 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5046 mono_error_raise_exception (&error);
5047 mono_array_setref (res, j, rm);
5050 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5052 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5053 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5056 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5057 mono_error_raise_exception (&error);
5058 mono_array_setref (res, j, rm);
5065 ICALL_EXPORT MonoReflectionMethod*
5066 ves_icall_GetCurrentMethod (void)
5068 MonoReflectionMethod *res = NULL;
5071 MonoMethod *m = mono_method_get_last_managed ();
5074 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5078 while (m->is_inflated)
5079 m = ((MonoMethodInflated*)m)->declaring;
5081 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5082 mono_error_raise_exception (&error);
5088 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5091 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5094 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5095 //method is inflated, we should inflate it on the other class
5096 MonoGenericContext ctx;
5097 ctx.method_inst = inflated->context.method_inst;
5098 ctx.class_inst = inflated->context.class_inst;
5099 if (klass->generic_class)
5100 ctx.class_inst = klass->generic_class->context.class_inst;
5101 else if (klass->generic_container)
5102 ctx.class_inst = klass->generic_container->context.class_inst;
5103 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5104 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5108 mono_class_setup_methods (method->klass);
5109 if (mono_class_has_failure (method->klass))
5111 for (i = 0; i < method->klass->method.count; ++i) {
5112 if (method->klass->methods [i] == method) {
5117 mono_class_setup_methods (klass);
5118 if (mono_class_has_failure (klass))
5120 g_assert (offset >= 0 && offset < klass->method.count);
5121 return klass->methods [offset];
5124 ICALL_EXPORT MonoReflectionMethod*
5125 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5127 MonoReflectionMethod *res = NULL;
5131 klass = mono_class_from_mono_type (type);
5132 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5134 if (method->klass != klass) {
5135 method = mono_method_get_equivalent_method (method, klass);
5140 klass = method->klass;
5141 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5142 mono_error_raise_exception (&error);
5146 ICALL_EXPORT MonoReflectionMethodBody*
5147 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5150 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5151 mono_error_set_pending_exception (&error);
5155 ICALL_EXPORT MonoReflectionAssembly*
5156 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5159 MonoReflectionAssembly *result;
5160 MonoMethod *dest = NULL;
5162 mono_stack_walk_no_il (get_executing, &dest);
5164 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5166 mono_error_set_pending_exception (&error);
5171 ICALL_EXPORT MonoReflectionAssembly*
5172 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5175 MonoReflectionAssembly *result;
5176 MonoDomain* domain = mono_domain_get ();
5178 if (!domain->entry_assembly)
5181 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5183 mono_error_set_pending_exception (&error);
5187 ICALL_EXPORT MonoReflectionAssembly*
5188 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5193 MonoReflectionAssembly *result;
5196 mono_stack_walk_no_il (get_executing, &dest);
5198 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5202 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5205 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5207 mono_error_set_pending_exception (&error);
5211 ICALL_EXPORT MonoString *
5212 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5213 gboolean assembly_qualified)
5215 MonoDomain *domain = mono_object_domain (object);
5216 MonoTypeNameFormat format;
5221 format = assembly_qualified ?
5222 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5223 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5225 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5227 name = mono_type_get_name_full (object->type, format);
5231 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5236 res = mono_string_new (domain, name);
5243 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5246 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5248 mono_class_init_checked (klass, &error);
5249 mono_error_raise_exception (&error);
5250 return mono_security_core_clr_class_level (klass);
5254 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5256 MonoClassField *field = rfield->field;
5257 return mono_security_core_clr_field_level (field, TRUE);
5261 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5263 MonoMethod *method = rfield->method;
5264 return mono_security_core_clr_method_level (method, TRUE);
5268 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)
5270 static MonoMethod *create_culture = NULL;
5274 const char *pkey_ptr;
5276 MonoBoolean assembly_ref = 0;
5278 mono_error_init (error);
5280 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5281 aname->major = name->major;
5282 aname->minor = name->minor;
5283 aname->build = name->build;
5284 aname->flags = name->flags;
5285 aname->revision = name->revision;
5286 aname->hashalg = name->hash_alg;
5287 aname->versioncompat = 1; /* SameMachine (default) */
5288 aname->processor_architecture = name->arch;
5290 if (by_default_version) {
5291 MonoObject *version;
5293 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5294 return_if_nok (error);
5296 MONO_OBJECT_SETREF (aname, version, version);
5300 if (absolute != NULL && *absolute != '\0') {
5301 const gchar *prepend = "file://";
5304 codebase = g_strdup (absolute);
5309 for (i = strlen (codebase) - 1; i >= 0; i--)
5310 if (codebase [i] == '\\')
5313 if (*codebase == '/' && *(codebase + 1) == '/') {
5316 prepend = "file:///";
5320 result = g_strconcat (prepend, codebase, NULL);
5326 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5330 if (!create_culture) {
5331 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5332 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5333 g_assert (create_culture);
5334 mono_method_desc_free (desc);
5337 if (name->culture) {
5338 args [0] = mono_string_new (domain, name->culture);
5339 args [1] = &assembly_ref;
5341 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5342 return_if_nok (error);
5344 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5347 if (name->public_key) {
5348 pkey_ptr = (char*)name->public_key;
5349 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5351 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5352 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5353 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5354 } else if (default_publickey) {
5355 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5356 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5359 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5360 if (name->public_key_token [0]) {
5364 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5365 p = mono_array_addr (aname->keyToken, char, 0);
5367 for (i = 0, j = 0; i < 8; i++) {
5368 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5369 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5372 } else if (default_token) {
5373 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5377 ICALL_EXPORT MonoString *
5378 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5380 MonoDomain *domain = mono_object_domain (assembly);
5381 MonoAssembly *mass = assembly->assembly;
5385 name = mono_stringify_assembly_name (&mass->aname);
5386 res = mono_string_new (domain, name);
5393 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5397 MonoAssembly *mass = assembly->assembly;
5399 if (g_path_is_absolute (mass->image->name)) {
5400 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5401 mono_error_set_pending_exception (&error);
5404 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5406 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5407 mono_error_set_pending_exception (&error);
5413 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5417 MonoImageOpenStatus status = MONO_IMAGE_OK;
5420 MonoAssemblyName name;
5423 filename = mono_string_to_utf8 (fname);
5425 dirname = g_path_get_dirname (filename);
5426 replace_shadow_path (mono_domain_get (), dirname, &filename);
5429 image = mono_image_open (filename, &status);
5435 if (status == MONO_IMAGE_IMAGE_INVALID)
5436 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5438 exc = mono_get_exception_file_not_found2 (NULL, fname);
5439 mono_set_pending_exception (exc);
5443 res = mono_assembly_fill_assembly_name (image, &name);
5445 mono_image_close (image);
5447 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5451 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5452 mono_error_set_pending_exception (&error);
5454 mono_image_close (image);
5458 ICALL_EXPORT MonoBoolean
5459 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5460 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5462 MonoBoolean result = FALSE;
5463 MonoDeclSecurityEntry entry;
5465 /* SecurityAction.RequestMinimum */
5466 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5467 *minimum = entry.blob;
5468 *minLength = entry.size;
5471 /* SecurityAction.RequestOptional */
5472 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5473 *optional = entry.blob;
5474 *optLength = entry.size;
5477 /* SecurityAction.RequestRefuse */
5478 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5479 *refused = entry.blob;
5480 *refLength = entry.size;
5488 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5490 guint32 attrs, visibility;
5492 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5493 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5494 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5497 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5503 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5505 MonoReflectionType *rt;
5508 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5511 mono_error_init (error);
5513 /* we start the count from 1 because we skip the special type <Module> */
5516 for (i = 1; i < tdef->rows; ++i) {
5517 if (mono_module_type_is_visible (tdef, image, i + 1))
5521 count = tdef->rows - 1;
5523 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5524 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5526 for (i = 1; i < tdef->rows; ++i) {
5527 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5528 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5529 mono_loader_assert_no_error (); /* Plug any leaks */
5530 mono_error_assert_ok (error);
5533 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5534 return_val_if_nok (error, NULL);
5536 mono_array_setref (res, count, rt);
5538 MonoException *ex = mono_error_convert_to_exception (error);
5539 mono_array_setref (*exceptions, count, ex);
5548 ICALL_EXPORT MonoArray*
5549 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5552 MonoArray *res = NULL;
5553 MonoArray *exceptions = NULL;
5554 MonoImage *image = NULL;
5555 MonoTableInfo *table = NULL;
5558 int i, len, ex_count;
5560 domain = mono_object_domain (assembly);
5562 g_assert (!assembly_is_dynamic (assembly->assembly));
5563 image = assembly->assembly->image;
5564 table = &image->tables [MONO_TABLE_FILE];
5565 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5566 mono_error_raise_exception (&error);
5568 /* Append data from all modules in the assembly */
5569 for (i = 0; i < table->rows; ++i) {
5570 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5571 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5576 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5577 mono_error_raise_exception (&error);
5579 /* Append the new types to the end of the array */
5580 if (mono_array_length (res2) > 0) {
5582 MonoArray *res3, *ex3;
5584 len1 = mono_array_length (res);
5585 len2 = mono_array_length (res2);
5587 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5588 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5589 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5592 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5593 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5594 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5601 /* the ReflectionTypeLoadException must have all the types (Types property),
5602 * NULL replacing types which throws an exception. The LoaderException must
5603 * contain all exceptions for NULL items.
5606 len = mono_array_length (res);
5609 for (i = 0; i < len; i++) {
5610 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5614 klass = mono_type_get_class (t->type);
5615 if ((klass != NULL) && mono_class_has_failure (klass)) {
5616 /* keep the class in the list */
5617 list = g_list_append (list, klass);
5618 /* and replace Type with NULL */
5619 mono_array_setref (res, i, NULL);
5626 if (list || ex_count) {
5628 MonoException *exc = NULL;
5629 MonoArray *exl = NULL;
5630 int j, length = g_list_length (list) + ex_count;
5632 mono_loader_clear_error ();
5634 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5635 /* Types for which mono_class_get_checked () succeeded */
5636 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5637 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5638 mono_array_setref (exl, i, exc);
5640 /* Types for which it don't */
5641 for (j = 0; j < mono_array_length (exceptions); ++j) {
5642 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5644 g_assert (i < length);
5645 mono_array_setref (exl, i, exc);
5652 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5653 if (!is_ok (&error)) {
5654 mono_error_set_pending_exception (&error);
5657 mono_loader_clear_error ();
5658 mono_set_pending_exception (exc);
5665 ICALL_EXPORT gboolean
5666 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5669 MonoAssemblyName aname;
5670 MonoDomain *domain = mono_object_domain (name);
5672 gboolean is_version_defined;
5673 gboolean is_token_defined;
5675 aname.public_key = NULL;
5676 val = mono_string_to_utf8 (assname);
5677 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5678 g_free ((guint8*) aname.public_key);
5683 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5684 mono_error_set_pending_exception (&error);
5686 mono_assembly_name_free (&aname);
5687 g_free ((guint8*) aname.public_key);
5693 ICALL_EXPORT MonoReflectionType*
5694 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5697 MonoReflectionType *ret;
5698 MonoDomain *domain = mono_object_domain (module);
5701 g_assert (module->image);
5703 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5704 /* These images do not have a global type */
5707 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5708 if (!mono_error_ok (&error)) {
5709 mono_error_set_pending_exception (&error);
5713 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5714 if (!mono_error_ok (&error)) {
5715 mono_error_set_pending_exception (&error);
5723 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5725 /*if (module->image)
5726 mono_image_close (module->image);*/
5729 ICALL_EXPORT MonoString*
5730 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5732 MonoDomain *domain = mono_object_domain (module);
5734 g_assert (module->image);
5735 return mono_string_new (domain, module->image->guid);
5738 ICALL_EXPORT gpointer
5739 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5742 if (module->image && module->image->is_module_handle)
5743 return module->image->raw_data;
5746 return (gpointer) (-1);
5750 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5752 if (image_is_dynamic (image)) {
5753 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5754 *pe_kind = dyn->pe_kind;
5755 *machine = dyn->machine;
5758 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5759 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5764 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5766 return (image->md_version_major << 16) | (image->md_version_minor);
5769 ICALL_EXPORT MonoArray*
5770 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5773 MonoArray *exceptions;
5777 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5781 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5782 mono_error_raise_exception (&error);
5784 for (i = 0; i < mono_array_length (exceptions); ++i) {
5785 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5787 mono_set_pending_exception (ex);
5796 mono_memberref_is_method (MonoImage *image, guint32 token)
5798 if (!image_is_dynamic (image)) {
5799 guint32 cols [MONO_MEMBERREF_SIZE];
5801 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5802 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5803 mono_metadata_decode_blob_size (sig, &sig);
5804 return (*sig != 0x6);
5806 MonoClass *handle_class;
5808 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5811 return mono_defaults.methodhandle_class == handle_class;
5816 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5819 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5820 mono_array_addr (type_args, MonoType*, 0));
5822 context->class_inst = NULL;
5824 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5825 mono_array_addr (method_args, MonoType*, 0));
5827 context->method_inst = NULL;
5830 ICALL_EXPORT MonoType*
5831 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5834 int table = mono_metadata_token_table (token);
5835 int index = mono_metadata_token_index (token);
5836 MonoGenericContext context;
5839 *resolve_error = ResolveTokenError_Other;
5841 /* Validate token */
5842 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5843 (table != MONO_TABLE_TYPESPEC)) {
5844 *resolve_error = ResolveTokenError_BadTable;
5848 if (image_is_dynamic (image)) {
5849 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5850 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5851 return klass ? &klass->byval_arg : NULL;
5854 init_generic_context_from_args (&context, type_args, method_args);
5855 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5856 return klass ? &klass->byval_arg : NULL;
5859 if ((index <= 0) || (index > image->tables [table].rows)) {
5860 *resolve_error = ResolveTokenError_OutOfRange;
5864 init_generic_context_from_args (&context, type_args, method_args);
5865 klass = mono_class_get_checked (image, token, &error);
5867 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5868 if (!mono_error_ok (&error)) {
5869 mono_error_set_pending_exception (&error);
5874 return &klass->byval_arg;
5879 ICALL_EXPORT MonoMethod*
5880 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5883 int table = mono_metadata_token_table (token);
5884 int index = mono_metadata_token_index (token);
5885 MonoGenericContext context;
5888 *resolve_error = ResolveTokenError_Other;
5890 /* Validate token */
5891 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5892 (table != MONO_TABLE_MEMBERREF)) {
5893 *resolve_error = ResolveTokenError_BadTable;
5897 if (image_is_dynamic (image)) {
5898 if (table == MONO_TABLE_METHOD)
5899 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5901 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5902 *resolve_error = ResolveTokenError_BadTable;
5906 init_generic_context_from_args (&context, type_args, method_args);
5907 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5910 if ((index <= 0) || (index > image->tables [table].rows)) {
5911 *resolve_error = ResolveTokenError_OutOfRange;
5914 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5915 *resolve_error = ResolveTokenError_BadTable;
5919 init_generic_context_from_args (&context, type_args, method_args);
5920 method = mono_get_method_checked (image, token, NULL, &context, &error);
5921 mono_error_set_pending_exception (&error);
5926 ICALL_EXPORT MonoString*
5927 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5929 int index = mono_metadata_token_index (token);
5931 *error = ResolveTokenError_Other;
5933 /* Validate token */
5934 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5935 *error = ResolveTokenError_BadTable;
5939 if (image_is_dynamic (image))
5940 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5942 if ((index <= 0) || (index >= image->heap_us.size)) {
5943 *error = ResolveTokenError_OutOfRange;
5947 /* FIXME: What to do if the index points into the middle of a string ? */
5949 return mono_ldstr (mono_domain_get (), image, index);
5952 ICALL_EXPORT MonoClassField*
5953 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5957 int table = mono_metadata_token_table (token);
5958 int index = mono_metadata_token_index (token);
5959 MonoGenericContext context;
5960 MonoClassField *field;
5962 *resolve_error = ResolveTokenError_Other;
5964 /* Validate token */
5965 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5966 *resolve_error = ResolveTokenError_BadTable;
5970 if (image_is_dynamic (image)) {
5971 if (table == MONO_TABLE_FIELD)
5972 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5974 if (mono_memberref_is_method (image, token)) {
5975 *resolve_error = ResolveTokenError_BadTable;
5979 init_generic_context_from_args (&context, type_args, method_args);
5980 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5983 if ((index <= 0) || (index > image->tables [table].rows)) {
5984 *resolve_error = ResolveTokenError_OutOfRange;
5987 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5988 *resolve_error = ResolveTokenError_BadTable;
5992 init_generic_context_from_args (&context, type_args, method_args);
5993 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5994 mono_error_set_pending_exception (&error);
6000 ICALL_EXPORT MonoObject*
6001 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6005 int table = mono_metadata_token_table (token);
6007 *error = ResolveTokenError_Other;
6010 case MONO_TABLE_TYPEDEF:
6011 case MONO_TABLE_TYPEREF:
6012 case MONO_TABLE_TYPESPEC: {
6013 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6015 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6016 mono_error_raise_exception (&merror);
6023 case MONO_TABLE_METHOD:
6024 case MONO_TABLE_METHODSPEC: {
6025 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6027 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6028 mono_error_raise_exception (&merror);
6034 case MONO_TABLE_FIELD: {
6035 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6037 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6038 mono_error_raise_exception (&merror);
6044 case MONO_TABLE_MEMBERREF:
6045 if (mono_memberref_is_method (image, token)) {
6046 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6048 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6049 mono_error_raise_exception (&merror);
6056 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6058 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6059 mono_error_raise_exception (&merror);
6068 *error = ResolveTokenError_BadTable;
6074 ICALL_EXPORT MonoArray*
6075 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6077 int table = mono_metadata_token_table (token);
6078 int idx = mono_metadata_token_index (token);
6079 MonoTableInfo *tables = image->tables;
6084 *error = ResolveTokenError_OutOfRange;
6086 /* FIXME: Support other tables ? */
6087 if (table != MONO_TABLE_STANDALONESIG)
6090 if (image_is_dynamic (image))
6093 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6096 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6098 ptr = mono_metadata_blob_heap (image, sig);
6099 len = mono_metadata_decode_blob_size (ptr, &ptr);
6101 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6102 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6106 ICALL_EXPORT MonoReflectionType*
6107 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6110 MonoReflectionType *ret;
6112 int isbyref = 0, rank;
6113 char *str = mono_string_to_utf8 (smodifiers);
6116 klass = mono_class_from_mono_type (tb->type.type);
6118 /* logic taken from mono_reflection_parse_type(): keep in sync */
6122 if (isbyref) { /* only one level allowed by the spec */
6131 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6132 mono_error_raise_exception (&error);
6136 klass = mono_ptr_class_get (&klass->byval_arg);
6137 mono_class_init (klass);
6148 else if (*p != '*') { /* '*' means unknown lower bound */
6159 klass = mono_array_class_get (klass, rank);
6160 mono_class_init (klass);
6169 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6170 mono_error_raise_exception (&error);
6175 ICALL_EXPORT MonoBoolean
6176 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6182 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6188 check_for_invalid_type (MonoClass *klass, MonoError *error)
6193 mono_error_init (error);
6195 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6198 name = mono_type_get_full_name (klass);
6199 str = mono_string_new (mono_domain_get (), name);
6201 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6204 ICALL_EXPORT MonoReflectionType *
6205 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6208 MonoReflectionType *ret;
6209 MonoClass *klass, *aklass;
6211 klass = mono_class_from_mono_type (type->type);
6212 check_for_invalid_type (klass, &error);
6213 mono_error_raise_exception (&error);
6215 if (rank == 0) //single dimentional array
6216 aklass = mono_array_class_get (klass, 1);
6218 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6220 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6221 mono_error_raise_exception (&error);
6226 ICALL_EXPORT MonoReflectionType *
6227 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6230 MonoReflectionType *ret;
6233 klass = mono_class_from_mono_type (type->type);
6234 mono_class_init_checked (klass, &error);
6235 mono_error_raise_exception (&error);
6236 check_for_invalid_type (klass, &error);
6237 mono_error_raise_exception (&error);
6239 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6240 mono_error_raise_exception (&error);
6245 ICALL_EXPORT MonoReflectionType *
6246 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6249 MonoReflectionType *ret;
6250 MonoClass *klass, *pklass;
6252 klass = mono_class_from_mono_type (type->type);
6253 mono_class_init_checked (klass, &error);
6254 mono_error_raise_exception (&error);
6255 check_for_invalid_type (klass, &error);
6256 mono_error_raise_exception (&error);
6258 pklass = mono_ptr_class_get (type->type);
6260 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6261 mono_error_raise_exception (&error);
6266 ICALL_EXPORT MonoObject *
6267 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6268 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6271 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6272 MonoObject *delegate;
6274 MonoMethod *method = info->method;
6276 mono_class_init_checked (delegate_class, &error);
6277 mono_error_raise_exception (&error);
6279 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6281 if (mono_security_core_clr_enabled ()) {
6282 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6286 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6287 mono_error_raise_exception (&error);
6289 if (method_is_dynamic (method)) {
6290 /* Creating a trampoline would leak memory */
6291 func = mono_compile_method (method);
6293 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6294 method = mono_object_get_virtual_method (target, method);
6295 func = mono_create_ftnptr (mono_domain_get (),
6296 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6299 mono_delegate_ctor_with_method (delegate, target, func, method);
6304 ICALL_EXPORT MonoMulticastDelegate *
6305 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6308 MonoMulticastDelegate *ret;
6310 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6312 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6313 mono_error_raise_exception (&error);
6314 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6319 ICALL_EXPORT MonoReflectionMethod*
6320 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6322 MonoReflectionMethod *ret = NULL;
6324 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6325 mono_error_raise_exception (&error);
6331 static inline gint32
6332 mono_array_get_byte_length (MonoArray *array)
6338 klass = array->obj.vtable->klass;
6340 if (array->bounds == NULL)
6341 length = array->max_length;
6344 for (i = 0; i < klass->rank; ++ i)
6345 length *= array->bounds [i].length;
6348 switch (klass->element_class->byval_arg.type) {
6351 case MONO_TYPE_BOOLEAN:
6355 case MONO_TYPE_CHAR:
6363 return length * sizeof (gpointer);
6374 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6376 return mono_array_get_byte_length (array);
6380 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6382 return mono_array_get (array, gint8, idx);
6386 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6388 mono_array_set (array, gint8, idx, value);
6391 ICALL_EXPORT MonoBoolean
6392 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6394 guint8 *src_buf, *dest_buf;
6397 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6401 g_assert (count >= 0);
6403 /* This is called directly from the class libraries without going through the managed wrapper */
6404 MONO_CHECK_ARG_NULL (src, FALSE);
6405 MONO_CHECK_ARG_NULL (dest, FALSE);
6407 /* watch out for integer overflow */
6408 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6411 src_buf = (guint8 *)src->vector + src_offset;
6412 dest_buf = (guint8 *)dest->vector + dest_offset;
6415 memcpy (dest_buf, src_buf, count);
6417 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6422 #ifndef DISABLE_REMOTING
6423 ICALL_EXPORT MonoObject *
6424 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6427 MonoDomain *domain = mono_object_domain (this_obj);
6429 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6430 MonoTransparentProxy *tp;
6434 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6435 mono_error_raise_exception (&error);
6436 tp = (MonoTransparentProxy*) res;
6438 MONO_OBJECT_SETREF (tp, rp, rp);
6439 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6440 klass = mono_class_from_mono_type (type);
6442 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6443 mono_class_setup_vtable (klass);
6444 if (mono_class_has_failure (klass)) {
6445 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6449 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6450 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6451 if (!is_ok (&error)) {
6452 mono_error_set_pending_exception (&error);
6456 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6460 ICALL_EXPORT MonoReflectionType *
6461 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6464 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6465 mono_error_raise_exception (&error);
6471 /* System.Environment */
6474 ves_icall_System_Environment_get_UserName (void)
6476 /* using glib is more portable */
6477 return mono_string_new (mono_domain_get (), g_get_user_name ());
6481 ICALL_EXPORT MonoString *
6482 ves_icall_System_Environment_get_MachineName (void)
6484 #if defined (HOST_WIN32)
6489 len = MAX_COMPUTERNAME_LENGTH + 1;
6490 buf = g_new (gunichar2, len);
6493 if (GetComputerName (buf, (PDWORD) &len)) {
6495 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6496 mono_error_raise_exception (&error);
6501 #elif !defined(DISABLE_SOCKETS)
6505 #if defined _SC_HOST_NAME_MAX
6506 n = sysconf (_SC_HOST_NAME_MAX);
6510 buf = g_malloc (n+1);
6512 if (gethostname (buf, n) == 0){
6514 result = mono_string_new (mono_domain_get (), buf);
6521 return mono_string_new (mono_domain_get (), "mono");
6526 ves_icall_System_Environment_get_Platform (void)
6528 #if defined (TARGET_WIN32)
6531 #elif defined(__MACH__)
6534 // Notice that the value is hidden from user code, and only exposed
6535 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6536 // define and making assumptions based on Unix/128/4 values before there
6537 // was a MacOS define. Lots of code would assume that not-Unix meant
6538 // Windows, but in this case, it would be OSX.
6547 ICALL_EXPORT MonoString *
6548 ves_icall_System_Environment_get_NewLine (void)
6550 #if defined (HOST_WIN32)
6551 return mono_string_new (mono_domain_get (), "\r\n");
6553 return mono_string_new (mono_domain_get (), "\n");
6557 ICALL_EXPORT MonoBoolean
6558 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6560 #if SIZEOF_VOID_P == 8
6564 gboolean isWow64Process = FALSE;
6565 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6566 return (MonoBoolean)isWow64Process;
6568 #elif defined(HAVE_SYS_UTSNAME_H)
6569 struct utsname name;
6571 if (uname (&name) >= 0) {
6572 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6579 ICALL_EXPORT MonoString *
6580 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6588 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6589 value = g_getenv (utf8_name);
6596 return mono_string_new (mono_domain_get (), value);
6600 * There is no standard way to get at environ.
6603 #ifndef __MINGW32_VERSION
6604 #if defined(__APPLE__)
6605 #if defined (TARGET_OSX)
6606 /* Apple defines this in crt_externs.h but doesn't provide that header for
6607 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6608 * in fact exist on all implementations (so far)
6610 gchar ***_NSGetEnviron(void);
6611 #define environ (*_NSGetEnviron())
6613 static char *mono_environ[1] = { NULL };
6614 #define environ mono_environ
6615 #endif /* defined (TARGET_OSX) */
6623 ICALL_EXPORT MonoArray *
6624 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6635 env_strings = GetEnvironmentStrings();
6638 env_string = env_strings;
6639 while (*env_string != '\0') {
6640 /* weird case that MS seems to skip */
6641 if (*env_string != '=')
6643 while (*env_string != '\0')
6649 domain = mono_domain_get ();
6650 names = mono_array_new (domain, mono_defaults.string_class, n);
6654 env_string = env_strings;
6655 while (*env_string != '\0') {
6656 /* weird case that MS seems to skip */
6657 if (*env_string != '=') {
6658 equal_str = wcschr(env_string, '=');
6659 g_assert(equal_str);
6661 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6662 mono_error_raise_exception (&error);
6663 mono_array_setref (names, n, str);
6666 while (*env_string != '\0')
6671 FreeEnvironmentStrings (env_strings);
6684 for (e = environ; *e != 0; ++ e)
6687 domain = mono_domain_get ();
6688 names = mono_array_new (domain, mono_defaults.string_class, n);
6691 for (e = environ; *e != 0; ++ e) {
6692 parts = g_strsplit (*e, "=", 2);
6694 str = mono_string_new (domain, *parts);
6695 mono_array_setref (names, n, str);
6708 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6710 #if !GLIB_CHECK_VERSION(2,4,0)
6711 #define g_setenv(a,b,c) setenv(a,b,c)
6712 #define g_unsetenv(a) unsetenv(a)
6716 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6719 gunichar2 *utf16_name, *utf16_value;
6721 gchar *utf8_name, *utf8_value;
6726 utf16_name = mono_string_to_utf16 (name);
6727 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6728 SetEnvironmentVariable (utf16_name, NULL);
6729 g_free (utf16_name);
6733 utf16_value = mono_string_to_utf16 (value);
6735 SetEnvironmentVariable (utf16_name, utf16_value);
6737 g_free (utf16_name);
6738 g_free (utf16_value);
6740 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6742 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6743 g_unsetenv (utf8_name);
6748 utf8_value = mono_string_to_utf8_checked (value, &error);
6749 if (!mono_error_ok (&error)) {
6751 mono_error_set_pending_exception (&error);
6754 g_setenv (utf8_name, utf8_value, TRUE);
6757 g_free (utf8_value);
6762 ves_icall_System_Environment_Exit (int result)
6764 mono_environment_exitcode_set (result);
6766 /* FIXME: There are some cleanup hangs that should be worked out, but
6767 * if the program is going to exit, everything will be cleaned up when
6768 * NaCl exits anyway.
6770 #ifndef __native_client__
6771 if (!mono_runtime_try_shutdown ())
6772 mono_thread_exit ();
6774 /* Suspend all managed threads since the runtime is going away */
6775 mono_thread_suspend_all_other_threads ();
6777 mono_runtime_quit ();
6780 /* we may need to do some cleanup here... */
6784 ICALL_EXPORT MonoString*
6785 ves_icall_System_Environment_GetGacPath (void)
6787 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6790 ICALL_EXPORT MonoString*
6791 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6793 #if defined (HOST_WIN32)
6794 #ifndef CSIDL_FLAG_CREATE
6795 #define CSIDL_FLAG_CREATE 0x8000
6798 WCHAR path [MAX_PATH];
6799 /* Create directory if no existing */
6800 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6805 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6806 mono_error_raise_exception (&error);
6810 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6812 return mono_string_new (mono_domain_get (), "");
6815 ICALL_EXPORT MonoArray *
6816 ves_icall_System_Environment_GetLogicalDrives (void)
6819 gunichar2 buf [256], *ptr, *dname;
6821 guint initial_size = 127, size = 128;
6824 MonoString *drivestr;
6825 MonoDomain *domain = mono_domain_get ();
6831 while (size > initial_size) {
6832 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6833 if (size > initial_size) {
6836 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6837 initial_size = size;
6851 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6856 while (*u16) { u16++; len ++; }
6857 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6858 mono_error_raise_exception (&error);
6859 mono_array_setref (result, ndrives++, drivestr);
6869 ICALL_EXPORT MonoString *
6870 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6872 gunichar2 volume_name [MAX_PATH + 1];
6874 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6876 return mono_string_from_utf16 (volume_name);
6879 ICALL_EXPORT MonoString *
6880 ves_icall_System_Environment_InternalGetHome (void)
6882 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6885 static const char *encodings [] = {
6887 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6888 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6889 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6891 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6892 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6893 "x_unicode_2_0_utf_7",
6895 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6896 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6898 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6901 "unicodefffe", "utf_16be",
6908 * Returns the internal codepage, if the value of "int_code_page" is
6909 * 1 at entry, and we can not compute a suitable code page number,
6910 * returns the code page as a string
6912 ICALL_EXPORT MonoString*
6913 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6918 char *codepage = NULL;
6920 int want_name = *int_code_page;
6923 *int_code_page = -1;
6925 g_get_charset (&cset);
6926 c = codepage = strdup (cset);
6927 for (c = codepage; *c; c++){
6928 if (isascii (*c) && isalpha (*c))
6933 /* g_print ("charset: %s\n", cset); */
6935 /* handle some common aliases */
6938 for (i = 0; p != 0; ){
6941 p = encodings [++i];
6944 if (strcmp (p, codepage) == 0){
6945 *int_code_page = code;
6948 p = encodings [++i];
6951 if (strstr (codepage, "utf_8") != NULL)
6952 *int_code_page |= 0x10000000;
6955 if (want_name && *int_code_page == -1)
6956 return mono_string_new (mono_domain_get (), cset);
6961 ICALL_EXPORT MonoBoolean
6962 ves_icall_System_Environment_get_HasShutdownStarted (void)
6964 if (mono_runtime_is_shutting_down ())
6967 if (mono_domain_is_unloading (mono_domain_get ()))
6974 ves_icall_System_Environment_BroadcastSettingChange (void)
6977 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6982 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6988 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6989 MonoReflectionMethod *method,
6990 MonoArray *out_args)
6992 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6995 #ifndef DISABLE_REMOTING
6996 ICALL_EXPORT MonoBoolean
6997 ves_icall_IsTransparentProxy (MonoObject *proxy)
7002 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7008 ICALL_EXPORT MonoReflectionMethod *
7009 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7010 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7012 MonoReflectionMethod *ret = NULL;
7017 MonoMethod **vtable;
7018 MonoMethod *res = NULL;
7020 MONO_CHECK_ARG_NULL (rtype, NULL);
7021 MONO_CHECK_ARG_NULL (rmethod, NULL);
7023 method = rmethod->method;
7024 klass = mono_class_from_mono_type (rtype->type);
7025 mono_class_init_checked (klass, &error);
7026 mono_error_raise_exception (&error);
7028 if (MONO_CLASS_IS_INTERFACE (klass))
7031 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7034 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7035 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7041 mono_class_setup_vtable (klass);
7042 vtable = klass->vtable;
7044 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7045 gboolean variance_used = FALSE;
7046 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7047 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7049 res = vtable [offs + method->slot];
7051 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7054 if (method->slot != -1)
7055 res = vtable [method->slot];
7061 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7062 mono_error_raise_exception (&error);
7067 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7073 klass = mono_class_from_mono_type (type->type);
7074 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7075 if (!is_ok (&error)) {
7076 mono_error_set_pending_exception (&error);
7080 mono_vtable_set_is_remote (vtable, enable);
7083 #else /* DISABLE_REMOTING */
7086 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7088 g_assert_not_reached ();
7093 ICALL_EXPORT MonoObject *
7094 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7101 domain = mono_object_domain (type);
7102 klass = mono_class_from_mono_type (type->type);
7103 mono_class_init_checked (klass, &error);
7104 mono_error_raise_exception (&error);
7106 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7107 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7111 if (klass->rank >= 1) {
7112 g_assert (klass->rank == 1);
7113 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7115 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7116 if (!is_ok (&error)) {
7117 mono_error_set_pending_exception (&error);
7120 /* Bypass remoting object creation check */
7121 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7122 mono_error_set_pending_exception (&error);
7128 ICALL_EXPORT MonoString *
7129 ves_icall_System_IO_get_temp_path (void)
7131 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7134 #ifndef PLATFORM_NO_DRIVEINFO
7135 ICALL_EXPORT MonoBoolean
7136 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7137 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7141 ULARGE_INTEGER wapi_free_bytes_avail;
7142 ULARGE_INTEGER wapi_total_number_of_bytes;
7143 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7145 *error = ERROR_SUCCESS;
7146 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7147 &wapi_total_number_of_free_bytes);
7150 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7151 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7152 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7154 *free_bytes_avail = 0;
7155 *total_number_of_bytes = 0;
7156 *total_number_of_free_bytes = 0;
7157 *error = GetLastError ();
7163 ICALL_EXPORT guint32
7164 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7166 return GetDriveType (mono_string_chars (root_path_name));
7170 ICALL_EXPORT gpointer
7171 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7173 return mono_compile_method (method);
7176 ICALL_EXPORT MonoString *
7177 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7182 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7184 #if defined (HOST_WIN32)
7185 /* Avoid mixing '/' and '\\' */
7188 for (i = strlen (path) - 1; i >= 0; i--)
7189 if (path [i] == '/')
7193 mcpath = mono_string_new (mono_domain_get (), path);
7200 get_bundled_app_config (void)
7202 const gchar *app_config;
7205 gchar *config_file_name, *config_file_path;
7206 gsize len, config_file_path_length, config_ext_length;
7209 domain = mono_domain_get ();
7210 file = domain->setup->configuration_file;
7211 if (!file || file->length == 0)
7214 // Retrieve config file and remove the extension
7215 config_file_name = mono_string_to_utf8 (file);
7216 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7217 if (!config_file_path)
7218 config_file_path = config_file_name;
7220 config_file_path_length = strlen (config_file_path);
7221 config_ext_length = strlen (".config");
7222 if (config_file_path_length <= config_ext_length)
7225 len = config_file_path_length - config_ext_length;
7226 module = (gchar *)g_malloc0 (len + 1);
7227 memcpy (module, config_file_path, len);
7228 // Get the config file from the module name
7229 app_config = mono_config_string_for_assembly_file (module);
7232 if (config_file_name != config_file_path)
7233 g_free (config_file_name);
7234 g_free (config_file_path);
7239 return mono_string_new (mono_domain_get (), app_config);
7243 get_bundled_machine_config (void)
7245 const gchar *machine_config;
7247 machine_config = mono_get_machine_config ();
7249 if (!machine_config)
7252 return mono_string_new (mono_domain_get (), machine_config);
7255 ICALL_EXPORT MonoString *
7256 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7261 path = g_path_get_dirname (mono_get_config_dir ());
7263 #if defined (HOST_WIN32)
7264 /* Avoid mixing '/' and '\\' */
7267 for (i = strlen (path) - 1; i >= 0; i--)
7268 if (path [i] == '/')
7272 ipath = mono_string_new (mono_domain_get (), path);
7278 ICALL_EXPORT gboolean
7279 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7281 MonoPEResourceDataEntry *entry;
7284 if (!assembly || !result || !size)
7289 image = assembly->assembly->image;
7290 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7294 *result = mono_image_rva_map (image, entry->rde_data_offset);
7299 *size = entry->rde_size;
7304 ICALL_EXPORT MonoBoolean
7305 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7307 return mono_is_debugger_attached ();
7310 ICALL_EXPORT MonoBoolean
7311 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7313 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7314 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7320 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7322 if (mono_get_runtime_callbacks ()->debug_log)
7323 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7327 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7329 #if defined (HOST_WIN32)
7330 OutputDebugString (mono_string_chars (message));
7332 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7336 /* Only used for value types */
7337 ICALL_EXPORT MonoObject *
7338 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7345 domain = mono_object_domain (type);
7346 klass = mono_class_from_mono_type (type->type);
7347 mono_class_init_checked (klass, &error);
7348 mono_error_raise_exception (&error);
7350 if (mono_class_is_nullable (klass))
7351 /* No arguments -> null */
7354 result = mono_object_new_checked (domain, klass, &error);
7355 mono_error_raise_exception (&error);
7359 ICALL_EXPORT MonoReflectionMethod *
7360 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7362 MonoReflectionMethod *ret = NULL;
7365 MonoClass *klass, *parent;
7366 MonoGenericContext *generic_inst = NULL;
7367 MonoMethod *method = m->method;
7368 MonoMethod *result = NULL;
7371 if (method->klass == NULL)
7374 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7375 MONO_CLASS_IS_INTERFACE (method->klass) ||
7376 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7379 slot = mono_method_get_vtable_slot (method);
7383 klass = method->klass;
7384 if (klass->generic_class) {
7385 generic_inst = mono_class_get_context (klass);
7386 klass = klass->generic_class->container_class;
7390 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7391 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7392 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7393 or klass is the generic container class and generic_inst is the instantiation.
7395 when we go to the parent, if the parent is an open constructed type, we need to
7396 replace the type parameters by the definitions from the generic_inst, and then take it
7397 apart again into the klass and the generic_inst.
7399 For cases like this:
7400 class C<T> : B<T, int> {
7401 public override void Foo () { ... }
7403 class B<U,V> : A<HashMap<U,V>> {
7404 public override void Foo () { ... }
7407 public virtual void Foo () { ... }
7410 if at each iteration the parent isn't open, we can skip inflating it. if at some
7411 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7414 MonoGenericContext *parent_inst = NULL;
7415 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7417 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7418 if (!mono_error_ok (&error)) {
7419 mono_error_set_pending_exception (&error);
7423 if (parent->generic_class) {
7424 parent_inst = mono_class_get_context (parent);
7425 parent = parent->generic_class->container_class;
7428 mono_class_setup_vtable (parent);
7429 if (parent->vtable_size <= slot)
7432 generic_inst = parent_inst;
7435 klass = klass->parent;
7438 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7439 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7440 if (!mono_error_ok (&error)) {
7441 mono_error_set_pending_exception (&error);
7445 generic_inst = NULL;
7447 if (klass->generic_class) {
7448 generic_inst = mono_class_get_context (klass);
7449 klass = klass->generic_class->container_class;
7455 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7456 if (!mono_error_ok (&error)) {
7457 mono_error_set_pending_exception (&error);
7462 if (klass == method->klass)
7465 /*This is possible if definition == FALSE.
7466 * Do it here to be really sure we don't read invalid memory.
7468 if (slot >= klass->vtable_size)
7471 mono_class_setup_vtable (klass);
7473 result = klass->vtable [slot];
7474 if (result == NULL) {
7475 /* It is an abstract method */
7476 gpointer iter = NULL;
7477 while ((result = mono_class_get_methods (klass, &iter)))
7478 if (result->slot == slot)
7485 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7486 mono_error_raise_exception (&error);
7490 ICALL_EXPORT MonoString*
7491 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7493 MonoMethod *method = m->method;
7495 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7500 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7502 iter->sig = *(MonoMethodSignature**)argsp;
7504 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7505 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7508 /* FIXME: it's not documented what start is exactly... */
7512 iter->args = argsp + sizeof (gpointer);
7514 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7516 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7519 ICALL_EXPORT MonoTypedRef
7520 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7522 guint32 i, arg_size;
7526 i = iter->sig->sentinelpos + iter->next_arg;
7528 g_assert (i < iter->sig->param_count);
7530 res.type = iter->sig->params [i];
7531 res.klass = mono_class_from_mono_type (res.type);
7532 arg_size = mono_type_stack_size (res.type, &align);
7533 #if defined(__arm__) || defined(__mips__)
7534 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7536 res.value = iter->args;
7537 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7538 /* Values are stored as 8 byte register sized objects, but 'value'
7539 * is dereferenced as a pointer in other routines.
7541 res.value = (char*)res.value + 4;
7543 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7544 if (arg_size <= sizeof (gpointer)) {
7546 int padding = arg_size - mono_type_size (res.type, &dummy);
7547 res.value = (guint8*)res.value + padding;
7550 iter->args = (char*)iter->args + arg_size;
7553 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7558 ICALL_EXPORT MonoTypedRef
7559 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7561 guint32 i, arg_size;
7565 i = iter->sig->sentinelpos + iter->next_arg;
7567 g_assert (i < iter->sig->param_count);
7569 while (i < iter->sig->param_count) {
7570 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7572 res.type = iter->sig->params [i];
7573 res.klass = mono_class_from_mono_type (res.type);
7574 /* FIXME: endianess issue... */
7575 arg_size = mono_type_stack_size (res.type, &align);
7576 #if defined(__arm__) || defined(__mips__)
7577 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7579 res.value = iter->args;
7580 iter->args = (char*)iter->args + arg_size;
7582 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7585 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7593 ICALL_EXPORT MonoType*
7594 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7598 i = iter->sig->sentinelpos + iter->next_arg;
7600 g_assert (i < iter->sig->param_count);
7602 return iter->sig->params [i];
7605 ICALL_EXPORT MonoObject*
7606 mono_TypedReference_ToObject (MonoTypedRef* tref)
7608 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7609 MonoObject** objp = (MonoObject **)tref->value;
7613 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
7616 ICALL_EXPORT MonoTypedRef
7617 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7620 MonoReflectionField *f;
7622 MonoType *ftype = NULL;
7626 memset (&res, 0, sizeof (res));
7629 g_assert (mono_array_length (fields) > 0);
7631 klass = target->vtable->klass;
7633 for (i = 0; i < mono_array_length (fields); ++i) {
7634 f = mono_array_get (fields, MonoReflectionField*, i);
7636 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7639 if (f->field->parent != klass) {
7640 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7644 p = (guint8*)target + f->field->offset;
7646 p += f->field->offset - sizeof (MonoObject);
7647 klass = mono_class_from_mono_type (f->field->type);
7648 ftype = f->field->type;
7652 res.klass = mono_class_from_mono_type (ftype);
7659 prelink_method (MonoMethod *method, MonoError *error)
7661 const char *exc_class, *exc_arg;
7663 mono_error_init (error);
7664 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7666 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7668 mono_error_set_exception_instance (error,
7669 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7672 /* create the wrapper, too? */
7676 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7680 prelink_method (method->method, &error);
7681 mono_error_raise_exception (&error);
7685 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7688 MonoClass *klass = mono_class_from_mono_type (type->type);
7690 gpointer iter = NULL;
7692 mono_class_init_checked (klass, &error);
7693 mono_error_raise_exception (&error);
7695 while ((m = mono_class_get_methods (klass, &iter))) {
7696 prelink_method (m, &error);
7697 mono_error_raise_exception (&error);
7701 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7703 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7704 gint32 const **exponents,
7705 gunichar2 const **digitLowerTable,
7706 gunichar2 const **digitUpperTable,
7707 gint64 const **tenPowersList,
7708 gint32 const **decHexDigits)
7710 *mantissas = Formatter_MantissaBitsTable;
7711 *exponents = Formatter_TensExponentTable;
7712 *digitLowerTable = Formatter_DigitLowerTable;
7713 *digitUpperTable = Formatter_DigitUpperTable;
7714 *tenPowersList = Formatter_TenPowersList;
7715 *decHexDigits = Formatter_DecHexDigits;
7719 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7720 * and avoid useless allocations.
7723 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7725 MonoReflectionType *rt;
7729 mono_error_init (error);
7730 for (i = 0; i < type->num_mods; ++i) {
7731 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7736 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7738 for (i = 0; i < type->num_mods; ++i) {
7739 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7740 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7741 return_val_if_nok (error, NULL);
7743 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7744 return_val_if_nok (error, NULL);
7746 mono_array_setref (res, count, rt);
7753 ICALL_EXPORT MonoArray*
7754 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7757 MonoType *type = param->ClassImpl->type;
7758 MonoClass *member_class = mono_object_class (param->MemberImpl);
7759 MonoMethod *method = NULL;
7762 MonoMethodSignature *sig;
7765 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7766 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7767 method = rmethod->method;
7768 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7769 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7770 if (!(method = prop->property->get))
7771 method = prop->property->set;
7774 char *type_name = mono_type_get_full_name (member_class);
7775 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7776 MonoException *ex = mono_get_exception_not_supported (msg);
7779 mono_set_pending_exception (ex);
7783 image = method->klass->image;
7784 pos = param->PositionImpl;
7785 sig = mono_method_signature (method);
7789 type = sig->params [pos];
7791 res = type_array_from_modifiers (image, type, optional, &error);
7792 mono_error_raise_exception (&error);
7797 get_property_type (MonoProperty *prop)
7799 MonoMethodSignature *sig;
7801 sig = mono_method_signature (prop->get);
7803 } else if (prop->set) {
7804 sig = mono_method_signature (prop->set);
7805 return sig->params [sig->param_count - 1];
7810 ICALL_EXPORT MonoArray*
7811 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7814 MonoType *type = get_property_type (property->property);
7815 MonoImage *image = property->klass->image;
7820 res = type_array_from_modifiers (image, type, optional, &error);
7821 mono_error_raise_exception (&error);
7826 *Construct a MonoType suited to be used to decode a constant blob object.
7828 * @type is the target type which will be constructed
7829 * @blob_type is the blob type, for example, that comes from the constant table
7830 * @real_type is the expected constructed type.
7833 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7835 type->type = blob_type;
7836 type->data.klass = NULL;
7837 if (blob_type == MONO_TYPE_CLASS)
7838 type->data.klass = mono_defaults.object_class;
7839 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7840 /* For enums, we need to use the base type */
7841 type->type = MONO_TYPE_VALUETYPE;
7842 type->data.klass = mono_class_from_mono_type (real_type);
7844 type->data.klass = mono_class_from_mono_type (real_type);
7847 ICALL_EXPORT MonoObject*
7848 property_info_get_default_value (MonoReflectionProperty *property)
7852 MonoProperty *prop = property->property;
7853 MonoType *type = get_property_type (prop);
7854 MonoDomain *domain = mono_object_domain (property);
7855 MonoTypeEnum def_type;
7856 const char *def_value;
7859 mono_class_init (prop->parent);
7861 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7862 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7866 def_value = mono_class_get_property_default_value (prop, &def_type);
7868 mono_type_from_blob_type (&blob_type, def_type, type);
7869 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7871 mono_error_set_pending_exception (&error);
7875 ICALL_EXPORT MonoBoolean
7876 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7879 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7880 MonoCustomAttrInfo *cinfo;
7883 mono_class_init_checked (attr_class, &error);
7884 mono_error_raise_exception (&error);
7886 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7887 if (!is_ok (&error)) {
7888 mono_error_set_pending_exception (&error);
7893 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7895 mono_custom_attrs_free (cinfo);
7899 ICALL_EXPORT MonoArray*
7900 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7902 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7907 mono_class_init_checked (attr_class, &error);
7908 mono_error_raise_exception (&error);
7911 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7912 if (!mono_error_ok (&error)) {
7913 mono_error_set_pending_exception (&error);
7917 if (mono_loader_get_last_error ()) {
7918 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7925 ICALL_EXPORT MonoArray*
7926 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7930 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7931 mono_error_set_pending_exception (&error);
7936 ICALL_EXPORT MonoString*
7937 ves_icall_Mono_Runtime_GetDisplayName (void)
7940 MonoString *display_name;
7942 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7943 display_name = mono_string_new (mono_domain_get (), info);
7945 return display_name;
7948 ICALL_EXPORT MonoString*
7949 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7952 MonoString *message;
7956 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7957 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7960 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7962 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7963 mono_error_raise_exception (&error);
7970 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7973 char *path_str = mono_string_to_utf8 (path);
7975 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7983 ICALL_EXPORT gpointer
7984 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
7986 return GetCurrentProcess ();
7989 ICALL_EXPORT MonoBoolean
7990 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
7992 return GetExitCodeProcess (handle, (guint32*) exitcode);
7995 ICALL_EXPORT MonoBoolean
7996 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
7998 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
7999 return CloseHandle (handle);
8001 return CloseProcess (handle);
8005 ICALL_EXPORT MonoBoolean
8006 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8008 return TerminateProcess (handle, exitcode);
8012 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8014 return WaitForInputIdle (handle, milliseconds);
8017 ICALL_EXPORT MonoBoolean
8018 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8020 return GetProcessWorkingSetSize (handle, min, max);
8023 ICALL_EXPORT MonoBoolean
8024 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8026 return SetProcessWorkingSetSize (handle, min, max);
8029 ICALL_EXPORT MonoBoolean
8030 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8032 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8036 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8038 return mono_process_current_pid ();
8042 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8044 return GetPriorityClass (handle);
8047 ICALL_EXPORT MonoBoolean
8048 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8050 return SetPriorityClass (handle, priorityClass);
8053 #ifndef DISABLE_ICALL_TABLES
8055 #define ICALL_TYPE(id,name,first)
8056 #define ICALL(id,name,func) Icall_ ## id,
8059 #include "metadata/icall-def.h"
8065 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8066 #define ICALL(id,name,func)
8068 #include "metadata/icall-def.h"
8074 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8075 #define ICALL(id,name,func)
8077 guint16 first_icall;
8080 static const IcallTypeDesc
8081 icall_type_descs [] = {
8082 #include "metadata/icall-def.h"
8086 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8089 #define ICALL_TYPE(id,name,first)
8092 #ifdef HAVE_ARRAY_ELEM_INIT
8093 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8094 #define MSGSTRFIELD1(line) str##line
8096 static const struct msgstrtn_t {
8097 #define ICALL(id,name,func)
8099 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8100 #include "metadata/icall-def.h"
8102 } icall_type_names_str = {
8103 #define ICALL_TYPE(id,name,first) (name),
8104 #include "metadata/icall-def.h"
8107 static const guint16 icall_type_names_idx [] = {
8108 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8109 #include "metadata/icall-def.h"
8112 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8114 static const struct msgstr_t {
8116 #define ICALL_TYPE(id,name,first)
8117 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8118 #include "metadata/icall-def.h"
8120 } icall_names_str = {
8121 #define ICALL(id,name,func) (name),
8122 #include "metadata/icall-def.h"
8125 static const guint16 icall_names_idx [] = {
8126 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8127 #include "metadata/icall-def.h"
8130 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8136 #define ICALL_TYPE(id,name,first) name,
8137 #define ICALL(id,name,func)
8138 static const char* const
8139 icall_type_names [] = {
8140 #include "metadata/icall-def.h"
8144 #define icall_type_name_get(id) (icall_type_names [(id)])
8148 #define ICALL_TYPE(id,name,first)
8149 #define ICALL(id,name,func) name,
8150 static const char* const
8152 #include "metadata/icall-def.h"
8155 #define icall_name_get(id) icall_names [(id)]
8157 #endif /* !HAVE_ARRAY_ELEM_INIT */
8161 #define ICALL_TYPE(id,name,first)
8162 #define ICALL(id,name,func) func,
8163 static const gconstpointer
8164 icall_functions [] = {
8165 #include "metadata/icall-def.h"
8169 #ifdef ENABLE_ICALL_SYMBOL_MAP
8172 #define ICALL_TYPE(id,name,first)
8173 #define ICALL(id,name,func) #func,
8174 static const gconstpointer
8175 icall_symbols [] = {
8176 #include "metadata/icall-def.h"
8181 #endif /* DISABLE_ICALL_TABLES */
8183 static mono_mutex_t icall_mutex;
8184 static GHashTable *icall_hash = NULL;
8185 static GHashTable *jit_icall_hash_name = NULL;
8186 static GHashTable *jit_icall_hash_addr = NULL;
8189 mono_icall_init (void)
8191 #ifndef DISABLE_ICALL_TABLES
8194 /* check that tables are sorted: disable in release */
8197 const char *prev_class = NULL;
8198 const char *prev_method;
8200 for (i = 0; i < Icall_type_num; ++i) {
8201 const IcallTypeDesc *desc;
8204 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8205 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8206 prev_class = icall_type_name_get (i);
8207 desc = &icall_type_descs [i];
8208 num_icalls = icall_desc_num_icalls (desc);
8209 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8210 for (j = 0; j < num_icalls; ++j) {
8211 const char *methodn = icall_name_get (desc->first_icall + j);
8212 if (prev_method && strcmp (prev_method, methodn) >= 0)
8213 g_print ("method %s should come before method %s\n", methodn, prev_method);
8214 prev_method = methodn;
8220 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8221 mono_os_mutex_init (&icall_mutex);
8225 mono_icall_lock (void)
8227 mono_locks_os_acquire (&icall_mutex, IcallLock);
8231 mono_icall_unlock (void)
8233 mono_locks_os_release (&icall_mutex, IcallLock);
8237 mono_icall_cleanup (void)
8239 g_hash_table_destroy (icall_hash);
8240 g_hash_table_destroy (jit_icall_hash_name);
8241 g_hash_table_destroy (jit_icall_hash_addr);
8242 mono_os_mutex_destroy (&icall_mutex);
8246 * mono_add_internal_call:
8247 * @name: method specification to surface to the managed world
8248 * @method: pointer to a C method to invoke when the method is called
8250 * This method surfaces the C function pointed by @method as a method
8251 * that has been surfaced in managed code with the method specified in
8252 * @name as an internal call.
8254 * Internal calls are surfaced to all app domains loaded and they are
8255 * accessibly by a type with the specified name.
8257 * You must provide a fully qualified type name, that is namespaces
8258 * and type name, followed by a colon and the method name, with an
8259 * optional signature to bind.
8261 * For example, the following are all valid declarations:
8263 * "MyApp.Services.ScriptService:Accelerate"
8264 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8266 * You use method parameters in cases where there might be more than
8267 * one surface method to managed code. That way you can register different
8268 * internal calls for different method overloads.
8270 * The internal calls are invoked with no marshalling. This means that .NET
8271 * types like System.String are exposed as `MonoString *` parameters. This is
8272 * different than the way that strings are surfaced in P/Invoke.
8274 * For more information on how the parameters are marshalled, see the
8275 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8278 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8279 * reference for more information on the format of method descriptions.
8282 mono_add_internal_call (const char *name, gconstpointer method)
8286 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8288 mono_icall_unlock ();
8291 #ifndef DISABLE_ICALL_TABLES
8293 #ifdef HAVE_ARRAY_ELEM_INIT
8295 compare_method_imap (const void *key, const void *elem)
8297 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8298 return strcmp (key, method_name);
8302 find_method_icall (const IcallTypeDesc *imap, const char *name)
8304 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);
8307 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8311 compare_class_imap (const void *key, const void *elem)
8313 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8314 return strcmp (key, class_name);
8317 static const IcallTypeDesc*
8318 find_class_icalls (const char *name)
8320 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);
8323 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8326 #else /* HAVE_ARRAY_ELEM_INIT */
8329 compare_method_imap (const void *key, const void *elem)
8331 const char** method_name = (const char**)elem;
8332 return strcmp (key, *method_name);
8336 find_method_icall (const IcallTypeDesc *imap, const char *name)
8338 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8341 return (gpointer)icall_functions [(nameslot - icall_names)];
8345 compare_class_imap (const void *key, const void *elem)
8347 const char** class_name = (const char**)elem;
8348 return strcmp (key, *class_name);
8351 static const IcallTypeDesc*
8352 find_class_icalls (const char *name)
8354 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8357 return &icall_type_descs [nameslot - icall_type_names];
8360 #endif /* HAVE_ARRAY_ELEM_INIT */
8362 #endif /* DISABLE_ICALL_TABLES */
8365 * we should probably export this as an helper (handle nested types).
8366 * Returns the number of chars written in buf.
8369 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8371 int nspacelen, cnamelen;
8372 nspacelen = strlen (klass->name_space);
8373 cnamelen = strlen (klass->name);
8374 if (nspacelen + cnamelen + 2 > bufsize)
8377 memcpy (buf, klass->name_space, nspacelen);
8378 buf [nspacelen ++] = '.';
8380 memcpy (buf + nspacelen, klass->name, cnamelen);
8381 buf [nspacelen + cnamelen] = 0;
8382 return nspacelen + cnamelen;
8385 #ifdef DISABLE_ICALL_TABLES
8387 no_icall_table (void)
8389 g_assert_not_reached ();
8394 mono_lookup_internal_call (MonoMethod *method)
8399 int typelen = 0, mlen, siglen;
8401 #ifndef DISABLE_ICALL_TABLES
8402 const IcallTypeDesc *imap = NULL;
8405 g_assert (method != NULL);
8407 if (method->is_inflated)
8408 method = ((MonoMethodInflated *) method)->declaring;
8410 if (method->klass->nested_in) {
8411 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8415 mname [pos++] = '/';
8418 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8424 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8429 #ifndef DISABLE_ICALL_TABLES
8430 imap = find_class_icalls (mname);
8433 mname [typelen] = ':';
8434 mname [typelen + 1] = ':';
8436 mlen = strlen (method->name);
8437 memcpy (mname + typelen + 2, method->name, mlen);
8438 sigstart = mname + typelen + 2 + mlen;
8441 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8442 siglen = strlen (tmpsig);
8443 if (typelen + mlen + siglen + 6 > sizeof (mname))
8446 memcpy (sigstart + 1, tmpsig, siglen);
8447 sigstart [siglen + 1] = ')';
8448 sigstart [siglen + 2] = 0;
8453 res = g_hash_table_lookup (icall_hash, mname);
8455 mono_icall_unlock ();;
8458 /* try without signature */
8460 res = g_hash_table_lookup (icall_hash, mname);
8462 mono_icall_unlock ();
8466 #ifdef DISABLE_ICALL_TABLES
8467 mono_icall_unlock ();
8468 /* Fail only when the result is actually used */
8469 /* mono_marshal_get_native_wrapper () depends on this */
8470 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8471 return ves_icall_System_String_ctor_RedirectToCreateString;
8473 return no_icall_table;
8475 /* it wasn't found in the static call tables */
8477 mono_icall_unlock ();
8480 res = find_method_icall (imap, sigstart - mlen);
8482 mono_icall_unlock ();
8485 /* try _with_ signature */
8487 res = find_method_icall (imap, sigstart - mlen);
8489 mono_icall_unlock ();
8493 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8494 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8495 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8496 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8497 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");
8498 g_print ("If you see other errors or faults after this message they are probably related\n");
8499 g_print ("and you need to fix your mono install first.\n");
8501 mono_icall_unlock ();
8507 #ifdef ENABLE_ICALL_SYMBOL_MAP
8509 func_cmp (gconstpointer key, gconstpointer p)
8511 return (gsize)key - (gsize)*(gsize*)p;
8516 * mono_lookup_icall_symbol:
8518 * Given the icall METHOD, returns its C symbol.
8521 mono_lookup_icall_symbol (MonoMethod *m)
8523 #ifdef DISABLE_ICALL_TABLES
8524 g_assert_not_reached ();
8527 #ifdef ENABLE_ICALL_SYMBOL_MAP
8531 static gconstpointer *functions_sorted;
8532 static const char**symbols_sorted;
8533 static gboolean inited;
8538 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8539 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8540 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8541 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8542 /* Bubble sort the two arrays */
8546 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8547 if (functions_sorted [i] > functions_sorted [i + 1]) {
8550 tmp = functions_sorted [i];
8551 functions_sorted [i] = functions_sorted [i + 1];
8552 functions_sorted [i + 1] = tmp;
8553 tmp = symbols_sorted [i];
8554 symbols_sorted [i] = symbols_sorted [i + 1];
8555 symbols_sorted [i + 1] = tmp;
8562 func = mono_lookup_internal_call (m);
8565 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8569 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8571 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8572 g_assert_not_reached ();
8579 type_from_typename (char *type_name)
8581 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8583 if (!strcmp (type_name, "int"))
8584 klass = mono_defaults.int_class;
8585 else if (!strcmp (type_name, "ptr"))
8586 klass = mono_defaults.int_class;
8587 else if (!strcmp (type_name, "void"))
8588 klass = mono_defaults.void_class;
8589 else if (!strcmp (type_name, "int32"))
8590 klass = mono_defaults.int32_class;
8591 else if (!strcmp (type_name, "uint32"))
8592 klass = mono_defaults.uint32_class;
8593 else if (!strcmp (type_name, "int8"))
8594 klass = mono_defaults.sbyte_class;
8595 else if (!strcmp (type_name, "uint8"))
8596 klass = mono_defaults.byte_class;
8597 else if (!strcmp (type_name, "int16"))
8598 klass = mono_defaults.int16_class;
8599 else if (!strcmp (type_name, "uint16"))
8600 klass = mono_defaults.uint16_class;
8601 else if (!strcmp (type_name, "long"))
8602 klass = mono_defaults.int64_class;
8603 else if (!strcmp (type_name, "ulong"))
8604 klass = mono_defaults.uint64_class;
8605 else if (!strcmp (type_name, "float"))
8606 klass = mono_defaults.single_class;
8607 else if (!strcmp (type_name, "double"))
8608 klass = mono_defaults.double_class;
8609 else if (!strcmp (type_name, "object"))
8610 klass = mono_defaults.object_class;
8611 else if (!strcmp (type_name, "obj"))
8612 klass = mono_defaults.object_class;
8613 else if (!strcmp (type_name, "string"))
8614 klass = mono_defaults.string_class;
8615 else if (!strcmp (type_name, "bool"))
8616 klass = mono_defaults.boolean_class;
8617 else if (!strcmp (type_name, "boolean"))
8618 klass = mono_defaults.boolean_class;
8620 g_error ("%s", type_name);
8621 g_assert_not_reached ();
8623 return &klass->byval_arg;
8627 * LOCKING: Take the corlib image lock.
8629 MonoMethodSignature*
8630 mono_create_icall_signature (const char *sigstr)
8635 MonoMethodSignature *res, *res2;
8636 MonoImage *corlib = mono_defaults.corlib;
8638 mono_image_lock (corlib);
8639 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8640 mono_image_unlock (corlib);
8645 parts = g_strsplit (sigstr, " ", 256);
8654 res = mono_metadata_signature_alloc (corlib, len - 1);
8659 * Under windows, the default pinvoke calling convention is STDCALL but
8662 res->call_convention = MONO_CALL_C;
8665 res->ret = type_from_typename (parts [0]);
8666 for (i = 1; i < len; ++i) {
8667 res->params [i - 1] = type_from_typename (parts [i]);
8672 mono_image_lock (corlib);
8673 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8675 res = res2; /*Value is allocated in the image pool*/
8677 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8678 mono_image_unlock (corlib);
8684 mono_find_jit_icall_by_name (const char *name)
8686 MonoJitICallInfo *info;
8687 g_assert (jit_icall_hash_name);
8690 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8691 mono_icall_unlock ();
8696 mono_find_jit_icall_by_addr (gconstpointer addr)
8698 MonoJitICallInfo *info;
8699 g_assert (jit_icall_hash_addr);
8702 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8703 mono_icall_unlock ();
8709 * mono_get_jit_icall_info:
8711 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8712 * caller should access it while holding the icall lock.
8715 mono_get_jit_icall_info (void)
8717 return jit_icall_hash_name;
8721 * mono_lookup_jit_icall_symbol:
8723 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8726 mono_lookup_jit_icall_symbol (const char *name)
8728 MonoJitICallInfo *info;
8729 const char *res = NULL;
8732 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8734 res = info->c_symbol;
8735 mono_icall_unlock ();
8740 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8743 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8744 mono_icall_unlock ();
8748 * 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
8749 * icalls without wrappers in some cases.
8752 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8754 MonoJitICallInfo *info;
8761 if (!jit_icall_hash_name) {
8762 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8763 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8766 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8767 g_warning ("jit icall already defined \"%s\"\n", name);
8768 g_assert_not_reached ();
8771 info = g_new0 (MonoJitICallInfo, 1);
8776 info->c_symbol = c_symbol;
8777 info->no_raise = no_raise;
8780 info->wrapper = func;
8782 info->wrapper = NULL;
8785 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8786 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8788 mono_icall_unlock ();
8793 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8795 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);