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/file-io.h>
49 #include <mono/metadata/console-io.h>
50 #include <mono/metadata/mono-route.h>
51 #include <mono/metadata/socket-io.h>
52 #include <mono/metadata/mono-endian.h>
53 #include <mono/metadata/tokentype.h>
54 #include <mono/metadata/domain-internals.h>
55 #include <mono/metadata/metadata-internals.h>
56 #include <mono/metadata/class-internals.h>
57 #include <mono/metadata/reflection-internals.h>
58 #include <mono/metadata/marshal.h>
59 #include <mono/metadata/gc-internals.h>
60 #include <mono/metadata/mono-gc.h>
61 #include <mono/metadata/rand.h>
62 #include <mono/metadata/sysmath.h>
63 #include <mono/metadata/string-icalls.h>
64 #include <mono/metadata/debug-helpers.h>
65 #include <mono/metadata/process.h>
66 #include <mono/metadata/environment.h>
67 #include <mono/metadata/profiler-private.h>
68 #include <mono/metadata/locales.h>
69 #include <mono/metadata/filewatcher.h>
70 #include <mono/metadata/security.h>
71 #include <mono/metadata/mono-config.h>
72 #include <mono/metadata/cil-coff.h>
73 #include <mono/metadata/number-formatter.h>
74 #include <mono/metadata/security-manager.h>
75 #include <mono/metadata/security-core-clr.h>
76 #include <mono/metadata/mono-perfcounters.h>
77 #include <mono/metadata/mono-debug.h>
78 #include <mono/metadata/mono-ptr-array.h>
79 #include <mono/metadata/verify-internals.h>
80 #include <mono/metadata/runtime.h>
81 #include <mono/metadata/file-mmap.h>
82 #include <mono/metadata/seq-points-data.h>
83 #include <mono/io-layer/io-layer.h>
84 #include <mono/utils/monobitset.h>
85 #include <mono/utils/mono-time.h>
86 #include <mono/utils/mono-proclib.h>
87 #include <mono/utils/mono-string.h>
88 #include <mono/utils/mono-error-internals.h>
89 #include <mono/utils/mono-mmap.h>
90 #include <mono/utils/mono-io-portability.h>
91 #include <mono/utils/mono-digest.h>
92 #include <mono/utils/bsearch.h>
93 #include <mono/utils/mono-os-mutex.h>
94 #include <mono/utils/mono-threads.h>
96 #if defined (HOST_WIN32)
100 #include "decimal-ms.h"
101 #include "number-ms.h"
103 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
105 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
108 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
110 static inline MonoBoolean
111 is_generic_parameter (MonoType *type)
113 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
117 mono_class_init_or_throw (MonoClass *klass)
119 if (!mono_class_init (klass))
120 mono_raise_exception (mono_class_get_exception_for_failure (klass));
123 ICALL_EXPORT MonoObject *
124 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
130 ac = (MonoClass *)arr->obj.vtable->klass;
132 esize = mono_array_element_size (ac);
133 ea = (gpointer*)((char*)arr->vector + (pos * esize));
135 if (ac->element_class->valuetype)
136 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
138 return (MonoObject *)*ea;
141 ICALL_EXPORT MonoObject *
142 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
148 MONO_CHECK_ARG_NULL (idxs, NULL);
151 ic = (MonoClass *)io->obj.vtable->klass;
153 ac = (MonoClass *)arr->obj.vtable->klass;
155 g_assert (ic->rank == 1);
156 if (io->bounds != NULL || io->max_length != ac->rank) {
157 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
161 ind = (gint32 *)io->vector;
163 if (arr->bounds == NULL) {
164 if (*ind < 0 || *ind >= arr->max_length) {
165 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
169 return ves_icall_System_Array_GetValueImpl (arr, *ind);
172 for (i = 0; i < ac->rank; i++) {
173 if ((ind [i] < arr->bounds [i].lower_bound) ||
174 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
175 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
180 pos = ind [0] - arr->bounds [0].lower_bound;
181 for (i = 1; i < ac->rank; i++)
182 pos = pos * arr->bounds [i].length + ind [i] -
183 arr->bounds [i].lower_bound;
185 return ves_icall_System_Array_GetValueImpl (arr, pos);
189 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
191 MonoClass *ac, *vc, *ec;
201 vc = value->vtable->klass;
205 ac = arr->obj.vtable->klass;
206 ec = ac->element_class;
208 esize = mono_array_element_size (ac);
209 ea = (gpointer*)((char*)arr->vector + (pos * esize));
210 va = (gpointer*)((char*)value + sizeof (MonoObject));
212 if (mono_class_is_nullable (ec)) {
213 mono_nullable_init ((guint8*)ea, value, ec);
218 mono_gc_bzero_atomic (ea, esize);
222 #define NO_WIDENING_CONVERSION G_STMT_START{\
223 mono_set_pending_exception (mono_get_exception_argument ( \
224 "value", "not a widening conversion")); \
228 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
229 if (esize < vsize + (extra)) { \
230 mono_set_pending_exception (mono_get_exception_argument ( \
231 "value", "not a widening conversion")); \
236 #define INVALID_CAST G_STMT_START{ \
237 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
238 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
242 /* Check element (destination) type. */
243 switch (ec->byval_arg.type) {
244 case MONO_TYPE_STRING:
245 switch (vc->byval_arg.type) {
246 case MONO_TYPE_STRING:
252 case MONO_TYPE_BOOLEAN:
253 switch (vc->byval_arg.type) {
254 case MONO_TYPE_BOOLEAN:
267 NO_WIDENING_CONVERSION;
276 if (!ec->valuetype) {
277 if (!mono_object_isinst (value, ec))
279 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
283 if (mono_object_isinst (value, ec)) {
284 if (ec->has_references)
285 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
287 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
294 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
296 et = ec->byval_arg.type;
297 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
298 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
300 vt = vc->byval_arg.type;
301 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
302 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
304 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
310 case MONO_TYPE_CHAR: \
311 CHECK_WIDENING_CONVERSION(0); \
312 *(etype *) ea = (etype) u64; \
314 /* You can't assign a signed value to an unsigned array. */ \
319 /* You can't assign a floating point number to an integer array. */ \
322 NO_WIDENING_CONVERSION; \
326 #define ASSIGN_SIGNED(etype) G_STMT_START{\
332 CHECK_WIDENING_CONVERSION(0); \
333 *(etype *) ea = (etype) i64; \
335 /* You can assign an unsigned value to a signed array if the array's */ \
336 /* element size is larger than the value size. */ \
341 case MONO_TYPE_CHAR: \
342 CHECK_WIDENING_CONVERSION(1); \
343 *(etype *) ea = (etype) u64; \
345 /* You can't assign a floating point number to an integer array. */ \
348 NO_WIDENING_CONVERSION; \
352 #define ASSIGN_REAL(etype) G_STMT_START{\
356 CHECK_WIDENING_CONVERSION(0); \
357 *(etype *) ea = (etype) r64; \
359 /* All integer values fit into a floating point array, so we don't */ \
360 /* need to CHECK_WIDENING_CONVERSION here. */ \
365 *(etype *) ea = (etype) i64; \
371 case MONO_TYPE_CHAR: \
372 *(etype *) ea = (etype) u64; \
379 u64 = *(guint8 *) va;
382 u64 = *(guint16 *) va;
385 u64 = *(guint32 *) va;
388 u64 = *(guint64 *) va;
394 i64 = *(gint16 *) va;
397 i64 = *(gint32 *) va;
400 i64 = *(gint64 *) va;
403 r64 = *(gfloat *) va;
406 r64 = *(gdouble *) va;
409 u64 = *(guint16 *) va;
411 case MONO_TYPE_BOOLEAN:
412 /* Boolean is only compatible with itself. */
425 NO_WIDENING_CONVERSION;
432 /* If we can't do a direct copy, let's try a widening conversion. */
435 ASSIGN_UNSIGNED (guint16);
437 ASSIGN_UNSIGNED (guint8);
439 ASSIGN_UNSIGNED (guint16);
441 ASSIGN_UNSIGNED (guint32);
443 ASSIGN_UNSIGNED (guint64);
445 ASSIGN_SIGNED (gint8);
447 ASSIGN_SIGNED (gint16);
449 ASSIGN_SIGNED (gint32);
451 ASSIGN_SIGNED (gint64);
453 ASSIGN_REAL (gfloat);
455 ASSIGN_REAL (gdouble);
459 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
463 #undef NO_WIDENING_CONVERSION
464 #undef CHECK_WIDENING_CONVERSION
465 #undef ASSIGN_UNSIGNED
471 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
477 MONO_CHECK_ARG_NULL (idxs,);
479 ic = idxs->obj.vtable->klass;
480 ac = arr->obj.vtable->klass;
482 g_assert (ic->rank == 1);
483 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
484 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
488 ind = (gint32 *)idxs->vector;
490 if (arr->bounds == NULL) {
491 if (*ind < 0 || *ind >= arr->max_length) {
492 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
496 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
500 for (i = 0; i < ac->rank; i++)
501 if ((ind [i] < arr->bounds [i].lower_bound) ||
502 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
503 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
507 pos = ind [0] - arr->bounds [0].lower_bound;
508 for (i = 1; i < ac->rank; i++)
509 pos = pos * arr->bounds [i].length + ind [i] -
510 arr->bounds [i].lower_bound;
512 ves_icall_System_Array_SetValueImpl (arr, value, pos);
515 ICALL_EXPORT MonoArray *
516 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
518 MonoClass *aklass, *klass;
521 gboolean bounded = FALSE;
523 MONO_CHECK_ARG_NULL (type, NULL);
524 MONO_CHECK_ARG_NULL (lengths, NULL);
526 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
528 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
530 for (i = 0; i < mono_array_length (lengths); i++) {
531 if (mono_array_get (lengths, gint32, i) < 0) {
532 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
537 klass = mono_class_from_mono_type (type->type);
538 mono_class_init_or_throw (klass);
540 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
541 /* vectors are not the same as one dimensional arrays with no-zero bounds */
546 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
548 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
549 for (i = 0; i < aklass->rank; ++i) {
550 sizes [i] = mono_array_get (lengths, guint32, i);
552 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
554 sizes [i + aklass->rank] = 0;
557 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
562 ICALL_EXPORT MonoArray *
563 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
565 MonoClass *aklass, *klass;
568 gboolean bounded = FALSE;
570 MONO_CHECK_ARG_NULL (type, NULL);
571 MONO_CHECK_ARG_NULL (lengths, NULL);
573 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
575 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
577 for (i = 0; i < mono_array_length (lengths); i++) {
578 if ((mono_array_get (lengths, gint64, i) < 0) ||
579 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
580 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
585 klass = mono_class_from_mono_type (type->type);
586 mono_class_init_or_throw (klass);
588 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
589 /* vectors are not the same as one dimensional arrays with no-zero bounds */
594 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
596 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
597 for (i = 0; i < aklass->rank; ++i) {
598 sizes [i] = mono_array_get (lengths, guint64, i);
600 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
602 sizes [i + aklass->rank] = 0;
605 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
611 ves_icall_System_Array_GetRank (MonoObject *arr)
613 return arr->vtable->klass->rank;
617 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
619 gint32 rank = arr->obj.vtable->klass->rank;
622 if ((dimension < 0) || (dimension >= rank)) {
623 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
627 if (arr->bounds == NULL)
628 length = arr->max_length;
630 length = arr->bounds [dimension].length;
632 #ifdef MONO_BIG_ARRAYS
633 if (length > G_MAXINT32) {
634 mono_set_pending_exception (mono_get_exception_overflow ());
642 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
644 gint32 rank = arr->obj.vtable->klass->rank;
646 if ((dimension < 0) || (dimension >= rank)) {
647 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
651 if (arr->bounds == NULL)
652 return arr->max_length;
654 return arr->bounds [dimension].length;
658 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
660 gint32 rank = arr->obj.vtable->klass->rank;
662 if ((dimension < 0) || (dimension >= rank)) {
663 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
667 if (arr->bounds == NULL)
670 return arr->bounds [dimension].lower_bound;
674 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
676 int sz = mono_array_element_size (mono_object_class (arr));
677 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
680 ICALL_EXPORT gboolean
681 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
686 MonoVTable *src_vtable;
687 MonoVTable *dest_vtable;
688 MonoClass *src_class;
689 MonoClass *dest_class;
691 src_vtable = source->obj.vtable;
692 dest_vtable = dest->obj.vtable;
694 if (src_vtable->rank != dest_vtable->rank)
697 if (source->bounds || dest->bounds)
700 /* there's no integer overflow since mono_array_length returns an unsigned integer */
701 if ((dest_idx + length > mono_array_length_fast (dest)) ||
702 (source_idx + length > mono_array_length_fast (source)))
705 src_class = src_vtable->klass->element_class;
706 dest_class = dest_vtable->klass->element_class;
709 * Handle common cases.
712 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
713 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
715 if (src_class == mono_defaults.object_class && dest_class->valuetype)
718 /* Check if we're copying a char[] <==> (u)short[] */
719 if (src_class != dest_class) {
720 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
723 /* 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. */
724 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
728 if (dest_class->valuetype) {
729 element_size = mono_array_element_size (source->obj.vtable->klass);
730 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
731 if (dest_class->has_references) {
732 mono_value_copy_array (dest, dest_idx, source_addr, length);
734 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
735 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
738 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
745 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
751 ac = (MonoClass *)arr->obj.vtable->klass;
753 esize = mono_array_element_size (ac);
754 ea = (gpointer*)((char*)arr->vector + (pos * esize));
756 mono_gc_memmove_atomic (value, ea, esize);
760 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
766 ac = (MonoClass *)arr->obj.vtable->klass;
767 ec = ac->element_class;
769 esize = mono_array_element_size (ac);
770 ea = (gpointer*)((char*)arr->vector + (pos * esize));
772 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
773 g_assert (esize == sizeof (gpointer));
774 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
776 g_assert (ec->inited);
777 g_assert (esize == mono_class_value_size (ec, NULL));
778 if (ec->has_references)
779 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
781 mono_gc_memmove_atomic (ea, value, esize);
786 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
788 MonoClass *klass = array->obj.vtable->klass;
789 guint32 size = mono_array_element_size (klass);
790 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
792 const char *field_data;
794 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
795 MonoException *exc = mono_get_exception_argument("array",
796 "Cannot initialize array of non-primitive type.");
797 mono_set_pending_exception (exc);
801 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
802 MonoException *exc = mono_get_exception_argument("field_handle",
803 "Field doesn't have an RVA");
804 mono_set_pending_exception (exc);
808 size *= array->max_length;
809 field_data = mono_field_get_data (field_handle);
811 if (size > mono_type_size (field_handle->type, &align)) {
812 MonoException *exc = mono_get_exception_argument("field_handle",
813 "Field not large enough to fill array");
814 mono_set_pending_exception (exc);
818 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
820 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
821 guint ## n *src = (guint ## n *) field_data; \
822 guint ## n *end = (guint ## n *)((char*)src + size); \
824 for (; src < end; data++, src++) { \
825 *data = read ## n (src); \
829 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
831 switch (type->type) {
848 memcpy (mono_array_addr (array, char, 0), field_data, size);
852 memcpy (mono_array_addr (array, char, 0), field_data, size);
857 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
859 return offsetof (MonoString, chars);
862 ICALL_EXPORT MonoObject *
863 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
865 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
868 return mono_object_clone (obj);
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
877 MONO_CHECK_ARG_NULL (handle,);
879 klass = mono_class_from_mono_type (handle);
880 MONO_CHECK_ARG (handle, klass,);
882 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
884 /* This will call the type constructor */
885 mono_runtime_class_init (vtable);
889 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
893 mono_image_check_for_module_cctor (image);
894 if (image->has_module_cctor) {
895 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
896 mono_error_raise_exception (&error);
897 /*It's fine to raise the exception here*/
898 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
902 ICALL_EXPORT MonoBoolean
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
908 /* later make this configurable and per-arch */
909 int min_size = 4096 * 4 * sizeof (void*);
910 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
911 /* if we have no info we are optimistic and assume there is enough room */
915 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
919 current = (guint8 *)&stack_addr;
920 if (current > stack_addr) {
921 if ((current - stack_addr) < min_size)
924 if (current - (stack_addr - stack_size) < min_size)
930 ICALL_EXPORT MonoObject *
931 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
933 return mono_object_clone (this_obj);
937 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
940 MonoObject **values = NULL;
943 gint32 result = (int)(gsize)mono_defaults.int32_class;
944 MonoClassField* field;
947 klass = mono_object_class (this_obj);
949 if (mono_class_num_fields (klass) == 0)
953 * Compute the starting value of the hashcode for fields of primitive
954 * types, and return the remaining fields in an array to the managed side.
955 * This way, we can avoid costly reflection operations in managed code.
958 while ((field = mono_class_get_fields (klass, &iter))) {
959 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
961 if (mono_field_is_deleted (field))
963 /* FIXME: Add more types */
964 switch (field->type->type) {
966 result ^= *(gint32*)((guint8*)this_obj + field->offset);
968 case MONO_TYPE_STRING: {
970 s = *(MonoString**)((guint8*)this_obj + field->offset);
972 result ^= mono_string_hash (s);
977 values = g_newa (MonoObject*, mono_class_num_fields (klass));
978 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
979 values [count++] = o;
985 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
986 for (i = 0; i < count; ++i)
987 mono_array_setref (*fields, i, values [i]);
994 ICALL_EXPORT MonoBoolean
995 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
998 MonoObject **values = NULL;
1000 MonoClassField* field;
1004 MONO_CHECK_ARG_NULL (that, FALSE);
1006 if (this_obj->vtable != that->vtable)
1009 klass = mono_object_class (this_obj);
1011 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1012 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1015 * Do the comparison for fields of primitive type and return a result if
1016 * possible. Otherwise, return the remaining fields in an array to the
1017 * managed side. This way, we can avoid costly reflection operations in
1022 while ((field = mono_class_get_fields (klass, &iter))) {
1023 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1025 if (mono_field_is_deleted (field))
1027 /* FIXME: Add more types */
1028 switch (field->type->type) {
1031 case MONO_TYPE_BOOLEAN:
1032 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1037 case MONO_TYPE_CHAR:
1038 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1043 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1048 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1052 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1056 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1061 case MONO_TYPE_STRING: {
1062 MonoString *s1, *s2;
1063 guint32 s1len, s2len;
1064 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1065 s2 = *(MonoString**)((guint8*)that + field->offset);
1068 if ((s1 == NULL) || (s2 == NULL))
1070 s1len = mono_string_length (s1);
1071 s2len = mono_string_length (s2);
1075 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1081 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1082 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1083 values [count++] = o;
1084 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1085 values [count++] = o;
1088 if (klass->enumtype)
1089 /* enums only have one non-static field */
1095 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1096 for (i = 0; i < count; ++i)
1097 mono_array_setref_fast (*fields, i, values [i]);
1104 ICALL_EXPORT MonoReflectionType *
1105 ves_icall_System_Object_GetType (MonoObject *obj)
1107 #ifndef DISABLE_REMOTING
1108 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1109 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1112 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1116 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1118 mtype->type = &obj->vtable->klass->byval_arg;
1119 g_assert (mtype->type->type);
1123 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1125 MONO_CHECK_ARG_NULL (obj, 0);
1127 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1131 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1132 MonoReflectionMethod *method,
1133 MonoArray *opt_param_types)
1135 MONO_CHECK_ARG_NULL (method, 0);
1137 return mono_image_create_method_token (
1138 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1142 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1144 mono_image_create_pefile (mb, file);
1148 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1150 mono_image_build_metadata (mb);
1154 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1156 mono_image_register_token (mb->dynamic_image, token, obj);
1159 ICALL_EXPORT MonoObject*
1160 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1164 mono_loader_lock ();
1165 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1166 mono_loader_unlock ();
1172 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1174 MonoMethod **dest = (MonoMethod **)data;
1176 /* skip unmanaged frames */
1192 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1194 MonoMethod **dest = (MonoMethod **)data;
1196 /* skip unmanaged frames */
1201 if (!strcmp (m->klass->name_space, "System.Reflection"))
1210 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1212 MonoMethod **dest = (MonoMethod **)data;
1214 /* skip unmanaged frames */
1218 if (m->wrapper_type != MONO_WRAPPER_NONE)
1221 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1235 static MonoReflectionType *
1236 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1238 MonoMethod *m, *dest;
1240 MonoType *type = NULL;
1241 MonoAssembly *assembly = NULL;
1242 gboolean type_resolve = FALSE;
1245 * We must compute the calling assembly as type loading must happen under a metadata context.
1246 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1247 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1249 m = mono_method_get_last_managed ();
1252 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1257 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1258 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1259 * to crash. This only seems to happen in some strange remoting
1260 * scenarios and I was unable to figure out what's happening there.
1261 * Dec 10, 2005 - Martin.
1265 assembly = dest->klass->image->assembly;
1266 type_resolve = TRUE;
1268 g_warning (G_STRLOC);
1271 if (info->assembly.name)
1272 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1276 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1277 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1280 if (!info->assembly.name && !type) /* try mscorlib */
1281 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1283 if (assembly && !type && type_resolve) {
1284 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1285 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1291 return mono_type_get_object (mono_domain_get (), type);
1295 MonoReflectionType *
1296 mono_type_get (const char *str)
1298 char *copy = g_strdup (str);
1299 MonoTypeNameParse info;
1300 MonoReflectionType *type;
1303 parsedOk = mono_reflection_parse_type(copy, &info);
1305 mono_reflection_free_type_info (&info);
1310 type = type_from_parsed_name (&info, FALSE);
1312 mono_reflection_free_type_info (&info);
1319 ICALL_EXPORT MonoReflectionType*
1320 ves_icall_type_from_name (MonoString *name,
1321 MonoBoolean throwOnError,
1322 MonoBoolean ignoreCase)
1324 char *str = mono_string_to_utf8 (name);
1325 MonoTypeNameParse info;
1326 MonoReflectionType *type;
1329 parsedOk = mono_reflection_parse_type (str, &info);
1331 /* mono_reflection_parse_type() mangles the string */
1333 mono_reflection_free_type_info (&info);
1336 mono_set_pending_exception(mono_get_exception_argument("typeName", "failed parse"));
1341 type = type_from_parsed_name (&info, ignoreCase);
1343 mono_reflection_free_type_info (&info);
1347 MonoException *e = NULL;
1350 e = mono_get_exception_type_load (name, NULL);
1352 mono_loader_clear_error ();
1354 mono_set_pending_exception (e);
1363 ICALL_EXPORT MonoReflectionType*
1364 ves_icall_type_from_handle (MonoType *handle)
1366 MonoDomain *domain = mono_domain_get ();
1368 return mono_type_get_object (domain, handle);
1371 /* System.TypeCode */
1390 TYPECODE_STRING = 18
1393 ICALL_EXPORT guint32
1394 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1396 int t = type->type->type;
1398 if (type->type->byref)
1399 return TYPECODE_OBJECT;
1403 case MONO_TYPE_VOID:
1404 return TYPECODE_OBJECT;
1405 case MONO_TYPE_BOOLEAN:
1406 return TYPECODE_BOOLEAN;
1408 return TYPECODE_BYTE;
1410 return TYPECODE_SBYTE;
1412 return TYPECODE_UINT16;
1414 return TYPECODE_INT16;
1415 case MONO_TYPE_CHAR:
1416 return TYPECODE_CHAR;
1420 return TYPECODE_OBJECT;
1422 return TYPECODE_UINT32;
1424 return TYPECODE_INT32;
1426 return TYPECODE_UINT64;
1428 return TYPECODE_INT64;
1430 return TYPECODE_SINGLE;
1432 return TYPECODE_DOUBLE;
1433 case MONO_TYPE_VALUETYPE: {
1434 MonoClass *klass = type->type->data.klass;
1436 if (klass->enumtype) {
1437 t = mono_class_enum_basetype (klass)->type;
1439 } else if (mono_is_corlib_image (klass->image)) {
1440 if (strcmp (klass->name_space, "System") == 0) {
1441 if (strcmp (klass->name, "Decimal") == 0)
1442 return TYPECODE_DECIMAL;
1443 else if (strcmp (klass->name, "DateTime") == 0)
1444 return TYPECODE_DATETIME;
1447 return TYPECODE_OBJECT;
1449 case MONO_TYPE_STRING:
1450 return TYPECODE_STRING;
1451 case MONO_TYPE_SZARRAY:
1452 case MONO_TYPE_ARRAY:
1453 case MONO_TYPE_OBJECT:
1455 case MONO_TYPE_MVAR:
1456 case MONO_TYPE_TYPEDBYREF:
1457 return TYPECODE_OBJECT;
1458 case MONO_TYPE_CLASS:
1460 MonoClass *klass = type->type->data.klass;
1461 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1462 if (strcmp (klass->name, "DBNull") == 0)
1463 return TYPECODE_DBNULL;
1466 return TYPECODE_OBJECT;
1467 case MONO_TYPE_GENERICINST:
1468 return TYPECODE_OBJECT;
1470 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1476 mono_type_is_primitive (MonoType *type)
1478 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1479 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1483 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1485 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1486 return mono_class_enum_basetype (type->data.klass);
1487 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1488 return mono_class_enum_basetype (type->data.generic_class->container_class);
1492 ICALL_EXPORT guint32
1493 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1498 g_assert (type != NULL);
1500 klass = mono_class_from_mono_type (type->type);
1501 klassc = mono_class_from_mono_type (c->type);
1503 if (type->type->byref ^ c->type->byref)
1506 if (type->type->byref) {
1507 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1508 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1510 klass = mono_class_from_mono_type (t);
1511 klassc = mono_class_from_mono_type (ot);
1513 if (mono_type_is_primitive (t)) {
1514 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1515 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1516 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1517 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1518 return t->type == ot->type;
1520 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1523 if (klass->valuetype)
1524 return klass == klassc;
1525 return klass->valuetype == klassc->valuetype;
1528 return mono_class_is_assignable_from (klass, klassc);
1531 ICALL_EXPORT guint32
1532 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1534 MonoClass *klass = mono_class_from_mono_type (type->type);
1535 mono_class_init_or_throw (klass);
1536 return mono_object_isinst (obj, klass) != NULL;
1539 ICALL_EXPORT guint32
1540 ves_icall_get_attributes (MonoReflectionType *type)
1542 MonoClass *klass = mono_class_from_mono_type (type->type);
1543 return klass->flags;
1546 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1547 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1549 MonoClass *klass = field->field->parent;
1550 MonoMarshalType *info;
1554 if (klass->generic_container ||
1555 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1558 ftype = mono_field_get_type (field->field);
1559 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1562 info = mono_marshal_load_type_info (klass);
1564 for (i = 0; i < info->num_fields; ++i) {
1565 if (info->fields [i].field == field->field) {
1566 if (!info->fields [i].mspec)
1569 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1576 ICALL_EXPORT MonoReflectionField*
1577 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1579 gboolean found = FALSE;
1586 klass = handle->parent;
1588 klass = mono_class_from_mono_type (type);
1590 /* Check that the field belongs to the class */
1591 for (k = klass; k; k = k->parent) {
1592 if (k == handle->parent) {
1599 /* The managed code will throw the exception */
1603 return mono_field_get_object (mono_domain_get (), klass, handle);
1606 ICALL_EXPORT MonoArray*
1607 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1610 MonoType *type = mono_field_get_type_checked (field->field, &error);
1611 mono_error_raise_exception (&error);
1613 return type_array_from_modifiers (field->field->parent->image, type, optional);
1617 vell_icall_get_method_attributes (MonoMethod *method)
1619 return method->flags;
1623 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1626 MonoDomain *domain = mono_domain_get ();
1627 MonoMethodSignature* sig;
1629 sig = mono_method_signature_checked (method, &error);
1630 if (!mono_error_ok (&error))
1631 mono_error_raise_exception (&error);
1634 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1635 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1636 info->attrs = method->flags;
1637 info->implattrs = method->iflags;
1638 if (sig->call_convention == MONO_CALL_DEFAULT)
1639 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1641 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1646 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1649 ICALL_EXPORT MonoArray*
1650 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1652 MonoDomain *domain = mono_domain_get ();
1654 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1657 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1658 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1660 MonoDomain *domain = mono_domain_get ();
1661 MonoReflectionMarshalAsAttribute* res = NULL;
1662 MonoMarshalSpec **mspecs;
1665 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1666 mono_method_get_marshal_info (method, mspecs);
1669 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1671 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1673 mono_metadata_free_marshal_spec (mspecs [i]);
1680 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1682 MonoClass *parent = field->field->parent;
1683 if (!parent->size_inited)
1684 mono_class_init (parent);
1685 mono_class_setup_fields_locking (parent);
1687 return field->field->offset - sizeof (MonoObject);
1690 ICALL_EXPORT MonoReflectionType*
1691 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1695 parent = declaring? field->field->parent: field->klass;
1697 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1700 ICALL_EXPORT MonoObject *
1701 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1703 MonoClass *fklass = field->klass;
1704 MonoClassField *cf = field->field;
1705 MonoDomain *domain = mono_object_domain (field);
1707 if (fklass->image->assembly->ref_only) {
1708 mono_set_pending_exception (mono_get_exception_invalid_operation (
1709 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1713 if (mono_security_core_clr_enabled ())
1714 mono_security_core_clr_ensure_reflection_access_field (cf);
1716 return mono_field_get_value_object (domain, cf, obj);
1720 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1723 MonoClassField *cf = field->field;
1727 if (field->klass->image->assembly->ref_only) {
1728 mono_set_pending_exception (mono_get_exception_invalid_operation (
1729 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1733 if (mono_security_core_clr_enabled ())
1734 mono_security_core_clr_ensure_reflection_access_field (cf);
1736 type = mono_field_get_type_checked (cf, &error);
1737 if (!mono_error_ok (&error))
1738 mono_error_raise_exception (&error);
1740 v = (gchar *) value;
1742 switch (type->type) {
1745 case MONO_TYPE_BOOLEAN:
1748 case MONO_TYPE_CHAR:
1757 case MONO_TYPE_VALUETYPE:
1760 v += sizeof (MonoObject);
1762 case MONO_TYPE_STRING:
1763 case MONO_TYPE_OBJECT:
1764 case MONO_TYPE_CLASS:
1765 case MONO_TYPE_ARRAY:
1766 case MONO_TYPE_SZARRAY:
1769 case MONO_TYPE_GENERICINST: {
1770 MonoGenericClass *gclass = type->data.generic_class;
1771 g_assert (!gclass->context.class_inst->is_open);
1773 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1774 MonoClass *nklass = mono_class_from_mono_type (type);
1775 MonoObject *nullable;
1778 * Convert the boxed vtype into a Nullable structure.
1779 * This is complicated by the fact that Nullables have
1780 * a variable structure.
1782 nullable = mono_object_new (mono_domain_get (), nklass);
1784 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1786 v = (gchar *)mono_object_unbox (nullable);
1789 if (gclass->container_class->valuetype && (v != NULL))
1790 v += sizeof (MonoObject);
1794 g_error ("type 0x%x not handled in "
1795 "ves_icall_FieldInfo_SetValueInternal", type->type);
1800 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1801 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1802 if (!vtable->initialized)
1803 mono_runtime_class_init (vtable);
1804 mono_field_static_set_value (vtable, cf, v);
1806 mono_field_set_value (obj, cf, v);
1811 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1820 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1821 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1825 if (MONO_TYPE_IS_REFERENCE (f->type))
1826 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1828 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1831 ICALL_EXPORT MonoObject *
1832 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1834 MonoObject *o = NULL;
1835 MonoClassField *field = rfield->field;
1837 MonoDomain *domain = mono_object_domain (rfield);
1839 MonoTypeEnum def_type;
1840 const char *def_value;
1844 mono_class_init (field->parent);
1846 t = mono_field_get_type_checked (field, &error);
1847 if (!mono_error_ok (&error))
1848 mono_error_raise_exception (&error);
1850 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1851 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1855 if (image_is_dynamic (field->parent->image)) {
1856 MonoClass *klass = field->parent;
1857 int fidx = field - klass->fields;
1859 g_assert (fidx >= 0 && fidx < klass->field.count);
1860 g_assert (klass->ext);
1861 g_assert (klass->ext->field_def_values);
1862 def_type = klass->ext->field_def_values [fidx].def_type;
1863 def_value = klass->ext->field_def_values [fidx].data;
1864 if (def_type == MONO_TYPE_END) {
1865 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1869 def_value = mono_class_get_field_default_value (field, &def_type);
1870 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1872 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1877 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1881 case MONO_TYPE_BOOLEAN:
1884 case MONO_TYPE_CHAR:
1892 case MONO_TYPE_R8: {
1895 /* boxed value type */
1896 t = g_new0 (MonoType, 1);
1898 klass = mono_class_from_mono_type (t);
1900 o = mono_object_new (domain, klass);
1901 v = ((gchar *) o) + sizeof (MonoObject);
1902 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1905 case MONO_TYPE_STRING:
1906 case MONO_TYPE_CLASS:
1907 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1910 g_assert_not_reached ();
1916 ICALL_EXPORT MonoReflectionType*
1917 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1920 MonoClassField *field = ref_field->field;
1921 MonoType *type = mono_field_get_type_checked (field, &error);
1922 if (!mono_error_ok (&error))
1923 mono_error_raise_exception (&error);
1924 return mono_type_get_object (mono_object_domain (ref_field), type);
1927 ICALL_EXPORT MonoReflectionType*
1928 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1930 MonoMethod *method = rmethod->method.method;
1932 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1935 /* From MonoProperty.cs */
1937 PInfo_Attributes = 1,
1938 PInfo_GetMethod = 1 << 1,
1939 PInfo_SetMethod = 1 << 2,
1940 PInfo_ReflectedType = 1 << 3,
1941 PInfo_DeclaringType = 1 << 4,
1946 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1948 MonoDomain *domain = mono_object_domain (property);
1949 const MonoProperty *pproperty = property->property;
1951 if ((req_info & PInfo_ReflectedType) != 0)
1952 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1953 if ((req_info & PInfo_DeclaringType) != 0)
1954 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &pproperty->parent->byval_arg));
1956 if ((req_info & PInfo_Name) != 0)
1957 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
1959 if ((req_info & PInfo_Attributes) != 0)
1960 info->attrs = pproperty->attrs;
1962 if ((req_info & PInfo_GetMethod) != 0)
1963 MONO_STRUCT_SETREF (info, get, pproperty->get &&
1964 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->get->klass == property->klass) ?
1965 mono_method_get_object (domain, pproperty->get, property->klass): NULL);
1966 if ((req_info & PInfo_SetMethod) != 0)
1967 MONO_STRUCT_SETREF (info, set, pproperty->set &&
1968 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->set->klass == property->klass) ?
1969 mono_method_get_object (domain, pproperty->set, property->klass): NULL);
1971 * There may be other methods defined for properties, though, it seems they are not exposed
1972 * in the reflection API
1977 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1979 MonoDomain *domain = mono_object_domain (event);
1981 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1982 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1984 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1985 info->attrs = event->event->attrs;
1986 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
1987 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
1988 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
1990 #ifndef MONO_SMALL_CONFIG
1991 if (event->event->other) {
1993 while (event->event->other [n])
1995 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
1997 for (i = 0; i < n; i++)
1998 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2004 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2009 mono_class_setup_interfaces (klass, error);
2010 if (!mono_error_ok (error))
2013 for (i = 0; i < klass->interface_count; i++) {
2014 ic = klass->interfaces [i];
2015 g_hash_table_insert (ifaces, ic, ic);
2017 collect_interfaces (ic, ifaces, error);
2018 if (!mono_error_ok (error))
2024 MonoArray *iface_array;
2025 MonoGenericContext *context;
2029 } FillIfaceArrayData;
2032 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2034 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2035 MonoClass *ic = (MonoClass *)key;
2036 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2038 if (!mono_error_ok (data->error))
2041 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2042 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2043 if (!mono_error_ok (data->error))
2047 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2050 mono_metadata_free_type (inflated);
2054 get_interfaces_hash (gconstpointer v1)
2056 MonoClass *k = (MonoClass*)v1;
2058 return k->type_token;
2061 ICALL_EXPORT MonoArray*
2062 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2065 MonoClass *klass = mono_class_from_mono_type (type->type);
2067 FillIfaceArrayData data = { 0 };
2070 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2072 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2073 data.context = mono_class_get_context (klass);
2074 klass = klass->generic_class->container_class;
2077 for (parent = klass; parent; parent = parent->parent) {
2078 mono_class_setup_interfaces (parent, &error);
2079 if (!mono_error_ok (&error))
2081 collect_interfaces (parent, iface_hash, &error);
2082 if (!mono_error_ok (&error))
2086 data.error = &error;
2087 data.domain = mono_object_domain (type);
2089 len = g_hash_table_size (iface_hash);
2091 g_hash_table_destroy (iface_hash);
2092 if (!data.domain->empty_types)
2093 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2094 return data.domain->empty_types;
2097 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2098 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2099 if (!mono_error_ok (&error))
2102 g_hash_table_destroy (iface_hash);
2103 return data.iface_array;
2106 g_hash_table_destroy (iface_hash);
2107 mono_error_raise_exception (&error);
2112 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2114 gboolean variance_used;
2115 MonoClass *klass = mono_class_from_mono_type (type->type);
2116 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2117 MonoReflectionMethod *member;
2120 int i = 0, len, ioffset;
2123 mono_class_init_or_throw (klass);
2124 mono_class_init_or_throw (iclass);
2126 mono_class_setup_vtable (klass);
2128 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2132 len = mono_class_num_methods (iclass);
2133 domain = mono_object_domain (type);
2134 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2135 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2137 while ((method = mono_class_get_methods (iclass, &iter))) {
2138 member = mono_method_get_object (domain, method, iclass);
2139 mono_array_setref (*methods, i, member);
2140 member = mono_method_get_object (domain, klass->vtable [i + ioffset], klass);
2141 mono_array_setref (*targets, i, member);
2148 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2150 MonoClass *klass = mono_class_from_mono_type (type->type);
2151 mono_class_init_or_throw (klass);
2153 if (image_is_dynamic (klass->image)) {
2154 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2155 *packing = tb->packing_size;
2156 *size = tb->class_size;
2158 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2162 ICALL_EXPORT MonoReflectionType*
2163 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2167 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2168 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2170 klass = mono_class_from_mono_type (type->type);
2171 mono_class_init_or_throw (klass);
2173 // GetElementType should only return a type for:
2174 // Array Pointer PassedByRef
2175 if (type->type->byref)
2176 return mono_type_get_object (mono_object_domain (type), &klass->byval_arg);
2177 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2178 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2179 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2180 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2185 ICALL_EXPORT MonoReflectionType*
2186 ves_icall_get_type_parent (MonoReflectionType *type)
2188 if (type->type->byref)
2191 MonoClass *klass = mono_class_from_mono_type (type->type);
2192 return klass->parent ? mono_type_get_object (mono_object_domain (type), &klass->parent->byval_arg): NULL;
2195 ICALL_EXPORT MonoBoolean
2196 ves_icall_type_ispointer (MonoReflectionType *type)
2198 return type->type->type == MONO_TYPE_PTR;
2201 ICALL_EXPORT MonoBoolean
2202 ves_icall_type_isprimitive (MonoReflectionType *type)
2204 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)));
2207 ICALL_EXPORT MonoBoolean
2208 ves_icall_type_isbyref (MonoReflectionType *type)
2210 return type->type->byref;
2213 ICALL_EXPORT MonoBoolean
2214 ves_icall_type_iscomobject (MonoReflectionType *type)
2216 MonoClass *klass = mono_class_from_mono_type (type->type);
2217 mono_class_init_or_throw (klass);
2219 return mono_class_is_com_object (klass);
2222 ICALL_EXPORT MonoReflectionModule*
2223 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2225 MonoClass *klass = mono_class_from_mono_type (type->type);
2226 return mono_module_get_object (mono_object_domain (type), klass->image);
2229 ICALL_EXPORT MonoReflectionAssembly*
2230 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2232 MonoDomain *domain = mono_domain_get ();
2233 MonoClass *klass = mono_class_from_mono_type (type->type);
2234 return mono_assembly_get_object (domain, klass->image->assembly);
2237 ICALL_EXPORT MonoReflectionType*
2238 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2240 MonoDomain *domain = mono_domain_get ();
2243 if (type->type->byref)
2245 if (type->type->type == MONO_TYPE_VAR) {
2246 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2247 klass = param ? param->owner.klass : NULL;
2248 } else if (type->type->type == MONO_TYPE_MVAR) {
2249 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2250 klass = param ? param->owner.method->klass : NULL;
2252 klass = mono_class_from_mono_type (type->type)->nested_in;
2255 return klass ? mono_type_get_object (domain, &klass->byval_arg) : NULL;
2258 ICALL_EXPORT MonoString*
2259 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2261 MonoDomain *domain = mono_domain_get ();
2262 MonoClass *klass = mono_class_from_mono_type (type->type);
2264 if (type->type->byref) {
2265 char *n = g_strdup_printf ("%s&", klass->name);
2266 MonoString *res = mono_string_new (domain, n);
2272 return mono_string_new (domain, klass->name);
2276 ICALL_EXPORT MonoString*
2277 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2279 MonoDomain *domain = mono_domain_get ();
2280 MonoClass *klass = mono_class_from_mono_type (type->type);
2282 while (klass->nested_in)
2283 klass = klass->nested_in;
2285 if (klass->name_space [0] == '\0')
2288 return mono_string_new (domain, klass->name_space);
2292 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2296 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2297 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2301 klass = mono_class_from_mono_type (type->type);
2307 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2310 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2314 ICALL_EXPORT MonoArray*
2315 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2318 MonoClass *klass, *pklass;
2319 MonoDomain *domain = mono_object_domain (type);
2322 klass = mono_class_from_mono_type (type->type);
2324 if (klass->generic_container) {
2325 MonoGenericContainer *container = klass->generic_container;
2326 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2327 for (i = 0; i < container->type_argc; ++i) {
2328 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2329 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2331 } else if (klass->generic_class) {
2332 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2333 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2334 for (i = 0; i < inst->type_argc; ++i)
2335 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2342 ICALL_EXPORT gboolean
2343 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2347 if (!IS_MONOTYPE (type))
2350 if (type->type->byref)
2353 klass = mono_class_from_mono_type (type->type);
2354 return klass->generic_container != NULL;
2357 ICALL_EXPORT MonoReflectionType*
2358 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2362 if (type->type->byref)
2365 klass = mono_class_from_mono_type (type->type);
2367 if (klass->generic_container) {
2368 return type; /* check this one */
2370 if (klass->generic_class) {
2371 MonoClass *generic_class = klass->generic_class->container_class;
2374 tb = mono_class_get_ref_info (generic_class);
2376 if (generic_class->wastypebuilder && tb)
2377 return (MonoReflectionType *)tb;
2379 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2384 ICALL_EXPORT MonoReflectionType*
2385 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2388 MonoType *geninst, **types;
2391 g_assert (IS_MONOTYPE (type));
2392 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2394 count = mono_array_length (type_array);
2395 types = g_new0 (MonoType *, count);
2397 for (i = 0; i < count; i++) {
2398 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2399 types [i] = t->type;
2402 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2407 klass = mono_class_from_mono_type (geninst);
2409 /*we might inflate to the GTD*/
2410 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2411 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2415 return mono_type_get_object (mono_object_domain (type), geninst);
2418 ICALL_EXPORT gboolean
2419 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2423 if (!IS_MONOTYPE (type))
2426 if (type->type->byref)
2429 klass = mono_class_from_mono_type (type->type);
2430 return klass->generic_class != NULL || klass->generic_container != NULL;
2434 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2436 if (!IS_MONOTYPE (type))
2439 if (is_generic_parameter (type->type))
2440 return mono_type_get_generic_param_num (type->type);
2444 ICALL_EXPORT GenericParameterAttributes
2445 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2447 g_assert (IS_MONOTYPE (type));
2448 g_assert (is_generic_parameter (type->type));
2449 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2452 ICALL_EXPORT MonoArray *
2453 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2455 MonoGenericParamInfo *param_info;
2461 g_assert (IS_MONOTYPE (type));
2463 domain = mono_object_domain (type);
2464 param_info = mono_generic_param_info (type->type->data.generic_param);
2465 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2468 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2469 for (i = 0; i < count; i++)
2470 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2476 ICALL_EXPORT MonoBoolean
2477 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2479 return is_generic_parameter (type->type);
2482 ICALL_EXPORT MonoBoolean
2483 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2485 return is_generic_parameter (tb->type.type);
2489 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2490 MonoReflectionType *t)
2492 enumtype->type = t->type;
2495 ICALL_EXPORT MonoReflectionMethod*
2496 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2497 MonoReflectionMethod* generic)
2504 domain = ((MonoObject *)type)->vtable->domain;
2506 klass = mono_class_from_mono_type (type->type);
2507 mono_class_init_or_throw (klass);
2510 while ((method = mono_class_get_methods (klass, &iter))) {
2511 if (method->token == generic->method->token)
2512 return mono_method_get_object (domain, method, klass);
2518 ICALL_EXPORT MonoReflectionMethod *
2519 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2522 MonoType *type = ref_type->type;
2524 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2525 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2528 if (type->type == MONO_TYPE_VAR)
2531 method = mono_type_get_generic_param_owner (type)->owner.method;
2533 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2536 ICALL_EXPORT MonoBoolean
2537 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2539 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2543 ICALL_EXPORT MonoBoolean
2544 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2546 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2551 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2553 MonoDomain *domain = mono_domain_get ();
2554 MonoImage *image = method->method->klass->image;
2555 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2556 MonoTableInfo *tables = image->tables;
2557 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2558 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2559 guint32 im_cols [MONO_IMPLMAP_SIZE];
2560 guint32 scope_token;
2561 const char *import = NULL;
2562 const char *scope = NULL;
2564 if (image_is_dynamic (image)) {
2565 MonoReflectionMethodAux *method_aux =
2566 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2568 import = method_aux->dllentry;
2569 scope = method_aux->dll;
2572 if (!import || !scope) {
2573 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2578 if (piinfo->implmap_idx) {
2579 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2581 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2582 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2583 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2584 scope = mono_metadata_string_heap (image, scope_token);
2588 *flags = piinfo->piflags;
2589 *entry_point = mono_string_new (domain, import);
2590 *dll_name = mono_string_new (domain, scope);
2593 ICALL_EXPORT MonoReflectionMethod *
2594 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2596 MonoMethodInflated *imethod;
2599 if (method->method->is_generic)
2602 if (!method->method->is_inflated)
2605 imethod = (MonoMethodInflated *) method->method;
2607 result = imethod->declaring;
2608 /* Not a generic method. */
2609 if (!result->is_generic)
2612 if (image_is_dynamic (method->method->klass->image)) {
2613 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2614 MonoReflectionMethod *res;
2617 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2618 * the dynamic case as well ?
2620 mono_image_lock ((MonoImage*)image);
2621 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2622 mono_image_unlock ((MonoImage*)image);
2628 if (imethod->context.class_inst) {
2629 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2630 /*Generic methods gets the context of the GTD.*/
2631 if (mono_class_get_context (klass)) {
2633 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2634 mono_error_raise_exception (&error);
2638 return mono_method_get_object (mono_object_domain (method), result, NULL);
2641 ICALL_EXPORT gboolean
2642 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2644 return mono_method_signature (method->method)->generic_param_count != 0;
2647 ICALL_EXPORT gboolean
2648 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2650 return method->method->is_generic;
2653 ICALL_EXPORT MonoArray*
2654 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2660 domain = mono_object_domain (method);
2662 if (method->method->is_inflated) {
2663 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2666 count = inst->type_argc;
2667 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2669 for (i = 0; i < count; i++)
2670 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2676 count = mono_method_signature (method->method)->generic_param_count;
2677 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2679 for (i = 0; i < count; i++) {
2680 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2681 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2682 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2683 mono_array_setref (res, i,
2684 mono_type_get_object (domain, &pklass->byval_arg));
2690 ICALL_EXPORT MonoObject *
2691 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2694 * Invoke from reflection is supposed to always be a virtual call (the API
2695 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2696 * greater flexibility.
2698 MonoMethod *m = method->method;
2699 MonoMethodSignature *sig = mono_method_signature (m);
2702 void *obj = this_arg;
2706 if (mono_security_core_clr_enabled ())
2707 mono_security_core_clr_ensure_reflection_access_method (m);
2709 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2710 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2711 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2716 if (!mono_object_isinst (this_arg, m->klass)) {
2717 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2718 char *target_name = mono_type_get_full_name (m->klass);
2719 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2720 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2722 g_free (target_name);
2726 m = mono_object_get_virtual_method (this_arg, m);
2727 /* must pass the pointer to the value for valuetype methods */
2728 if (m->klass->valuetype)
2729 obj = mono_object_unbox (this_arg);
2730 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2731 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2736 if (sig->ret->byref) {
2737 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"));
2741 pcount = params? mono_array_length (params): 0;
2742 if (pcount != sig->param_count) {
2743 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2747 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2748 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."));
2752 image = m->klass->image;
2753 if (image->assembly->ref_only) {
2754 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."));
2758 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2759 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2763 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2766 intptr_t *lower_bounds;
2767 pcount = mono_array_length (params);
2768 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
2769 /* Note: the synthetized array .ctors have int32 as argument type */
2770 for (i = 0; i < pcount; ++i)
2771 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2773 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2774 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2775 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2777 for (i = 0; i < mono_array_length (arr); ++i) {
2778 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2780 mono_array_setref_fast (arr, i, subarray);
2782 return (MonoObject*)arr;
2785 if (m->klass->rank == pcount) {
2786 /* Only lengths provided. */
2787 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2789 g_assert (pcount == (m->klass->rank * 2));
2790 /* The arguments are lower-bound-length pairs */
2791 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
2793 for (i = 0; i < pcount / 2; ++i) {
2794 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
2795 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
2798 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2801 return mono_runtime_invoke_array (m, obj, params, NULL);
2804 #ifndef DISABLE_REMOTING
2805 ICALL_EXPORT MonoObject *
2806 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
2808 MonoDomain *domain = mono_object_domain (method);
2809 MonoMethod *m = method->method;
2810 MonoMethodSignature *sig = mono_method_signature (m);
2811 MonoArray *out_args;
2813 int i, j, outarg_count = 0;
2815 if (m->klass == mono_defaults.object_class) {
2816 if (!strcmp (m->name, "FieldGetter")) {
2817 MonoClass *k = this_arg->vtable->klass;
2821 /* If this is a proxy, then it must be a CBO */
2822 if (k == mono_defaults.transparent_proxy_class) {
2823 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2824 this_arg = tp->rp->unwrapped_server;
2825 g_assert (this_arg);
2826 k = this_arg->vtable->klass;
2829 name = mono_array_get (params, MonoString *, 1);
2830 str = mono_string_to_utf8 (name);
2833 MonoClassField* field = mono_class_get_field_from_name (k, str);
2835 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2836 if (field_klass->valuetype)
2837 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
2839 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
2841 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2842 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2843 mono_array_setref (out_args, 0, result);
2851 g_assert_not_reached ();
2853 } else if (!strcmp (m->name, "FieldSetter")) {
2854 MonoClass *k = this_arg->vtable->klass;
2860 /* If this is a proxy, then it must be a CBO */
2861 if (k == mono_defaults.transparent_proxy_class) {
2862 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2863 this_arg = tp->rp->unwrapped_server;
2864 g_assert (this_arg);
2865 k = this_arg->vtable->klass;
2868 name = mono_array_get (params, MonoString *, 1);
2869 str = mono_string_to_utf8 (name);
2872 MonoClassField* field = mono_class_get_field_from_name (k, str);
2874 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2875 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
2877 if (field_klass->valuetype) {
2878 size = mono_type_size (field->type, &align);
2879 g_assert (size == mono_class_value_size (field_klass, NULL));
2880 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2882 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
2885 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2886 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2896 g_assert_not_reached ();
2901 for (i = 0; i < mono_array_length (params); i++) {
2902 if (sig->params [i]->byref)
2906 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2908 /* handle constructors only for objects already allocated */
2909 if (!strcmp (method->method->name, ".ctor"))
2910 g_assert (this_arg);
2912 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2913 g_assert (!method->method->klass->valuetype);
2914 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
2916 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2917 if (sig->params [i]->byref) {
2919 arg = mono_array_get (params, gpointer, i);
2920 mono_array_setref (out_args, j, arg);
2925 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2932 read_enum_value (const char *mem, int type)
2935 case MONO_TYPE_BOOLEAN:
2937 return *(guint8*)mem;
2939 return *(gint8*)mem;
2940 case MONO_TYPE_CHAR:
2942 return read16 (mem);
2944 return (gint16) read16 (mem);
2946 return read32 (mem);
2948 return (gint32) read32 (mem);
2951 return read64 (mem);
2953 g_assert_not_reached ();
2959 write_enum_value (char *mem, int type, guint64 value)
2963 case MONO_TYPE_I1: {
2964 guint8 *p = (guint8*)mem;
2969 case MONO_TYPE_I2: {
2970 guint16 *p = (guint16 *)mem;
2975 case MONO_TYPE_I4: {
2976 guint32 *p = (guint32 *)mem;
2981 case MONO_TYPE_I8: {
2982 guint64 *p = (guint64 *)mem;
2987 g_assert_not_reached ();
2992 ICALL_EXPORT MonoObject *
2993 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3000 domain = mono_object_domain (enumType);
3001 enumc = mono_class_from_mono_type (enumType->type);
3003 mono_class_init_or_throw (enumc);
3005 etype = mono_class_enum_basetype (enumc);
3007 res = mono_object_new (domain, enumc);
3008 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3013 ICALL_EXPORT MonoBoolean
3014 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3016 int size = mono_class_value_size (a->vtable->klass, NULL);
3017 guint64 a_val = 0, b_val = 0;
3019 memcpy (&a_val, mono_object_unbox (a), size);
3020 memcpy (&b_val, mono_object_unbox (b), size);
3022 return (a_val & b_val) == b_val;
3025 ICALL_EXPORT MonoObject *
3026 ves_icall_System_Enum_get_value (MonoObject *eobj)
3037 g_assert (eobj->vtable->klass->enumtype);
3039 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3040 res = mono_object_new (mono_object_domain (eobj), enumc);
3041 dst = (char *)res + sizeof (MonoObject);
3042 src = (char *)eobj + sizeof (MonoObject);
3043 size = mono_class_value_size (enumc, NULL);
3045 memcpy (dst, src, size);
3050 ICALL_EXPORT MonoReflectionType *
3051 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3056 klass = mono_class_from_mono_type (type->type);
3057 mono_class_init_or_throw (klass);
3059 etype = mono_class_enum_basetype (klass);
3061 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3065 return mono_type_get_object (mono_object_domain (type), etype);
3069 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3071 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3072 gpointer odata = (char *)other + sizeof (MonoObject);
3073 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3074 g_assert (basetype);
3079 if (eobj->vtable->klass != other->vtable->klass)
3082 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3083 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3084 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3087 return me > other ? 1 : -1; \
3090 switch (basetype->type) {
3092 COMPARE_ENUM_VALUES (guint8);
3094 COMPARE_ENUM_VALUES (gint8);
3095 case MONO_TYPE_CHAR:
3097 COMPARE_ENUM_VALUES (guint16);
3099 COMPARE_ENUM_VALUES (gint16);
3101 COMPARE_ENUM_VALUES (guint32);
3103 COMPARE_ENUM_VALUES (gint32);
3105 COMPARE_ENUM_VALUES (guint64);
3107 COMPARE_ENUM_VALUES (gint64);
3111 #undef COMPARE_ENUM_VALUES
3112 /* indicates that the enum was of an unsupported unerlying type */
3117 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3119 gpointer data = (char *)eobj + sizeof (MonoObject);
3120 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3121 g_assert (basetype);
3123 switch (basetype->type) {
3124 case MONO_TYPE_I1: {
3125 gint8 value = *((gint8*)data);
3126 return ((int)value ^ (int)value << 8);
3129 return *((guint8*)data);
3130 case MONO_TYPE_CHAR:
3132 return *((guint16*)data);
3134 case MONO_TYPE_I2: {
3135 gint16 value = *((gint16*)data);
3136 return ((int)(guint16)value | (((int)value) << 16));
3139 return *((guint32*)data);
3141 return *((gint32*)data);
3143 case MONO_TYPE_I8: {
3144 gint64 value = *((gint64*)data);
3145 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3148 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3153 ICALL_EXPORT MonoBoolean
3154 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3156 MonoDomain *domain = mono_object_domain (type);
3157 MonoClass *enumc = mono_class_from_mono_type (type->type);
3158 guint j = 0, nvalues;
3160 MonoClassField *field;
3162 guint64 field_value, previous_value = 0;
3163 gboolean sorted = TRUE;
3165 mono_class_init_or_throw (enumc);
3167 if (!enumc->enumtype) {
3168 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3172 base_type = mono_class_enum_basetype (enumc)->type;
3174 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3175 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3176 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3179 while ((field = mono_class_get_fields (enumc, &iter))) {
3181 MonoTypeEnum def_type;
3183 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3185 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3187 if (mono_field_is_deleted (field))
3189 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3191 p = mono_class_get_field_default_value (field, &def_type);
3192 /* len = */ mono_metadata_decode_blob_size (p, &p);
3194 field_value = read_enum_value (p, base_type);
3195 mono_array_set (*values, guint64, j, field_value);
3197 if (previous_value > field_value)
3200 previous_value = field_value;
3208 BFLAGS_IgnoreCase = 1,
3209 BFLAGS_DeclaredOnly = 2,
3210 BFLAGS_Instance = 4,
3212 BFLAGS_Public = 0x10,
3213 BFLAGS_NonPublic = 0x20,
3214 BFLAGS_FlattenHierarchy = 0x40,
3215 BFLAGS_InvokeMethod = 0x100,
3216 BFLAGS_CreateInstance = 0x200,
3217 BFLAGS_GetField = 0x400,
3218 BFLAGS_SetField = 0x800,
3219 BFLAGS_GetProperty = 0x1000,
3220 BFLAGS_SetProperty = 0x2000,
3221 BFLAGS_ExactBinding = 0x10000,
3222 BFLAGS_SuppressChangeType = 0x20000,
3223 BFLAGS_OptionalParamBinding = 0x40000
3226 ICALL_EXPORT MonoArray*
3227 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3230 MonoClass *startklass, *klass, *refklass;
3235 char *utf8_name = NULL;
3236 int (*compare_func) (const char *s1, const char *s2) = NULL;
3237 MonoClassField *field;
3238 MonoPtrArray tmp_array;
3240 domain = ((MonoObject *)type)->vtable->domain;
3241 if (type->type->byref)
3242 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3244 klass = startklass = mono_class_from_mono_type (type->type);
3245 refklass = mono_class_from_mono_type (reftype->type);
3247 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3250 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3251 mono_ptr_array_destroy (tmp_array);
3252 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3257 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3258 guint32 flags = mono_field_get_flags (field);
3260 if (mono_field_is_deleted_with_flags (field, flags))
3262 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3263 if (bflags & BFLAGS_Public)
3265 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3266 if (bflags & BFLAGS_NonPublic) {
3273 if (flags & FIELD_ATTRIBUTE_STATIC) {
3274 if (bflags & BFLAGS_Static)
3275 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3278 if (bflags & BFLAGS_Instance)
3286 if (utf8_name == NULL) {
3287 utf8_name = mono_string_to_utf8 (name);
3288 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3291 if (compare_func (mono_field_get_name (field), utf8_name))
3295 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3296 mono_ptr_array_append (tmp_array, member);
3298 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3301 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3303 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3304 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3306 mono_ptr_array_destroy (tmp_array);
3308 if (utf8_name != NULL)
3315 method_nonpublic (MonoMethod* method, gboolean start_klass)
3317 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3318 case METHOD_ATTRIBUTE_ASSEM:
3319 return (start_klass || mono_defaults.generic_ilist_class);
3320 case METHOD_ATTRIBUTE_PRIVATE:
3322 case METHOD_ATTRIBUTE_PUBLIC:
3330 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3333 MonoClass *startklass;
3337 /*FIXME, use MonoBitSet*/
3338 guint32 method_slots_default [8];
3339 guint32 *method_slots = NULL;
3340 int (*compare_func) (const char *s1, const char *s2) = NULL;
3342 array = g_ptr_array_new ();
3347 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3349 /* An optimization for calls made from Delegate:CreateDelegate () */
3350 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3351 method = mono_get_delegate_invoke (klass);
3352 if (mono_loader_get_last_error ())
3355 g_ptr_array_add (array, method);
3359 mono_class_setup_methods (klass);
3360 mono_class_setup_vtable (klass);
3361 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3364 if (is_generic_parameter (&klass->byval_arg))
3365 nslots = mono_class_get_vtable_size (klass->parent);
3367 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3368 if (nslots >= sizeof (method_slots_default) * 8) {
3369 method_slots = g_new0 (guint32, nslots / 32 + 1);
3371 method_slots = method_slots_default;
3372 memset (method_slots, 0, sizeof (method_slots_default));
3375 mono_class_setup_methods (klass);
3376 mono_class_setup_vtable (klass);
3377 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3381 while ((method = mono_class_get_methods (klass, &iter))) {
3383 if (method->slot != -1) {
3384 g_assert (method->slot < nslots);
3385 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3387 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3388 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3391 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3393 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3394 if (bflags & BFLAGS_Public)
3396 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3402 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3403 if (bflags & BFLAGS_Static)
3404 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3407 if (bflags & BFLAGS_Instance)
3415 if (compare_func (name, method->name))
3420 g_ptr_array_add (array, method);
3422 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3424 if (method_slots != method_slots_default)
3425 g_free (method_slots);
3430 if (method_slots != method_slots_default)
3431 g_free (method_slots);
3432 g_ptr_array_free (array, TRUE);
3434 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3435 *ex = mono_class_get_exception_for_failure (klass);
3437 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3438 mono_loader_clear_error ();
3443 ICALL_EXPORT MonoArray*
3444 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3446 static MonoClass *MethodInfo_array;
3449 MonoVTable *array_vtable;
3450 MonoException *ex = NULL;
3451 const char *mname = NULL;
3452 GPtrArray *method_array;
3453 MonoClass *klass, *refklass;
3456 if (!MethodInfo_array) {
3457 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3458 mono_memory_barrier ();
3459 MethodInfo_array = klass;
3462 klass = mono_class_from_mono_type (type->type);
3463 refklass = mono_class_from_mono_type (reftype->type);
3464 domain = ((MonoObject *)type)->vtable->domain;
3465 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3466 if (type->type->byref)
3467 return mono_array_new_specific (array_vtable, 0);
3470 mname = mono_string_to_utf8 (name);
3472 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3473 g_free ((char*)mname);
3475 mono_set_pending_exception (ex);
3479 res = mono_array_new_specific (array_vtable, method_array->len);
3481 for (i = 0; i < method_array->len; ++i) {
3482 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3483 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3486 g_ptr_array_free (method_array, TRUE);
3490 ICALL_EXPORT MonoArray*
3491 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3494 static MonoClass *System_Reflection_ConstructorInfo;
3495 MonoClass *startklass, *klass, *refklass;
3500 gpointer iter = NULL;
3501 MonoPtrArray tmp_array;
3503 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3505 domain = ((MonoObject *)type)->vtable->domain;
3506 if (type->type->byref)
3507 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3508 klass = startklass = mono_class_from_mono_type (type->type);
3509 refklass = mono_class_from_mono_type (reftype->type);
3511 if (!System_Reflection_ConstructorInfo)
3512 System_Reflection_ConstructorInfo = mono_class_from_name (
3513 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3515 mono_class_setup_methods (klass);
3516 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3517 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3522 while ((method = mono_class_get_methods (klass, &iter))) {
3524 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3526 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3527 if (bflags & BFLAGS_Public)
3530 if (bflags & BFLAGS_NonPublic)
3536 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3537 if (bflags & BFLAGS_Static)
3538 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3541 if (bflags & BFLAGS_Instance)
3547 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3549 mono_ptr_array_append (tmp_array, member);
3552 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3554 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3555 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3557 mono_ptr_array_destroy (tmp_array);
3563 property_hash (gconstpointer data)
3565 MonoProperty *prop = (MonoProperty*)data;
3567 return g_str_hash (prop->name);
3571 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3573 if (method1->is_inflated)
3574 method1 = ((MonoMethodInflated*) method1)->declaring;
3575 if (method2->is_inflated)
3576 method2 = ((MonoMethodInflated*) method2)->declaring;
3578 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3582 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3584 // Properties are hide-by-name-and-signature
3585 if (!g_str_equal (prop1->name, prop2->name))
3588 /* If we see a property in a generic method, we want to
3589 compare the generic signatures, not the inflated signatures
3590 because we might conflate two properties that were
3594 public T this[T t] { getter { return t; } } // method 1
3595 public U this[U u] { getter { return u; } } // method 2
3598 If we see int Foo<int,int>::Item[int] we need to know if
3599 the indexer came from method 1 or from method 2, and we
3600 shouldn't conflate them. (Bugzilla 36283)
3602 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3605 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3612 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3617 return method_nonpublic (accessor, start_klass);
3620 ICALL_EXPORT MonoArray*
3621 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3625 static MonoClass *System_Reflection_PropertyInfo;
3626 MonoClass *startklass, *klass;
3632 gchar *propname = NULL;
3633 int (*compare_func) (const char *s1, const char *s2) = NULL;
3635 GHashTable *properties = NULL;
3636 MonoPtrArray tmp_array;
3638 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3640 if (!System_Reflection_PropertyInfo)
3641 System_Reflection_PropertyInfo = mono_class_from_name (
3642 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3644 domain = ((MonoObject *)type)->vtable->domain;
3645 if (type->type->byref)
3646 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3647 klass = startklass = mono_class_from_mono_type (type->type);
3650 propname = mono_string_to_utf8 (name);
3651 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3654 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3656 mono_class_setup_methods (klass);
3657 mono_class_setup_vtable (klass);
3658 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3662 while ((prop = mono_class_get_properties (klass, &iter))) {
3668 flags = method->flags;
3671 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3672 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3673 if (bflags & BFLAGS_Public)
3675 } else if (bflags & BFLAGS_NonPublic) {
3676 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3677 property_accessor_nonpublic(prop->set, startklass == klass)) {
3684 if (flags & METHOD_ATTRIBUTE_STATIC) {
3685 if (bflags & BFLAGS_Static)
3686 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3689 if (bflags & BFLAGS_Instance)
3698 if (compare_func (propname, prop->name))
3702 if (g_hash_table_lookup (properties, prop))
3705 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3707 g_hash_table_insert (properties, prop, prop);
3709 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3712 g_hash_table_destroy (properties);
3715 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3716 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3717 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3719 mono_ptr_array_destroy (tmp_array);
3725 g_hash_table_destroy (properties);
3728 mono_ptr_array_destroy (tmp_array);
3730 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3731 ex = mono_class_get_exception_for_failure (klass);
3733 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3734 mono_loader_clear_error ();
3736 mono_set_pending_exception (ex);
3741 event_hash (gconstpointer data)
3743 MonoEvent *event = (MonoEvent*)data;
3745 return g_str_hash (event->name);
3749 event_equal (MonoEvent *event1, MonoEvent *event2)
3751 // Events are hide-by-name
3752 return g_str_equal (event1->name, event2->name);
3755 ICALL_EXPORT MonoArray*
3756 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3760 static MonoClass *System_Reflection_EventInfo;
3761 MonoClass *startklass, *klass;
3767 char *utf8_name = NULL;
3768 int (*compare_func) (const char *s1, const char *s2) = NULL;
3769 GHashTable *events = NULL;
3770 MonoPtrArray tmp_array;
3772 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
3774 if (!System_Reflection_EventInfo)
3775 System_Reflection_EventInfo = mono_class_from_name (
3776 mono_defaults.corlib, "System.Reflection", "EventInfo");
3778 domain = mono_object_domain (type);
3779 if (type->type->byref)
3780 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3781 klass = startklass = mono_class_from_mono_type (type->type);
3783 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3785 mono_class_setup_methods (klass);
3786 mono_class_setup_vtable (klass);
3787 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3791 while ((event = mono_class_get_events (klass, &iter))) {
3793 method = event->add;
3795 method = event->remove;
3797 method = event->raise;
3799 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3800 if (bflags & BFLAGS_Public)
3802 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3803 if (bflags & BFLAGS_NonPublic)
3808 if (bflags & BFLAGS_NonPublic)
3814 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3815 if (bflags & BFLAGS_Static)
3816 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3819 if (bflags & BFLAGS_Instance)
3824 if (bflags & BFLAGS_Instance)
3830 if (utf8_name == NULL) {
3831 utf8_name = mono_string_to_utf8 (name);
3832 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3835 if (compare_func (event->name, utf8_name))
3839 if (g_hash_table_lookup (events, event))
3842 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3844 g_hash_table_insert (events, event, event);
3846 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3849 g_hash_table_destroy (events);
3851 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3853 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3854 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3856 mono_ptr_array_destroy (tmp_array);
3858 if (utf8_name != NULL)
3864 mono_ptr_array_destroy (tmp_array);
3865 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3866 ex = mono_class_get_exception_for_failure (klass);
3868 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3869 mono_loader_clear_error ();
3871 mono_set_pending_exception (ex);
3875 ICALL_EXPORT MonoArray*
3876 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
3886 MonoPtrArray tmp_array;
3888 domain = ((MonoObject *)type)->vtable->domain;
3889 if (type->type->byref)
3890 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3891 klass = mono_class_from_mono_type (type->type);
3894 * If a nested type is generic, return its generic type definition.
3895 * Note that this means that the return value is essentially the set
3896 * of nested types of the generic type definition of @klass.
3898 * A note in MSDN claims that a generic type definition can have
3899 * nested types that aren't generic. In any case, the container of that
3900 * nested type would be the generic type definition.
3902 if (klass->generic_class)
3903 klass = klass->generic_class->container_class;
3905 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
3907 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3909 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3910 if (bflags & BFLAGS_Public)
3913 if (bflags & BFLAGS_NonPublic)
3921 str = mono_string_to_utf8 (name);
3922 mono_identifier_unescape_type_name_chars (str);
3925 if (strcmp (nested->name, str))
3929 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3930 mono_ptr_array_append (tmp_array, member);
3933 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
3935 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3936 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3938 mono_ptr_array_destroy (tmp_array);
3946 ICALL_EXPORT MonoReflectionType*
3947 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3950 MonoType *type = NULL;
3951 MonoTypeNameParse info;
3952 gboolean type_resolve;
3954 /* On MS.NET, this does not fire a TypeResolve event */
3955 type_resolve = TRUE;
3956 str = mono_string_to_utf8 (name);
3957 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3958 if (!mono_reflection_parse_type (str, &info)) {
3960 mono_reflection_free_type_info (&info);
3962 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
3965 /*g_print ("failed parse\n");*/
3969 if (info.assembly.name) {
3971 mono_reflection_free_type_info (&info);
3973 /* 1.0 and 2.0 throw different exceptions */
3974 if (mono_defaults.generic_ilist_class)
3975 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
3977 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
3983 if (module != NULL) {
3985 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
3990 if (assembly_is_dynamic (assembly->assembly)) {
3991 /* Enumerate all modules */
3992 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
3996 if (abuilder->modules) {
3997 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
3998 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
3999 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4005 if (!type && abuilder->loaded_modules) {
4006 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4007 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4008 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4015 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4017 mono_reflection_free_type_info (&info);
4019 MonoException *e = NULL;
4022 e = mono_get_exception_type_load (name, NULL);
4024 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4025 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4027 mono_loader_clear_error ();
4030 mono_set_pending_exception (e);
4032 } else if (mono_loader_get_last_error ()) {
4034 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4037 mono_loader_clear_error ();
4040 if (type->type == MONO_TYPE_CLASS) {
4041 MonoClass *klass = mono_type_get_class (type);
4043 /* need to report exceptions ? */
4044 if (throwOnError && klass->exception_type) {
4045 /* report SecurityException (or others) that occured when loading the assembly */
4046 MonoException *exc = mono_class_get_exception_for_failure (klass);
4047 mono_loader_clear_error ();
4048 mono_set_pending_exception (exc);
4053 /* g_print ("got it\n"); */
4054 return mono_type_get_object (mono_object_domain (assembly), type);
4058 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4061 gchar *shadow_ini_file;
4064 /* Check for shadow-copied assembly */
4065 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4066 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4068 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4069 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4075 g_free (shadow_ini_file);
4076 if (content != NULL) {
4079 *filename = content;
4086 ICALL_EXPORT MonoString *
4087 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4089 MonoDomain *domain = mono_object_domain (assembly);
4090 MonoAssembly *mass = assembly->assembly;
4091 MonoString *res = NULL;
4096 if (g_path_is_absolute (mass->image->name)) {
4097 absolute = g_strdup (mass->image->name);
4098 dirname = g_path_get_dirname (absolute);
4100 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4101 dirname = g_strdup (mass->basedir);
4104 replace_shadow_path (domain, dirname, &absolute);
4109 for (i = strlen (absolute) - 1; i >= 0; i--)
4110 if (absolute [i] == '\\')
4115 uri = g_filename_to_uri (absolute, NULL, NULL);
4117 const char *prepend = "file://";
4119 if (*absolute == '/' && *(absolute + 1) == '/') {
4122 prepend = "file:///";
4125 uri = g_strconcat (prepend, absolute, NULL);
4129 res = mono_string_new (domain, uri);
4136 ICALL_EXPORT MonoBoolean
4137 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4139 MonoAssembly *mass = assembly->assembly;
4141 return mass->in_gac;
4144 ICALL_EXPORT MonoReflectionAssembly*
4145 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4149 MonoImageOpenStatus status;
4151 name = mono_string_to_utf8 (mname);
4152 res = mono_assembly_load_with_partial_name (name, &status);
4158 return mono_assembly_get_object (mono_domain_get (), res);
4161 ICALL_EXPORT MonoString *
4162 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4164 MonoDomain *domain = mono_object_domain (assembly);
4167 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4172 ICALL_EXPORT MonoBoolean
4173 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4175 return assembly->assembly->ref_only;
4178 ICALL_EXPORT MonoString *
4179 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4181 MonoDomain *domain = mono_object_domain (assembly);
4183 return mono_string_new (domain, assembly->assembly->image->version);
4186 ICALL_EXPORT MonoReflectionMethod*
4187 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4191 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4195 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4196 mono_error_raise_exception (&error);
4198 return mono_method_get_object (mono_object_domain (assembly), method, NULL);
4201 ICALL_EXPORT MonoReflectionModule*
4202 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4204 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4207 ICALL_EXPORT MonoArray*
4208 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4210 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4211 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4215 for (i = 0; i < table->rows; ++i) {
4216 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4217 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4223 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4225 static MonoClass *System_Version = NULL;
4226 static MonoMethod *create_version = NULL;
4230 if (!System_Version) {
4231 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4232 g_assert (System_Version);
4235 if (!create_version) {
4236 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4237 create_version = mono_method_desc_search_in_class (desc, System_Version);
4238 g_assert (create_version);
4239 mono_method_desc_free (desc);
4245 args [3] = &revision;
4246 result = mono_object_new (domain, System_Version);
4247 mono_runtime_invoke (create_version, result, args, NULL);
4252 ICALL_EXPORT MonoArray*
4253 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4255 static MonoClass *System_Reflection_AssemblyName;
4257 MonoDomain *domain = mono_object_domain (assembly);
4259 static MonoMethod *create_culture = NULL;
4260 MonoImage *image = assembly->assembly->image;
4263 if (!System_Reflection_AssemblyName)
4264 System_Reflection_AssemblyName = mono_class_from_name (
4265 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4267 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4270 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4272 if (count > 0 && !create_culture) {
4273 MonoMethodDesc *desc = mono_method_desc_new (
4274 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4275 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4276 g_assert (create_culture);
4277 mono_method_desc_free (desc);
4280 for (i = 0; i < count; i++) {
4281 MonoReflectionAssemblyName *aname;
4282 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4284 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4286 aname = (MonoReflectionAssemblyName *) mono_object_new (
4287 domain, System_Reflection_AssemblyName);
4289 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4291 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4292 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4293 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4294 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4295 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4296 aname->versioncompat = 1; /* SameMachine (default) */
4297 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4298 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4300 if (create_culture) {
4302 MonoBoolean assembly_ref = 1;
4303 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4304 args [1] = &assembly_ref;
4305 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4308 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4309 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4310 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4312 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4313 /* public key token isn't copied - the class library will
4314 automatically generate it from the public key if required */
4315 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4316 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4318 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4319 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4322 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4325 /* note: this function doesn't return the codebase on purpose (i.e. it can
4326 be used under partial trust as path information isn't present). */
4328 mono_array_setref (result, i, aname);
4333 /* move this in some file in mono/util/ */
4335 g_concat_dir_and_file (const char *dir, const char *file)
4337 g_return_val_if_fail (dir != NULL, NULL);
4338 g_return_val_if_fail (file != NULL, NULL);
4341 * If the directory name doesn't have a / on the end, we need
4342 * to add one so we get a proper path to the file
4344 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4345 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4347 return g_strconcat (dir, file, NULL);
4351 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4353 char *n = mono_string_to_utf8 (name);
4354 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4356 guint32 cols [MONO_MANIFEST_SIZE];
4357 guint32 impl, file_idx;
4361 for (i = 0; i < table->rows; ++i) {
4362 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4363 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4364 if (strcmp (val, n) == 0)
4368 if (i == table->rows)
4371 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4374 * this code should only be called after obtaining the
4375 * ResourceInfo and handling the other cases.
4377 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4378 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4380 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4385 module = assembly->assembly->image;
4387 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4389 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4392 ICALL_EXPORT gboolean
4393 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4395 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4397 guint32 cols [MONO_MANIFEST_SIZE];
4398 guint32 file_cols [MONO_FILE_SIZE];
4402 n = mono_string_to_utf8 (name);
4403 for (i = 0; i < table->rows; ++i) {
4404 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4405 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4406 if (strcmp (val, n) == 0)
4410 if (i == table->rows)
4413 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4414 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4417 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4418 case MONO_IMPLEMENTATION_FILE:
4419 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4420 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4421 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4422 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4423 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4424 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4427 info->location = RESOURCE_LOCATION_EMBEDDED;
4430 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4431 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4432 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4433 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4434 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4435 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4437 mono_set_pending_exception (ex);
4440 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4442 /* Obtain info recursively */
4443 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4444 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4447 case MONO_IMPLEMENTATION_EXP_TYPE:
4448 g_assert_not_reached ();
4456 ICALL_EXPORT MonoObject*
4457 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4459 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4460 MonoArray *result = NULL;
4465 /* check hash if needed */
4467 n = mono_string_to_utf8 (name);
4468 for (i = 0; i < table->rows; ++i) {
4469 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4470 if (strcmp (val, n) == 0) {
4473 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4474 fn = mono_string_new (mono_object_domain (assembly), n);
4476 return (MonoObject*)fn;
4484 for (i = 0; i < table->rows; ++i) {
4485 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4489 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4492 for (i = 0; i < table->rows; ++i) {
4493 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4494 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4495 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4496 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4501 return (MonoObject*)result;
4504 ICALL_EXPORT MonoArray*
4505 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4507 MonoDomain *domain = mono_domain_get();
4510 int i, j, file_count = 0;
4511 MonoImage **modules;
4512 guint32 module_count, real_module_count;
4513 MonoTableInfo *table;
4514 guint32 cols [MONO_FILE_SIZE];
4515 MonoImage *image = assembly->assembly->image;
4517 g_assert (image != NULL);
4518 g_assert (!assembly_is_dynamic (assembly->assembly));
4520 table = &image->tables [MONO_TABLE_FILE];
4521 file_count = table->rows;
4523 modules = image->modules;
4524 module_count = image->module_count;
4526 real_module_count = 0;
4527 for (i = 0; i < module_count; ++i)
4529 real_module_count ++;
4531 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4532 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4534 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4536 for (i = 0; i < module_count; ++i)
4538 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4542 for (i = 0; i < file_count; ++i, ++j) {
4543 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4544 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4545 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4547 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4549 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4550 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4553 mono_array_setref (res, j, mono_module_get_object (domain, m));
4560 ICALL_EXPORT MonoReflectionMethod*
4561 ves_icall_GetCurrentMethod (void)
4563 MonoMethod *m = mono_method_get_last_managed ();
4565 while (m->is_inflated)
4566 m = ((MonoMethodInflated*)m)->declaring;
4568 return mono_method_get_object (mono_domain_get (), m, NULL);
4573 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4576 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4579 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4580 //method is inflated, we should inflate it on the other class
4581 MonoGenericContext ctx;
4582 ctx.method_inst = inflated->context.method_inst;
4583 ctx.class_inst = inflated->context.class_inst;
4584 if (klass->generic_class)
4585 ctx.class_inst = klass->generic_class->context.class_inst;
4586 else if (klass->generic_container)
4587 ctx.class_inst = klass->generic_container->context.class_inst;
4588 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4589 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4593 mono_class_setup_methods (method->klass);
4594 if (method->klass->exception_type)
4596 for (i = 0; i < method->klass->method.count; ++i) {
4597 if (method->klass->methods [i] == method) {
4602 mono_class_setup_methods (klass);
4603 if (klass->exception_type)
4605 g_assert (offset >= 0 && offset < klass->method.count);
4606 return klass->methods [offset];
4609 ICALL_EXPORT MonoReflectionMethod*
4610 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4614 klass = mono_class_from_mono_type (type);
4615 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4617 if (method->klass != klass) {
4618 method = mono_method_get_equivalent_method (method, klass);
4623 klass = method->klass;
4624 return mono_method_get_object (mono_domain_get (), method, klass);
4627 ICALL_EXPORT MonoReflectionMethodBody*
4628 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4630 return mono_method_body_get_object (mono_domain_get (), method);
4633 ICALL_EXPORT MonoReflectionAssembly*
4634 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4636 MonoMethod *dest = NULL;
4638 mono_stack_walk_no_il (get_executing, &dest);
4640 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4644 ICALL_EXPORT MonoReflectionAssembly*
4645 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4647 MonoDomain* domain = mono_domain_get ();
4649 if (!domain->entry_assembly)
4652 return mono_assembly_get_object (domain, domain->entry_assembly);
4655 ICALL_EXPORT MonoReflectionAssembly*
4656 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4662 mono_stack_walk_no_il (get_executing, &dest);
4664 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
4667 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4670 ICALL_EXPORT MonoString *
4671 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4672 gboolean assembly_qualified)
4674 MonoDomain *domain = mono_object_domain (object);
4675 MonoTypeNameFormat format;
4680 format = assembly_qualified ?
4681 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4682 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4684 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4686 name = mono_type_get_name_full (object->type, format);
4690 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4695 res = mono_string_new (domain, name);
4702 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
4704 MonoClass *klass = mono_class_from_mono_type (rfield->type);
4705 mono_class_init_or_throw (klass);
4706 return mono_security_core_clr_class_level (klass);
4710 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
4712 MonoClassField *field = rfield->field;
4713 return mono_security_core_clr_field_level (field, TRUE);
4717 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
4719 MonoMethod *method = rfield->method;
4720 return mono_security_core_clr_method_level (method, TRUE);
4724 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4726 static MonoMethod *create_culture = NULL;
4729 const char *pkey_ptr;
4731 MonoBoolean assembly_ref = 0;
4733 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4734 aname->major = name->major;
4735 aname->minor = name->minor;
4736 aname->build = name->build;
4737 aname->flags = name->flags;
4738 aname->revision = name->revision;
4739 aname->hashalg = name->hash_alg;
4740 aname->versioncompat = 1; /* SameMachine (default) */
4741 aname->processor_architecture = name->arch;
4743 if (by_default_version)
4744 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4747 if (absolute != NULL && *absolute != '\0') {
4748 const gchar *prepend = "file://";
4751 codebase = g_strdup (absolute);
4756 for (i = strlen (codebase) - 1; i >= 0; i--)
4757 if (codebase [i] == '\\')
4760 if (*codebase == '/' && *(codebase + 1) == '/') {
4763 prepend = "file:///";
4767 result = g_strconcat (prepend, codebase, NULL);
4773 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4777 if (!create_culture) {
4778 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4779 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4780 g_assert (create_culture);
4781 mono_method_desc_free (desc);
4784 if (name->culture) {
4785 args [0] = mono_string_new (domain, name->culture);
4786 args [1] = &assembly_ref;
4787 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4790 if (name->public_key) {
4791 pkey_ptr = (char*)name->public_key;
4792 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4794 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4795 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4796 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4797 } else if (default_publickey) {
4798 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4799 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4802 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4803 if (name->public_key_token [0]) {
4807 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4808 p = mono_array_addr (aname->keyToken, char, 0);
4810 for (i = 0, j = 0; i < 8; i++) {
4811 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4812 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4815 } else if (default_token) {
4816 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4820 ICALL_EXPORT MonoString *
4821 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4823 MonoDomain *domain = mono_object_domain (assembly);
4824 MonoAssembly *mass = assembly->assembly;
4828 name = mono_stringify_assembly_name (&mass->aname);
4829 res = mono_string_new (domain, name);
4836 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4839 MonoAssembly *mass = assembly->assembly;
4841 if (g_path_is_absolute (mass->image->name)) {
4842 fill_reflection_assembly_name (mono_object_domain (assembly),
4843 aname, &mass->aname, mass->image->name, TRUE,
4847 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4849 fill_reflection_assembly_name (mono_object_domain (assembly),
4850 aname, &mass->aname, absolute, TRUE, TRUE,
4857 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4860 MonoImageOpenStatus status = MONO_IMAGE_OK;
4863 MonoAssemblyName name;
4866 filename = mono_string_to_utf8 (fname);
4868 dirname = g_path_get_dirname (filename);
4869 replace_shadow_path (mono_domain_get (), dirname, &filename);
4872 image = mono_image_open (filename, &status);
4878 if (status == MONO_IMAGE_IMAGE_INVALID)
4879 exc = mono_get_exception_bad_image_format2 (NULL, fname);
4881 exc = mono_get_exception_file_not_found2 (NULL, fname);
4882 mono_set_pending_exception (exc);
4886 res = mono_assembly_fill_assembly_name (image, &name);
4888 mono_image_close (image);
4890 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4894 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
4898 mono_image_close (image);
4901 ICALL_EXPORT MonoBoolean
4902 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4903 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4905 MonoBoolean result = FALSE;
4906 MonoDeclSecurityEntry entry;
4908 /* SecurityAction.RequestMinimum */
4909 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4910 *minimum = entry.blob;
4911 *minLength = entry.size;
4914 /* SecurityAction.RequestOptional */
4915 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4916 *optional = entry.blob;
4917 *optLength = entry.size;
4920 /* SecurityAction.RequestRefuse */
4921 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4922 *refused = entry.blob;
4923 *refLength = entry.size;
4931 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
4933 guint32 attrs, visibility;
4935 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
4936 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4937 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
4940 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
4946 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
4950 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4953 /* we start the count from 1 because we skip the special type <Module> */
4956 for (i = 1; i < tdef->rows; ++i) {
4957 if (mono_module_type_is_visible (tdef, image, i + 1))
4961 count = tdef->rows - 1;
4963 res = mono_array_new (domain, mono_defaults.monotype_class, count);
4964 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
4966 for (i = 1; i < tdef->rows; ++i) {
4967 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
4969 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
4970 mono_loader_assert_no_error (); /* Plug any leaks */
4973 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
4975 MonoException *ex = mono_error_convert_to_exception (&error);
4976 mono_array_setref (*exceptions, count, ex);
4985 ICALL_EXPORT MonoArray*
4986 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
4988 MonoArray *res = NULL;
4989 MonoArray *exceptions = NULL;
4990 MonoImage *image = NULL;
4991 MonoTableInfo *table = NULL;
4994 int i, len, ex_count;
4996 domain = mono_object_domain (assembly);
4998 g_assert (!assembly_is_dynamic (assembly->assembly));
4999 image = assembly->assembly->image;
5000 table = &image->tables [MONO_TABLE_FILE];
5001 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5003 /* Append data from all modules in the assembly */
5004 for (i = 0; i < table->rows; ++i) {
5005 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5006 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5009 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5010 /* Append the new types to the end of the array */
5011 if (mono_array_length (res2) > 0) {
5013 MonoArray *res3, *ex3;
5015 len1 = mono_array_length (res);
5016 len2 = mono_array_length (res2);
5018 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5019 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5020 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5023 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5024 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5025 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5032 /* the ReflectionTypeLoadException must have all the types (Types property),
5033 * NULL replacing types which throws an exception. The LoaderException must
5034 * contain all exceptions for NULL items.
5037 len = mono_array_length (res);
5040 for (i = 0; i < len; i++) {
5041 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5045 klass = mono_type_get_class (t->type);
5046 if ((klass != NULL) && klass->exception_type) {
5047 /* keep the class in the list */
5048 list = g_list_append (list, klass);
5049 /* and replace Type with NULL */
5050 mono_array_setref (res, i, NULL);
5057 if (list || ex_count) {
5059 MonoException *exc = NULL;
5060 MonoArray *exl = NULL;
5061 int j, length = g_list_length (list) + ex_count;
5063 mono_loader_clear_error ();
5065 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5066 /* Types for which mono_class_get_checked () succeeded */
5067 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5068 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5069 mono_array_setref (exl, i, exc);
5071 /* Types for which it don't */
5072 for (j = 0; j < mono_array_length (exceptions); ++j) {
5073 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5075 g_assert (i < length);
5076 mono_array_setref (exl, i, exc);
5083 exc = mono_get_exception_reflection_type_load (res, exl);
5084 mono_loader_clear_error ();
5085 mono_set_pending_exception (exc);
5092 ICALL_EXPORT gboolean
5093 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5095 MonoAssemblyName aname;
5096 MonoDomain *domain = mono_object_domain (name);
5098 gboolean is_version_defined;
5099 gboolean is_token_defined;
5101 aname.public_key = NULL;
5102 val = mono_string_to_utf8 (assname);
5103 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5104 g_free ((guint8*) aname.public_key);
5109 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5110 FALSE, is_token_defined);
5112 mono_assembly_name_free (&aname);
5113 g_free ((guint8*) aname.public_key);
5119 ICALL_EXPORT MonoReflectionType*
5120 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5123 MonoDomain *domain = mono_object_domain (module);
5126 g_assert (module->image);
5128 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5129 /* These images do not have a global type */
5132 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5133 mono_error_raise_exception (&error);
5134 return mono_type_get_object (domain, &klass->byval_arg);
5138 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5140 /*if (module->image)
5141 mono_image_close (module->image);*/
5144 ICALL_EXPORT MonoString*
5145 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5147 MonoDomain *domain = mono_object_domain (module);
5149 g_assert (module->image);
5150 return mono_string_new (domain, module->image->guid);
5153 ICALL_EXPORT gpointer
5154 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5157 if (module->image && module->image->is_module_handle)
5158 return module->image->raw_data;
5161 return (gpointer) (-1);
5165 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5167 if (image_is_dynamic (image)) {
5168 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5169 *pe_kind = dyn->pe_kind;
5170 *machine = dyn->machine;
5173 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5174 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5179 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5181 return (image->md_version_major << 16) | (image->md_version_minor);
5184 ICALL_EXPORT MonoArray*
5185 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5187 MonoArray *exceptions;
5191 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5193 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5194 for (i = 0; i < mono_array_length (exceptions); ++i) {
5195 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5197 mono_set_pending_exception (ex);
5206 mono_memberref_is_method (MonoImage *image, guint32 token)
5208 if (!image_is_dynamic (image)) {
5209 guint32 cols [MONO_MEMBERREF_SIZE];
5211 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5212 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5213 mono_metadata_decode_blob_size (sig, &sig);
5214 return (*sig != 0x6);
5216 MonoClass *handle_class;
5218 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5221 return mono_defaults.methodhandle_class == handle_class;
5226 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5229 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5230 mono_array_addr (type_args, MonoType*, 0));
5232 context->class_inst = NULL;
5234 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5235 mono_array_addr (method_args, MonoType*, 0));
5237 context->method_inst = NULL;
5240 ICALL_EXPORT MonoType*
5241 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5244 int table = mono_metadata_token_table (token);
5245 int index = mono_metadata_token_index (token);
5246 MonoGenericContext context;
5249 *resolve_error = ResolveTokenError_Other;
5251 /* Validate token */
5252 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5253 (table != MONO_TABLE_TYPESPEC)) {
5254 *resolve_error = ResolveTokenError_BadTable;
5258 if (image_is_dynamic (image)) {
5259 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5260 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5261 return klass ? &klass->byval_arg : NULL;
5264 init_generic_context_from_args (&context, type_args, method_args);
5265 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5266 return klass ? &klass->byval_arg : NULL;
5269 if ((index <= 0) || (index > image->tables [table].rows)) {
5270 *resolve_error = ResolveTokenError_OutOfRange;
5274 init_generic_context_from_args (&context, type_args, method_args);
5275 klass = mono_class_get_checked (image, token, &error);
5277 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5278 mono_error_raise_exception (&error);
5281 return &klass->byval_arg;
5286 ICALL_EXPORT MonoMethod*
5287 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5290 int table = mono_metadata_token_table (token);
5291 int index = mono_metadata_token_index (token);
5292 MonoGenericContext context;
5295 *resolve_error = ResolveTokenError_Other;
5297 /* Validate token */
5298 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5299 (table != MONO_TABLE_MEMBERREF)) {
5300 *resolve_error = ResolveTokenError_BadTable;
5304 if (image_is_dynamic (image)) {
5305 if (table == MONO_TABLE_METHOD)
5306 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5308 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5309 *resolve_error = ResolveTokenError_BadTable;
5313 init_generic_context_from_args (&context, type_args, method_args);
5314 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5317 if ((index <= 0) || (index > image->tables [table].rows)) {
5318 *resolve_error = ResolveTokenError_OutOfRange;
5321 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5322 *resolve_error = ResolveTokenError_BadTable;
5326 init_generic_context_from_args (&context, type_args, method_args);
5327 method = mono_get_method_checked (image, token, NULL, &context, &error);
5328 mono_error_raise_exception (&error);
5333 ICALL_EXPORT MonoString*
5334 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5336 int index = mono_metadata_token_index (token);
5338 *error = ResolveTokenError_Other;
5340 /* Validate token */
5341 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5342 *error = ResolveTokenError_BadTable;
5346 if (image_is_dynamic (image))
5347 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5349 if ((index <= 0) || (index >= image->heap_us.size)) {
5350 *error = ResolveTokenError_OutOfRange;
5354 /* FIXME: What to do if the index points into the middle of a string ? */
5356 return mono_ldstr (mono_domain_get (), image, index);
5359 ICALL_EXPORT MonoClassField*
5360 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5364 int table = mono_metadata_token_table (token);
5365 int index = mono_metadata_token_index (token);
5366 MonoGenericContext context;
5367 MonoClassField *field;
5369 *resolve_error = ResolveTokenError_Other;
5371 /* Validate token */
5372 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5373 *resolve_error = ResolveTokenError_BadTable;
5377 if (image_is_dynamic (image)) {
5378 if (table == MONO_TABLE_FIELD)
5379 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5381 if (mono_memberref_is_method (image, token)) {
5382 *resolve_error = ResolveTokenError_BadTable;
5386 init_generic_context_from_args (&context, type_args, method_args);
5387 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5390 if ((index <= 0) || (index > image->tables [table].rows)) {
5391 *resolve_error = ResolveTokenError_OutOfRange;
5394 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5395 *resolve_error = ResolveTokenError_BadTable;
5399 init_generic_context_from_args (&context, type_args, method_args);
5400 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5401 mono_error_raise_exception (&error);
5407 ICALL_EXPORT MonoObject*
5408 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5410 int table = mono_metadata_token_table (token);
5412 *error = ResolveTokenError_Other;
5415 case MONO_TABLE_TYPEDEF:
5416 case MONO_TABLE_TYPEREF:
5417 case MONO_TABLE_TYPESPEC: {
5418 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5420 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5424 case MONO_TABLE_METHOD:
5425 case MONO_TABLE_METHODSPEC: {
5426 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5428 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5432 case MONO_TABLE_FIELD: {
5433 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5435 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5439 case MONO_TABLE_MEMBERREF:
5440 if (mono_memberref_is_method (image, token)) {
5441 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5443 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5448 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5450 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5457 *error = ResolveTokenError_BadTable;
5463 ICALL_EXPORT MonoArray*
5464 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5466 int table = mono_metadata_token_table (token);
5467 int idx = mono_metadata_token_index (token);
5468 MonoTableInfo *tables = image->tables;
5473 *error = ResolveTokenError_OutOfRange;
5475 /* FIXME: Support other tables ? */
5476 if (table != MONO_TABLE_STANDALONESIG)
5479 if (image_is_dynamic (image))
5482 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5485 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5487 ptr = mono_metadata_blob_heap (image, sig);
5488 len = mono_metadata_decode_blob_size (ptr, &ptr);
5490 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5491 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5495 ICALL_EXPORT MonoReflectionType*
5496 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5499 int isbyref = 0, rank;
5500 char *str = mono_string_to_utf8 (smodifiers);
5503 klass = mono_class_from_mono_type (tb->type.type);
5505 /* logic taken from mono_reflection_parse_type(): keep in sync */
5509 if (isbyref) { /* only one level allowed by the spec */
5516 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5519 klass = mono_ptr_class_get (&klass->byval_arg);
5520 mono_class_init (klass);
5531 else if (*p != '*') { /* '*' means unknown lower bound */
5542 klass = mono_array_class_get (klass, rank);
5543 mono_class_init (klass);
5550 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5553 ICALL_EXPORT MonoBoolean
5554 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5560 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5566 check_for_invalid_type (MonoClass *klass)
5570 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5573 name = mono_type_get_full_name (klass);
5574 str = mono_string_new (mono_domain_get (), name);
5576 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5579 ICALL_EXPORT MonoReflectionType *
5580 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5582 MonoClass *klass, *aklass;
5584 klass = mono_class_from_mono_type (type->type);
5585 check_for_invalid_type (klass);
5587 if (rank == 0) //single dimentional array
5588 aklass = mono_array_class_get (klass, 1);
5590 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5592 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5595 ICALL_EXPORT MonoReflectionType *
5596 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5600 klass = mono_class_from_mono_type (type->type);
5601 mono_class_init_or_throw (klass);
5602 check_for_invalid_type (klass);
5604 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5607 ICALL_EXPORT MonoReflectionType *
5608 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5610 MonoClass *klass, *pklass;
5612 klass = mono_class_from_mono_type (type->type);
5613 mono_class_init_or_throw (klass);
5614 check_for_invalid_type (klass);
5616 pklass = mono_ptr_class_get (type->type);
5618 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5621 ICALL_EXPORT MonoObject *
5622 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5623 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5625 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5626 MonoObject *delegate;
5628 MonoMethod *method = info->method;
5630 mono_class_init_or_throw (delegate_class);
5632 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5634 if (mono_security_core_clr_enabled ()) {
5635 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5639 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5641 if (method_is_dynamic (method)) {
5642 /* Creating a trampoline would leak memory */
5643 func = mono_compile_method (method);
5645 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5646 method = mono_object_get_virtual_method (target, method);
5647 func = mono_create_ftnptr (mono_domain_get (),
5648 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5651 mono_delegate_ctor_with_method (delegate, target, func, method);
5656 ICALL_EXPORT MonoMulticastDelegate *
5657 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
5659 MonoMulticastDelegate *ret;
5661 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
5663 ret = (MonoMulticastDelegate*) mono_object_new (mono_object_domain (delegate), mono_object_class (delegate));
5664 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
5669 ICALL_EXPORT MonoReflectionMethod*
5670 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
5672 return mono_method_get_object (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target));
5677 static inline gint32
5678 mono_array_get_byte_length (MonoArray *array)
5684 klass = array->obj.vtable->klass;
5686 if (array->bounds == NULL)
5687 length = array->max_length;
5690 for (i = 0; i < klass->rank; ++ i)
5691 length *= array->bounds [i].length;
5694 switch (klass->element_class->byval_arg.type) {
5697 case MONO_TYPE_BOOLEAN:
5701 case MONO_TYPE_CHAR:
5709 return length * sizeof (gpointer);
5720 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
5722 return mono_array_get_byte_length (array);
5726 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
5728 return mono_array_get (array, gint8, idx);
5732 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
5734 mono_array_set (array, gint8, idx, value);
5737 ICALL_EXPORT MonoBoolean
5738 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
5740 guint8 *src_buf, *dest_buf;
5743 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
5747 g_assert (count >= 0);
5749 /* This is called directly from the class libraries without going through the managed wrapper */
5750 MONO_CHECK_ARG_NULL (src, FALSE);
5751 MONO_CHECK_ARG_NULL (dest, FALSE);
5753 /* watch out for integer overflow */
5754 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5757 src_buf = (guint8 *)src->vector + src_offset;
5758 dest_buf = (guint8 *)dest->vector + dest_offset;
5761 memcpy (dest_buf, src_buf, count);
5763 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5768 #ifndef DISABLE_REMOTING
5769 ICALL_EXPORT MonoObject *
5770 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
5772 MonoDomain *domain = mono_object_domain (this_obj);
5774 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
5775 MonoTransparentProxy *tp;
5779 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5780 tp = (MonoTransparentProxy*) res;
5782 MONO_OBJECT_SETREF (tp, rp, rp);
5783 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5784 klass = mono_class_from_mono_type (type);
5786 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
5787 mono_class_setup_vtable (klass);
5788 if (klass->exception_type)
5789 mono_raise_exception (mono_class_get_exception_for_failure (klass));
5791 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
5792 tp->remote_class = mono_remote_class (domain, class_name, klass);
5794 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
5798 ICALL_EXPORT MonoReflectionType *
5799 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5801 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5805 /* System.Environment */
5808 ves_icall_System_Environment_get_UserName (void)
5810 /* using glib is more portable */
5811 return mono_string_new (mono_domain_get (), g_get_user_name ());
5815 ICALL_EXPORT MonoString *
5816 ves_icall_System_Environment_get_MachineName (void)
5818 #if defined (HOST_WIN32)
5823 len = MAX_COMPUTERNAME_LENGTH + 1;
5824 buf = g_new (gunichar2, len);
5827 if (GetComputerName (buf, (PDWORD) &len))
5828 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5832 #elif !defined(DISABLE_SOCKETS)
5836 if (gethostname (buf, sizeof (buf)) == 0)
5837 result = mono_string_new (mono_domain_get (), buf);
5843 return mono_string_new (mono_domain_get (), "mono");
5848 ves_icall_System_Environment_get_Platform (void)
5850 #if defined (TARGET_WIN32)
5853 #elif defined(__MACH__)
5856 // Notice that the value is hidden from user code, and only exposed
5857 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
5858 // define and making assumptions based on Unix/128/4 values before there
5859 // was a MacOS define. Lots of code would assume that not-Unix meant
5860 // Windows, but in this case, it would be OSX.
5869 ICALL_EXPORT MonoString *
5870 ves_icall_System_Environment_get_NewLine (void)
5872 #if defined (HOST_WIN32)
5873 return mono_string_new (mono_domain_get (), "\r\n");
5875 return mono_string_new (mono_domain_get (), "\n");
5879 ICALL_EXPORT MonoString *
5880 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5888 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5889 value = g_getenv (utf8_name);
5896 return mono_string_new (mono_domain_get (), value);
5900 * There is no standard way to get at environ.
5903 #ifndef __MINGW32_VERSION
5904 #if defined(__APPLE__)
5905 #if defined (TARGET_OSX)
5906 /* Apple defines this in crt_externs.h but doesn't provide that header for
5907 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
5908 * in fact exist on all implementations (so far)
5910 gchar ***_NSGetEnviron(void);
5911 #define environ (*_NSGetEnviron())
5913 static char *mono_environ[1] = { NULL };
5914 #define environ mono_environ
5915 #endif /* defined (TARGET_OSX) */
5923 ICALL_EXPORT MonoArray *
5924 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
5935 env_strings = GetEnvironmentStrings();
5938 env_string = env_strings;
5939 while (*env_string != '\0') {
5940 /* weird case that MS seems to skip */
5941 if (*env_string != '=')
5943 while (*env_string != '\0')
5949 domain = mono_domain_get ();
5950 names = mono_array_new (domain, mono_defaults.string_class, n);
5954 env_string = env_strings;
5955 while (*env_string != '\0') {
5956 /* weird case that MS seems to skip */
5957 if (*env_string != '=') {
5958 equal_str = wcschr(env_string, '=');
5959 g_assert(equal_str);
5960 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
5961 mono_array_setref (names, n, str);
5964 while (*env_string != '\0')
5969 FreeEnvironmentStrings (env_strings);
5982 for (e = environ; *e != 0; ++ e)
5985 domain = mono_domain_get ();
5986 names = mono_array_new (domain, mono_defaults.string_class, n);
5989 for (e = environ; *e != 0; ++ e) {
5990 parts = g_strsplit (*e, "=", 2);
5992 str = mono_string_new (domain, *parts);
5993 mono_array_setref (names, n, str);
6006 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6008 #if !GLIB_CHECK_VERSION(2,4,0)
6009 #define g_setenv(a,b,c) setenv(a,b,c)
6010 #define g_unsetenv(a) unsetenv(a)
6014 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6017 gunichar2 *utf16_name, *utf16_value;
6019 gchar *utf8_name, *utf8_value;
6024 utf16_name = mono_string_to_utf16 (name);
6025 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6026 SetEnvironmentVariable (utf16_name, NULL);
6027 g_free (utf16_name);
6031 utf16_value = mono_string_to_utf16 (value);
6033 SetEnvironmentVariable (utf16_name, utf16_value);
6035 g_free (utf16_name);
6036 g_free (utf16_value);
6038 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6040 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6041 g_unsetenv (utf8_name);
6046 utf8_value = mono_string_to_utf8_checked (value, &error);
6047 if (!mono_error_ok (&error)) {
6049 mono_error_raise_exception (&error);
6051 g_setenv (utf8_name, utf8_value, TRUE);
6054 g_free (utf8_value);
6059 ves_icall_System_Environment_Exit (int result)
6061 mono_environment_exitcode_set (result);
6063 /* FIXME: There are some cleanup hangs that should be worked out, but
6064 * if the program is going to exit, everything will be cleaned up when
6065 * NaCl exits anyway.
6067 #ifndef __native_client__
6068 if (!mono_runtime_try_shutdown ())
6069 mono_thread_exit ();
6071 /* Suspend all managed threads since the runtime is going away */
6072 mono_thread_suspend_all_other_threads ();
6074 mono_runtime_quit ();
6077 /* we may need to do some cleanup here... */
6081 ICALL_EXPORT MonoString*
6082 ves_icall_System_Environment_GetGacPath (void)
6084 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6087 ICALL_EXPORT MonoString*
6088 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6090 #if defined (HOST_WIN32)
6091 #ifndef CSIDL_FLAG_CREATE
6092 #define CSIDL_FLAG_CREATE 0x8000
6095 WCHAR path [MAX_PATH];
6096 /* Create directory if no existing */
6097 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6101 return mono_string_new_utf16 (mono_domain_get (), path, len);
6104 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6106 return mono_string_new (mono_domain_get (), "");
6109 ICALL_EXPORT MonoArray *
6110 ves_icall_System_Environment_GetLogicalDrives (void)
6112 gunichar2 buf [256], *ptr, *dname;
6114 guint initial_size = 127, size = 128;
6117 MonoString *drivestr;
6118 MonoDomain *domain = mono_domain_get ();
6124 while (size > initial_size) {
6125 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6126 if (size > initial_size) {
6129 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6130 initial_size = size;
6144 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6149 while (*u16) { u16++; len ++; }
6150 drivestr = mono_string_new_utf16 (domain, dname, len);
6151 mono_array_setref (result, ndrives++, drivestr);
6161 ICALL_EXPORT MonoString *
6162 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6164 gunichar2 volume_name [MAX_PATH + 1];
6166 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6168 return mono_string_from_utf16 (volume_name);
6171 ICALL_EXPORT MonoString *
6172 ves_icall_System_Environment_InternalGetHome (void)
6174 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6177 static const char *encodings [] = {
6179 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6180 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6181 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6183 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6184 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6185 "x_unicode_2_0_utf_7",
6187 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6188 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6190 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6193 "unicodefffe", "utf_16be",
6200 * Returns the internal codepage, if the value of "int_code_page" is
6201 * 1 at entry, and we can not compute a suitable code page number,
6202 * returns the code page as a string
6204 ICALL_EXPORT MonoString*
6205 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6210 char *codepage = NULL;
6212 int want_name = *int_code_page;
6215 *int_code_page = -1;
6217 g_get_charset (&cset);
6218 c = codepage = strdup (cset);
6219 for (c = codepage; *c; c++){
6220 if (isascii (*c) && isalpha (*c))
6225 /* g_print ("charset: %s\n", cset); */
6227 /* handle some common aliases */
6230 for (i = 0; p != 0; ){
6233 p = encodings [++i];
6236 if (strcmp (p, codepage) == 0){
6237 *int_code_page = code;
6240 p = encodings [++i];
6243 if (strstr (codepage, "utf_8") != NULL)
6244 *int_code_page |= 0x10000000;
6247 if (want_name && *int_code_page == -1)
6248 return mono_string_new (mono_domain_get (), cset);
6253 ICALL_EXPORT MonoBoolean
6254 ves_icall_System_Environment_get_HasShutdownStarted (void)
6256 if (mono_runtime_is_shutting_down ())
6259 if (mono_domain_is_unloading (mono_domain_get ()))
6266 ves_icall_System_Environment_BroadcastSettingChange (void)
6269 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6274 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6280 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6281 MonoReflectionMethod *method,
6282 MonoArray *out_args)
6284 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6287 #ifndef DISABLE_REMOTING
6288 ICALL_EXPORT MonoBoolean
6289 ves_icall_IsTransparentProxy (MonoObject *proxy)
6294 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6300 ICALL_EXPORT MonoReflectionMethod *
6301 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6302 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6306 MonoMethod **vtable;
6307 MonoMethod *res = NULL;
6309 MONO_CHECK_ARG_NULL (rtype, NULL);
6310 MONO_CHECK_ARG_NULL (rmethod, NULL);
6312 method = rmethod->method;
6313 klass = mono_class_from_mono_type (rtype->type);
6314 mono_class_init_or_throw (klass);
6316 if (MONO_CLASS_IS_INTERFACE (klass))
6319 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6322 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6323 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6329 mono_class_setup_vtable (klass);
6330 vtable = klass->vtable;
6332 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6333 gboolean variance_used = FALSE;
6334 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6335 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6337 res = vtable [offs + method->slot];
6339 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6342 if (method->slot != -1)
6343 res = vtable [method->slot];
6349 return mono_method_get_object (mono_domain_get (), res, NULL);
6353 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6358 klass = mono_class_from_mono_type (type->type);
6359 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6361 mono_vtable_set_is_remote (vtable, enable);
6364 #else /* DISABLE_REMOTING */
6367 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6369 g_assert_not_reached ();
6374 ICALL_EXPORT MonoObject *
6375 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6380 domain = mono_object_domain (type);
6381 klass = mono_class_from_mono_type (type->type);
6382 mono_class_init_or_throw (klass);
6384 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6385 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6389 if (klass->rank >= 1) {
6390 g_assert (klass->rank == 1);
6391 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6393 /* Bypass remoting object creation check */
6394 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6398 ICALL_EXPORT MonoString *
6399 ves_icall_System_IO_get_temp_path (void)
6401 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6404 #ifndef PLATFORM_NO_DRIVEINFO
6405 ICALL_EXPORT MonoBoolean
6406 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6407 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6411 ULARGE_INTEGER wapi_free_bytes_avail;
6412 ULARGE_INTEGER wapi_total_number_of_bytes;
6413 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6415 *error = ERROR_SUCCESS;
6416 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6417 &wapi_total_number_of_free_bytes);
6420 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6421 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6422 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6424 *free_bytes_avail = 0;
6425 *total_number_of_bytes = 0;
6426 *total_number_of_free_bytes = 0;
6427 *error = GetLastError ();
6433 ICALL_EXPORT guint32
6434 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6436 return GetDriveType (mono_string_chars (root_path_name));
6440 ICALL_EXPORT gpointer
6441 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6443 return mono_compile_method (method);
6446 ICALL_EXPORT MonoString *
6447 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6452 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6454 #if defined (HOST_WIN32)
6455 /* Avoid mixing '/' and '\\' */
6458 for (i = strlen (path) - 1; i >= 0; i--)
6459 if (path [i] == '/')
6463 mcpath = mono_string_new (mono_domain_get (), path);
6470 get_bundled_app_config (void)
6472 const gchar *app_config;
6475 gchar *config_file_name, *config_file_path;
6476 gsize len, config_file_path_length, config_ext_length;
6479 domain = mono_domain_get ();
6480 file = domain->setup->configuration_file;
6481 if (!file || file->length == 0)
6484 // Retrieve config file and remove the extension
6485 config_file_name = mono_string_to_utf8 (file);
6486 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6487 if (!config_file_path)
6488 config_file_path = config_file_name;
6490 config_file_path_length = strlen (config_file_path);
6491 config_ext_length = strlen (".config");
6492 if (config_file_path_length <= config_ext_length)
6495 len = config_file_path_length - config_ext_length;
6496 module = (gchar *)g_malloc0 (len + 1);
6497 memcpy (module, config_file_path, len);
6498 // Get the config file from the module name
6499 app_config = mono_config_string_for_assembly_file (module);
6502 if (config_file_name != config_file_path)
6503 g_free (config_file_name);
6504 g_free (config_file_path);
6509 return mono_string_new (mono_domain_get (), app_config);
6513 get_bundled_machine_config (void)
6515 const gchar *machine_config;
6517 machine_config = mono_get_machine_config ();
6519 if (!machine_config)
6522 return mono_string_new (mono_domain_get (), machine_config);
6525 ICALL_EXPORT MonoString *
6526 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6531 path = g_path_get_dirname (mono_get_config_dir ());
6533 #if defined (HOST_WIN32)
6534 /* Avoid mixing '/' and '\\' */
6537 for (i = strlen (path) - 1; i >= 0; i--)
6538 if (path [i] == '/')
6542 ipath = mono_string_new (mono_domain_get (), path);
6548 ICALL_EXPORT gboolean
6549 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6551 MonoPEResourceDataEntry *entry;
6554 if (!assembly || !result || !size)
6559 image = assembly->assembly->image;
6560 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6564 *result = mono_image_rva_map (image, entry->rde_data_offset);
6569 *size = entry->rde_size;
6574 ICALL_EXPORT MonoBoolean
6575 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6577 return mono_is_debugger_attached ();
6580 ICALL_EXPORT MonoBoolean
6581 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
6583 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
6584 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
6590 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
6592 if (mono_get_runtime_callbacks ()->debug_log)
6593 mono_get_runtime_callbacks ()->debug_log (level, category, message);
6597 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6599 #if defined (HOST_WIN32)
6600 OutputDebugString (mono_string_chars (message));
6602 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6606 /* Only used for value types */
6607 ICALL_EXPORT MonoObject *
6608 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6613 domain = mono_object_domain (type);
6614 klass = mono_class_from_mono_type (type->type);
6615 mono_class_init_or_throw (klass);
6617 if (mono_class_is_nullable (klass))
6618 /* No arguments -> null */
6621 return mono_object_new (domain, klass);
6624 ICALL_EXPORT MonoReflectionMethod *
6625 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6627 MonoClass *klass, *parent;
6628 MonoGenericContext *generic_inst = NULL;
6629 MonoMethod *method = m->method;
6630 MonoMethod *result = NULL;
6633 if (method->klass == NULL)
6636 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6637 MONO_CLASS_IS_INTERFACE (method->klass) ||
6638 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6641 slot = mono_method_get_vtable_slot (method);
6645 klass = method->klass;
6646 if (klass->generic_class) {
6647 generic_inst = mono_class_get_context (klass);
6648 klass = klass->generic_class->container_class;
6652 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6653 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6654 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6655 or klass is the generic container class and generic_inst is the instantiation.
6657 when we go to the parent, if the parent is an open constructed type, we need to
6658 replace the type parameters by the definitions from the generic_inst, and then take it
6659 apart again into the klass and the generic_inst.
6661 For cases like this:
6662 class C<T> : B<T, int> {
6663 public override void Foo () { ... }
6665 class B<U,V> : A<HashMap<U,V>> {
6666 public override void Foo () { ... }
6669 public virtual void Foo () { ... }
6672 if at each iteration the parent isn't open, we can skip inflating it. if at some
6673 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6676 MonoGenericContext *parent_inst = NULL;
6677 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
6679 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
6680 mono_error_raise_exception(&error);
6682 if (parent->generic_class) {
6683 parent_inst = mono_class_get_context (parent);
6684 parent = parent->generic_class->container_class;
6687 mono_class_setup_vtable (parent);
6688 if (parent->vtable_size <= slot)
6691 generic_inst = parent_inst;
6694 klass = klass->parent;
6697 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
6699 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6700 mono_error_raise_exception(&error);
6702 generic_inst = NULL;
6704 if (klass->generic_class) {
6705 generic_inst = mono_class_get_context (klass);
6706 klass = klass->generic_class->container_class;
6713 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6714 mono_error_raise_exception(&error);
6717 if (klass == method->klass)
6720 /*This is possible if definition == FALSE.
6721 * Do it here to be really sure we don't read invalid memory.
6723 if (slot >= klass->vtable_size)
6726 mono_class_setup_vtable (klass);
6728 result = klass->vtable [slot];
6729 if (result == NULL) {
6730 /* It is an abstract method */
6731 gpointer iter = NULL;
6732 while ((result = mono_class_get_methods (klass, &iter)))
6733 if (result->slot == slot)
6740 return mono_method_get_object (mono_domain_get (), result, NULL);
6743 ICALL_EXPORT MonoString*
6744 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6746 MonoMethod *method = m->method;
6748 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6753 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6755 iter->sig = *(MonoMethodSignature**)argsp;
6757 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6758 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6761 /* FIXME: it's not documented what start is exactly... */
6765 iter->args = argsp + sizeof (gpointer);
6767 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6769 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6772 ICALL_EXPORT MonoTypedRef
6773 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6775 guint32 i, arg_size;
6779 i = iter->sig->sentinelpos + iter->next_arg;
6781 g_assert (i < iter->sig->param_count);
6783 res.type = iter->sig->params [i];
6784 res.klass = mono_class_from_mono_type (res.type);
6785 arg_size = mono_type_stack_size (res.type, &align);
6786 #if defined(__arm__) || defined(__mips__)
6787 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6789 res.value = iter->args;
6790 #if defined(__native_client__) && SIZEOF_REGISTER == 8
6791 /* Values are stored as 8 byte register sized objects, but 'value'
6792 * is dereferenced as a pointer in other routines.
6794 res.value = (char*)res.value + 4;
6796 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6797 if (arg_size <= sizeof (gpointer)) {
6799 int padding = arg_size - mono_type_size (res.type, &dummy);
6800 res.value = (guint8*)res.value + padding;
6803 iter->args = (char*)iter->args + arg_size;
6806 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6811 ICALL_EXPORT MonoTypedRef
6812 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6814 guint32 i, arg_size;
6818 i = iter->sig->sentinelpos + iter->next_arg;
6820 g_assert (i < iter->sig->param_count);
6822 while (i < iter->sig->param_count) {
6823 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6825 res.type = iter->sig->params [i];
6826 res.klass = mono_class_from_mono_type (res.type);
6827 /* FIXME: endianess issue... */
6828 arg_size = mono_type_stack_size (res.type, &align);
6829 #if defined(__arm__) || defined(__mips__)
6830 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6832 res.value = iter->args;
6833 iter->args = (char*)iter->args + arg_size;
6835 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6838 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6846 ICALL_EXPORT MonoType*
6847 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6851 i = iter->sig->sentinelpos + iter->next_arg;
6853 g_assert (i < iter->sig->param_count);
6855 return iter->sig->params [i];
6858 ICALL_EXPORT MonoObject*
6859 mono_TypedReference_ToObject (MonoTypedRef* tref)
6861 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
6862 MonoObject** objp = (MonoObject **)tref->value;
6866 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
6869 ICALL_EXPORT MonoTypedRef
6870 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
6873 MonoReflectionField *f;
6875 MonoType *ftype = NULL;
6879 memset (&res, 0, sizeof (res));
6882 g_assert (mono_array_length (fields) > 0);
6884 klass = target->vtable->klass;
6886 for (i = 0; i < mono_array_length (fields); ++i) {
6887 f = mono_array_get (fields, MonoReflectionField*, i);
6889 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
6892 if (f->field->parent != klass) {
6893 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
6897 p = (guint8*)target + f->field->offset;
6899 p += f->field->offset - sizeof (MonoObject);
6900 klass = mono_class_from_mono_type (f->field->type);
6901 ftype = f->field->type;
6905 res.klass = mono_class_from_mono_type (ftype);
6912 prelink_method (MonoMethod *method)
6914 const char *exc_class, *exc_arg;
6915 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6917 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6919 mono_raise_exception(
6920 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6922 /* create the wrapper, too? */
6926 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6928 prelink_method (method->method);
6932 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6934 MonoClass *klass = mono_class_from_mono_type (type->type);
6936 gpointer iter = NULL;
6938 mono_class_init_or_throw (klass);
6940 while ((m = mono_class_get_methods (klass, &iter)))
6944 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
6946 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
6947 gint32 const **exponents,
6948 gunichar2 const **digitLowerTable,
6949 gunichar2 const **digitUpperTable,
6950 gint64 const **tenPowersList,
6951 gint32 const **decHexDigits)
6953 *mantissas = Formatter_MantissaBitsTable;
6954 *exponents = Formatter_TensExponentTable;
6955 *digitLowerTable = Formatter_DigitLowerTable;
6956 *digitUpperTable = Formatter_DigitUpperTable;
6957 *tenPowersList = Formatter_TenPowersList;
6958 *decHexDigits = Formatter_DecHexDigits;
6962 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
6963 * and avoid useless allocations.
6968 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
6972 for (i = 0; i < type->num_mods; ++i) {
6973 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
6978 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
6980 for (i = 0; i < type->num_mods; ++i) {
6981 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
6983 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
6984 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
6985 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
6992 ICALL_EXPORT MonoArray*
6993 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
6995 MonoType *type = param->ClassImpl->type;
6996 MonoClass *member_class = mono_object_class (param->MemberImpl);
6997 MonoMethod *method = NULL;
7000 MonoMethodSignature *sig;
7002 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7003 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7004 method = rmethod->method;
7005 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7006 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7007 if (!(method = prop->property->get))
7008 method = prop->property->set;
7011 char *type_name = mono_type_get_full_name (member_class);
7012 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7013 MonoException *ex = mono_get_exception_not_supported (msg);
7016 mono_set_pending_exception (ex);
7020 image = method->klass->image;
7021 pos = param->PositionImpl;
7022 sig = mono_method_signature (method);
7026 type = sig->params [pos];
7028 return type_array_from_modifiers (image, type, optional);
7032 get_property_type (MonoProperty *prop)
7034 MonoMethodSignature *sig;
7036 sig = mono_method_signature (prop->get);
7038 } else if (prop->set) {
7039 sig = mono_method_signature (prop->set);
7040 return sig->params [sig->param_count - 1];
7045 ICALL_EXPORT MonoArray*
7046 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7048 MonoType *type = get_property_type (property->property);
7049 MonoImage *image = property->klass->image;
7053 return type_array_from_modifiers (image, type, optional);
7057 *Construct a MonoType suited to be used to decode a constant blob object.
7059 * @type is the target type which will be constructed
7060 * @blob_type is the blob type, for example, that comes from the constant table
7061 * @real_type is the expected constructed type.
7064 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7066 type->type = blob_type;
7067 type->data.klass = NULL;
7068 if (blob_type == MONO_TYPE_CLASS)
7069 type->data.klass = mono_defaults.object_class;
7070 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7071 /* For enums, we need to use the base type */
7072 type->type = MONO_TYPE_VALUETYPE;
7073 type->data.klass = mono_class_from_mono_type (real_type);
7075 type->data.klass = mono_class_from_mono_type (real_type);
7078 ICALL_EXPORT MonoObject*
7079 property_info_get_default_value (MonoReflectionProperty *property)
7082 MonoProperty *prop = property->property;
7083 MonoType *type = get_property_type (prop);
7084 MonoDomain *domain = mono_object_domain (property);
7085 MonoTypeEnum def_type;
7086 const char *def_value;
7089 mono_class_init (prop->parent);
7091 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7092 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7096 def_value = mono_class_get_property_default_value (prop, &def_type);
7098 mono_type_from_blob_type (&blob_type, def_type, type);
7099 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7104 ICALL_EXPORT MonoBoolean
7105 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7107 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7108 MonoCustomAttrInfo *cinfo;
7111 mono_class_init_or_throw (attr_class);
7113 cinfo = mono_reflection_get_custom_attrs_info (obj);
7116 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7118 mono_custom_attrs_free (cinfo);
7122 ICALL_EXPORT MonoArray*
7123 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7125 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7130 mono_class_init_or_throw (attr_class);
7132 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7133 mono_error_raise_exception (&error);
7135 if (mono_loader_get_last_error ()) {
7136 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7143 ICALL_EXPORT MonoString*
7144 ves_icall_Mono_Runtime_GetDisplayName (void)
7147 MonoString *display_name;
7149 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7150 display_name = mono_string_new (mono_domain_get (), info);
7152 return display_name;
7155 ICALL_EXPORT MonoString*
7156 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7158 MonoString *message;
7162 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7163 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7166 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7168 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7175 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7178 char *path_str = mono_string_to_utf8 (path);
7180 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7188 #ifndef DISABLE_ICALL_TABLES
7190 #define ICALL_TYPE(id,name,first)
7191 #define ICALL(id,name,func) Icall_ ## id,
7194 #include "metadata/icall-def.h"
7200 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7201 #define ICALL(id,name,func)
7203 #include "metadata/icall-def.h"
7209 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7210 #define ICALL(id,name,func)
7212 guint16 first_icall;
7215 static const IcallTypeDesc
7216 icall_type_descs [] = {
7217 #include "metadata/icall-def.h"
7221 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7224 #define ICALL_TYPE(id,name,first)
7227 #ifdef HAVE_ARRAY_ELEM_INIT
7228 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7229 #define MSGSTRFIELD1(line) str##line
7231 static const struct msgstrtn_t {
7232 #define ICALL(id,name,func)
7234 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7235 #include "metadata/icall-def.h"
7237 } icall_type_names_str = {
7238 #define ICALL_TYPE(id,name,first) (name),
7239 #include "metadata/icall-def.h"
7242 static const guint16 icall_type_names_idx [] = {
7243 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7244 #include "metadata/icall-def.h"
7247 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7249 static const struct msgstr_t {
7251 #define ICALL_TYPE(id,name,first)
7252 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7253 #include "metadata/icall-def.h"
7255 } icall_names_str = {
7256 #define ICALL(id,name,func) (name),
7257 #include "metadata/icall-def.h"
7260 static const guint16 icall_names_idx [] = {
7261 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7262 #include "metadata/icall-def.h"
7265 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7271 #define ICALL_TYPE(id,name,first) name,
7272 #define ICALL(id,name,func)
7273 static const char* const
7274 icall_type_names [] = {
7275 #include "metadata/icall-def.h"
7279 #define icall_type_name_get(id) (icall_type_names [(id)])
7283 #define ICALL_TYPE(id,name,first)
7284 #define ICALL(id,name,func) name,
7285 static const char* const
7287 #include "metadata/icall-def.h"
7290 #define icall_name_get(id) icall_names [(id)]
7292 #endif /* !HAVE_ARRAY_ELEM_INIT */
7296 #define ICALL_TYPE(id,name,first)
7297 #define ICALL(id,name,func) func,
7298 static const gconstpointer
7299 icall_functions [] = {
7300 #include "metadata/icall-def.h"
7304 #ifdef ENABLE_ICALL_SYMBOL_MAP
7307 #define ICALL_TYPE(id,name,first)
7308 #define ICALL(id,name,func) #func,
7309 static const gconstpointer
7310 icall_symbols [] = {
7311 #include "metadata/icall-def.h"
7316 #endif /* DISABLE_ICALL_TABLES */
7318 static mono_mutex_t icall_mutex;
7319 static GHashTable *icall_hash = NULL;
7320 static GHashTable *jit_icall_hash_name = NULL;
7321 static GHashTable *jit_icall_hash_addr = NULL;
7324 mono_icall_init (void)
7326 #ifndef DISABLE_ICALL_TABLES
7329 /* check that tables are sorted: disable in release */
7332 const char *prev_class = NULL;
7333 const char *prev_method;
7335 for (i = 0; i < Icall_type_num; ++i) {
7336 const IcallTypeDesc *desc;
7339 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7340 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7341 prev_class = icall_type_name_get (i);
7342 desc = &icall_type_descs [i];
7343 num_icalls = icall_desc_num_icalls (desc);
7344 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7345 for (j = 0; j < num_icalls; ++j) {
7346 const char *methodn = icall_name_get (desc->first_icall + j);
7347 if (prev_method && strcmp (prev_method, methodn) >= 0)
7348 g_print ("method %s should come before method %s\n", methodn, prev_method);
7349 prev_method = methodn;
7355 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7356 mono_os_mutex_init (&icall_mutex);
7360 mono_icall_lock (void)
7362 mono_locks_os_acquire (&icall_mutex, IcallLock);
7366 mono_icall_unlock (void)
7368 mono_locks_os_release (&icall_mutex, IcallLock);
7372 mono_icall_cleanup (void)
7374 g_hash_table_destroy (icall_hash);
7375 g_hash_table_destroy (jit_icall_hash_name);
7376 g_hash_table_destroy (jit_icall_hash_addr);
7377 mono_os_mutex_destroy (&icall_mutex);
7381 mono_add_internal_call (const char *name, gconstpointer method)
7385 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7387 mono_icall_unlock ();
7390 #ifndef DISABLE_ICALL_TABLES
7392 #ifdef HAVE_ARRAY_ELEM_INIT
7394 compare_method_imap (const void *key, const void *elem)
7396 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7397 return strcmp (key, method_name);
7401 find_method_icall (const IcallTypeDesc *imap, const char *name)
7403 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);
7406 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7410 compare_class_imap (const void *key, const void *elem)
7412 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7413 return strcmp (key, class_name);
7416 static const IcallTypeDesc*
7417 find_class_icalls (const char *name)
7419 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);
7422 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7425 #else /* HAVE_ARRAY_ELEM_INIT */
7428 compare_method_imap (const void *key, const void *elem)
7430 const char** method_name = (const char**)elem;
7431 return strcmp (key, *method_name);
7435 find_method_icall (const IcallTypeDesc *imap, const char *name)
7437 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7440 return (gpointer)icall_functions [(nameslot - icall_names)];
7444 compare_class_imap (const void *key, const void *elem)
7446 const char** class_name = (const char**)elem;
7447 return strcmp (key, *class_name);
7450 static const IcallTypeDesc*
7451 find_class_icalls (const char *name)
7453 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7456 return &icall_type_descs [nameslot - icall_type_names];
7459 #endif /* HAVE_ARRAY_ELEM_INIT */
7461 #endif /* DISABLE_ICALL_TABLES */
7464 * we should probably export this as an helper (handle nested types).
7465 * Returns the number of chars written in buf.
7468 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7470 int nspacelen, cnamelen;
7471 nspacelen = strlen (klass->name_space);
7472 cnamelen = strlen (klass->name);
7473 if (nspacelen + cnamelen + 2 > bufsize)
7476 memcpy (buf, klass->name_space, nspacelen);
7477 buf [nspacelen ++] = '.';
7479 memcpy (buf + nspacelen, klass->name, cnamelen);
7480 buf [nspacelen + cnamelen] = 0;
7481 return nspacelen + cnamelen;
7484 #ifdef DISABLE_ICALL_TABLES
7486 no_icall_table (void)
7488 g_assert_not_reached ();
7493 mono_lookup_internal_call (MonoMethod *method)
7498 int typelen = 0, mlen, siglen;
7500 #ifndef DISABLE_ICALL_TABLES
7501 const IcallTypeDesc *imap = NULL;
7504 g_assert (method != NULL);
7506 if (method->is_inflated)
7507 method = ((MonoMethodInflated *) method)->declaring;
7509 if (method->klass->nested_in) {
7510 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7514 mname [pos++] = '/';
7517 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7523 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7528 #ifndef DISABLE_ICALL_TABLES
7529 imap = find_class_icalls (mname);
7532 mname [typelen] = ':';
7533 mname [typelen + 1] = ':';
7535 mlen = strlen (method->name);
7536 memcpy (mname + typelen + 2, method->name, mlen);
7537 sigstart = mname + typelen + 2 + mlen;
7540 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7541 siglen = strlen (tmpsig);
7542 if (typelen + mlen + siglen + 6 > sizeof (mname))
7545 memcpy (sigstart + 1, tmpsig, siglen);
7546 sigstart [siglen + 1] = ')';
7547 sigstart [siglen + 2] = 0;
7552 res = g_hash_table_lookup (icall_hash, mname);
7554 mono_icall_unlock ();;
7557 /* try without signature */
7559 res = g_hash_table_lookup (icall_hash, mname);
7561 mono_icall_unlock ();
7565 #ifdef DISABLE_ICALL_TABLES
7566 mono_icall_unlock ();
7567 /* Fail only when the result is actually used */
7568 /* mono_marshal_get_native_wrapper () depends on this */
7569 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
7570 return ves_icall_System_String_ctor_RedirectToCreateString;
7572 return no_icall_table;
7574 /* it wasn't found in the static call tables */
7576 mono_icall_unlock ();
7579 res = find_method_icall (imap, sigstart - mlen);
7581 mono_icall_unlock ();
7584 /* try _with_ signature */
7586 res = find_method_icall (imap, sigstart - mlen);
7588 mono_icall_unlock ();
7592 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7593 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7594 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7595 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
7596 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");
7597 g_print ("If you see other errors or faults after this message they are probably related\n");
7598 g_print ("and you need to fix your mono install first.\n");
7600 mono_icall_unlock ();
7606 #ifdef ENABLE_ICALL_SYMBOL_MAP
7608 func_cmp (gconstpointer key, gconstpointer p)
7610 return (gsize)key - (gsize)*(gsize*)p;
7615 * mono_lookup_icall_symbol:
7617 * Given the icall METHOD, returns its C symbol.
7620 mono_lookup_icall_symbol (MonoMethod *m)
7622 #ifdef DISABLE_ICALL_TABLES
7623 g_assert_not_reached ();
7626 #ifdef ENABLE_ICALL_SYMBOL_MAP
7630 static gconstpointer *functions_sorted;
7631 static const char**symbols_sorted;
7632 static gboolean inited;
7637 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7638 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7639 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7640 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7641 /* Bubble sort the two arrays */
7645 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
7646 if (functions_sorted [i] > functions_sorted [i + 1]) {
7649 tmp = functions_sorted [i];
7650 functions_sorted [i] = functions_sorted [i + 1];
7651 functions_sorted [i + 1] = tmp;
7652 tmp = symbols_sorted [i];
7653 symbols_sorted [i] = symbols_sorted [i + 1];
7654 symbols_sorted [i + 1] = tmp;
7661 func = mono_lookup_internal_call (m);
7664 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
7668 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
7670 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
7671 g_assert_not_reached ();
7678 type_from_typename (char *type_name)
7680 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7682 if (!strcmp (type_name, "int"))
7683 klass = mono_defaults.int_class;
7684 else if (!strcmp (type_name, "ptr"))
7685 klass = mono_defaults.int_class;
7686 else if (!strcmp (type_name, "void"))
7687 klass = mono_defaults.void_class;
7688 else if (!strcmp (type_name, "int32"))
7689 klass = mono_defaults.int32_class;
7690 else if (!strcmp (type_name, "uint32"))
7691 klass = mono_defaults.uint32_class;
7692 else if (!strcmp (type_name, "int8"))
7693 klass = mono_defaults.sbyte_class;
7694 else if (!strcmp (type_name, "uint8"))
7695 klass = mono_defaults.byte_class;
7696 else if (!strcmp (type_name, "int16"))
7697 klass = mono_defaults.int16_class;
7698 else if (!strcmp (type_name, "uint16"))
7699 klass = mono_defaults.uint16_class;
7700 else if (!strcmp (type_name, "long"))
7701 klass = mono_defaults.int64_class;
7702 else if (!strcmp (type_name, "ulong"))
7703 klass = mono_defaults.uint64_class;
7704 else if (!strcmp (type_name, "float"))
7705 klass = mono_defaults.single_class;
7706 else if (!strcmp (type_name, "double"))
7707 klass = mono_defaults.double_class;
7708 else if (!strcmp (type_name, "object"))
7709 klass = mono_defaults.object_class;
7710 else if (!strcmp (type_name, "obj"))
7711 klass = mono_defaults.object_class;
7712 else if (!strcmp (type_name, "string"))
7713 klass = mono_defaults.string_class;
7714 else if (!strcmp (type_name, "bool"))
7715 klass = mono_defaults.boolean_class;
7716 else if (!strcmp (type_name, "boolean"))
7717 klass = mono_defaults.boolean_class;
7719 g_error ("%s", type_name);
7720 g_assert_not_reached ();
7722 return &klass->byval_arg;
7726 * LOCKING: Take the corlib image lock.
7728 MonoMethodSignature*
7729 mono_create_icall_signature (const char *sigstr)
7734 MonoMethodSignature *res, *res2;
7735 MonoImage *corlib = mono_defaults.corlib;
7737 mono_image_lock (corlib);
7738 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7739 mono_image_unlock (corlib);
7744 parts = g_strsplit (sigstr, " ", 256);
7753 res = mono_metadata_signature_alloc (corlib, len - 1);
7758 * Under windows, the default pinvoke calling convention is STDCALL but
7761 res->call_convention = MONO_CALL_C;
7764 res->ret = type_from_typename (parts [0]);
7765 for (i = 1; i < len; ++i) {
7766 res->params [i - 1] = type_from_typename (parts [i]);
7771 mono_image_lock (corlib);
7772 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7774 res = res2; /*Value is allocated in the image pool*/
7776 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
7777 mono_image_unlock (corlib);
7783 mono_find_jit_icall_by_name (const char *name)
7785 MonoJitICallInfo *info;
7786 g_assert (jit_icall_hash_name);
7789 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7790 mono_icall_unlock ();
7795 mono_find_jit_icall_by_addr (gconstpointer addr)
7797 MonoJitICallInfo *info;
7798 g_assert (jit_icall_hash_addr);
7801 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7802 mono_icall_unlock ();
7808 * mono_get_jit_icall_info:
7810 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7811 * caller should access it while holding the icall lock.
7814 mono_get_jit_icall_info (void)
7816 return jit_icall_hash_name;
7820 * mono_lookup_jit_icall_symbol:
7822 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
7825 mono_lookup_jit_icall_symbol (const char *name)
7827 MonoJitICallInfo *info;
7828 const char *res = NULL;
7831 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7833 res = info->c_symbol;
7834 mono_icall_unlock ();
7839 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7842 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7843 mono_icall_unlock ();
7847 * 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
7848 * icalls without wrappers in some cases.
7851 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
7853 MonoJitICallInfo *info;
7860 if (!jit_icall_hash_name) {
7861 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7862 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7865 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7866 g_warning ("jit icall already defined \"%s\"\n", name);
7867 g_assert_not_reached ();
7870 info = g_new0 (MonoJitICallInfo, 1);
7875 info->c_symbol = c_symbol;
7876 info->no_raise = no_raise;
7879 info->wrapper = func;
7881 info->wrapper = NULL;
7884 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7885 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7887 mono_icall_unlock ();
7892 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7894 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);