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 if (klass->generic_container)
885 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
887 /* This will call the type constructor */
888 mono_runtime_class_init (vtable);
892 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
896 mono_image_check_for_module_cctor (image);
897 if (image->has_module_cctor) {
898 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
899 mono_error_raise_exception (&error);
900 /*It's fine to raise the exception here*/
901 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
905 ICALL_EXPORT MonoBoolean
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
911 /* later make this configurable and per-arch */
912 int min_size = 4096 * 4 * sizeof (void*);
913 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
914 /* if we have no info we are optimistic and assume there is enough room */
918 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
922 current = (guint8 *)&stack_addr;
923 if (current > stack_addr) {
924 if ((current - stack_addr) < min_size)
927 if (current - (stack_addr - stack_size) < min_size)
933 ICALL_EXPORT MonoObject *
934 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
936 return mono_object_clone (this_obj);
940 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
943 MonoObject **values = NULL;
946 gint32 result = (int)(gsize)mono_defaults.int32_class;
947 MonoClassField* field;
950 klass = mono_object_class (this_obj);
952 if (mono_class_num_fields (klass) == 0)
956 * Compute the starting value of the hashcode for fields of primitive
957 * types, and return the remaining fields in an array to the managed side.
958 * This way, we can avoid costly reflection operations in managed code.
961 while ((field = mono_class_get_fields (klass, &iter))) {
962 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
964 if (mono_field_is_deleted (field))
966 /* FIXME: Add more types */
967 switch (field->type->type) {
969 result ^= *(gint32*)((guint8*)this_obj + field->offset);
971 case MONO_TYPE_STRING: {
973 s = *(MonoString**)((guint8*)this_obj + field->offset);
975 result ^= mono_string_hash (s);
980 values = g_newa (MonoObject*, mono_class_num_fields (klass));
981 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
982 values [count++] = o;
988 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
989 for (i = 0; i < count; ++i)
990 mono_array_setref (*fields, i, values [i]);
997 ICALL_EXPORT MonoBoolean
998 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1001 MonoObject **values = NULL;
1003 MonoClassField* field;
1007 MONO_CHECK_ARG_NULL (that, FALSE);
1009 if (this_obj->vtable != that->vtable)
1012 klass = mono_object_class (this_obj);
1014 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1015 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1018 * Do the comparison for fields of primitive type and return a result if
1019 * possible. Otherwise, return the remaining fields in an array to the
1020 * managed side. This way, we can avoid costly reflection operations in
1025 while ((field = mono_class_get_fields (klass, &iter))) {
1026 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1028 if (mono_field_is_deleted (field))
1030 /* FIXME: Add more types */
1031 switch (field->type->type) {
1034 case MONO_TYPE_BOOLEAN:
1035 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1040 case MONO_TYPE_CHAR:
1041 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1046 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1051 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1055 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1059 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1064 case MONO_TYPE_STRING: {
1065 MonoString *s1, *s2;
1066 guint32 s1len, s2len;
1067 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1068 s2 = *(MonoString**)((guint8*)that + field->offset);
1071 if ((s1 == NULL) || (s2 == NULL))
1073 s1len = mono_string_length (s1);
1074 s2len = mono_string_length (s2);
1078 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1084 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1085 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1086 values [count++] = o;
1087 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1088 values [count++] = o;
1091 if (klass->enumtype)
1092 /* enums only have one non-static field */
1098 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1099 for (i = 0; i < count; ++i)
1100 mono_array_setref_fast (*fields, i, values [i]);
1107 ICALL_EXPORT MonoReflectionType *
1108 ves_icall_System_Object_GetType (MonoObject *obj)
1110 #ifndef DISABLE_REMOTING
1111 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1112 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1115 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1119 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1121 mtype->type = &obj->vtable->klass->byval_arg;
1122 g_assert (mtype->type->type);
1126 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1128 MONO_CHECK_ARG_NULL (obj, 0);
1130 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1134 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1135 MonoReflectionMethod *method,
1136 MonoArray *opt_param_types)
1138 MONO_CHECK_ARG_NULL (method, 0);
1140 return mono_image_create_method_token (
1141 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1145 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1147 mono_image_create_pefile (mb, file);
1151 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1153 mono_image_build_metadata (mb);
1157 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1159 mono_image_register_token (mb->dynamic_image, token, obj);
1162 ICALL_EXPORT MonoObject*
1163 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1167 mono_loader_lock ();
1168 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1169 mono_loader_unlock ();
1175 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1177 MonoMethod **dest = (MonoMethod **)data;
1179 /* skip unmanaged frames */
1195 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1197 MonoMethod **dest = (MonoMethod **)data;
1199 /* skip unmanaged frames */
1204 if (!strcmp (m->klass->name_space, "System.Reflection"))
1213 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1215 MonoMethod **dest = (MonoMethod **)data;
1217 /* skip unmanaged frames */
1221 if (m->wrapper_type != MONO_WRAPPER_NONE)
1224 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1238 static MonoReflectionType *
1239 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1241 MonoMethod *m, *dest;
1243 MonoType *type = NULL;
1244 MonoAssembly *assembly = NULL;
1245 gboolean type_resolve = FALSE;
1248 * We must compute the calling assembly as type loading must happen under a metadata context.
1249 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1250 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1252 m = mono_method_get_last_managed ();
1255 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1260 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1261 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1262 * to crash. This only seems to happen in some strange remoting
1263 * scenarios and I was unable to figure out what's happening there.
1264 * Dec 10, 2005 - Martin.
1268 assembly = dest->klass->image->assembly;
1269 type_resolve = TRUE;
1271 g_warning (G_STRLOC);
1274 if (info->assembly.name)
1275 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1279 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1280 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1283 if (!info->assembly.name && !type) /* try mscorlib */
1284 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1286 if (assembly && !type && type_resolve) {
1287 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1288 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1294 return mono_type_get_object (mono_domain_get (), type);
1298 MonoReflectionType *
1299 mono_type_get (const char *str)
1301 char *copy = g_strdup (str);
1302 MonoTypeNameParse info;
1303 MonoReflectionType *type;
1306 parsedOk = mono_reflection_parse_type(copy, &info);
1308 mono_reflection_free_type_info (&info);
1313 type = type_from_parsed_name (&info, FALSE);
1315 mono_reflection_free_type_info (&info);
1322 ICALL_EXPORT MonoReflectionType*
1323 ves_icall_type_from_name (MonoString *name,
1324 MonoBoolean throwOnError,
1325 MonoBoolean ignoreCase)
1327 char *str = mono_string_to_utf8 (name);
1328 MonoTypeNameParse info;
1329 MonoReflectionType *type;
1332 parsedOk = mono_reflection_parse_type (str, &info);
1334 /* mono_reflection_parse_type() mangles the string */
1336 mono_reflection_free_type_info (&info);
1339 mono_set_pending_exception(mono_get_exception_argument("typeName", "failed parse"));
1344 type = type_from_parsed_name (&info, ignoreCase);
1346 mono_reflection_free_type_info (&info);
1350 MonoException *e = NULL;
1353 e = mono_get_exception_type_load (name, NULL);
1355 mono_loader_clear_error ();
1357 mono_set_pending_exception (e);
1366 ICALL_EXPORT MonoReflectionType*
1367 ves_icall_type_from_handle (MonoType *handle)
1369 MonoDomain *domain = mono_domain_get ();
1371 return mono_type_get_object (domain, handle);
1374 /* System.TypeCode */
1393 TYPECODE_STRING = 18
1396 ICALL_EXPORT guint32
1397 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1399 int t = type->type->type;
1401 if (type->type->byref)
1402 return TYPECODE_OBJECT;
1406 case MONO_TYPE_VOID:
1407 return TYPECODE_OBJECT;
1408 case MONO_TYPE_BOOLEAN:
1409 return TYPECODE_BOOLEAN;
1411 return TYPECODE_BYTE;
1413 return TYPECODE_SBYTE;
1415 return TYPECODE_UINT16;
1417 return TYPECODE_INT16;
1418 case MONO_TYPE_CHAR:
1419 return TYPECODE_CHAR;
1423 return TYPECODE_OBJECT;
1425 return TYPECODE_UINT32;
1427 return TYPECODE_INT32;
1429 return TYPECODE_UINT64;
1431 return TYPECODE_INT64;
1433 return TYPECODE_SINGLE;
1435 return TYPECODE_DOUBLE;
1436 case MONO_TYPE_VALUETYPE: {
1437 MonoClass *klass = type->type->data.klass;
1439 if (klass->enumtype) {
1440 t = mono_class_enum_basetype (klass)->type;
1442 } else if (mono_is_corlib_image (klass->image)) {
1443 if (strcmp (klass->name_space, "System") == 0) {
1444 if (strcmp (klass->name, "Decimal") == 0)
1445 return TYPECODE_DECIMAL;
1446 else if (strcmp (klass->name, "DateTime") == 0)
1447 return TYPECODE_DATETIME;
1450 return TYPECODE_OBJECT;
1452 case MONO_TYPE_STRING:
1453 return TYPECODE_STRING;
1454 case MONO_TYPE_SZARRAY:
1455 case MONO_TYPE_ARRAY:
1456 case MONO_TYPE_OBJECT:
1458 case MONO_TYPE_MVAR:
1459 case MONO_TYPE_TYPEDBYREF:
1460 return TYPECODE_OBJECT;
1461 case MONO_TYPE_CLASS:
1463 MonoClass *klass = type->type->data.klass;
1464 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1465 if (strcmp (klass->name, "DBNull") == 0)
1466 return TYPECODE_DBNULL;
1469 return TYPECODE_OBJECT;
1470 case MONO_TYPE_GENERICINST:
1471 return TYPECODE_OBJECT;
1473 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1479 mono_type_is_primitive (MonoType *type)
1481 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1482 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1486 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1488 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1489 return mono_class_enum_basetype (type->data.klass);
1490 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1491 return mono_class_enum_basetype (type->data.generic_class->container_class);
1495 ICALL_EXPORT guint32
1496 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1501 g_assert (type != NULL);
1503 klass = mono_class_from_mono_type (type->type);
1504 klassc = mono_class_from_mono_type (c->type);
1506 if (type->type->byref ^ c->type->byref)
1509 if (type->type->byref) {
1510 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1511 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1513 klass = mono_class_from_mono_type (t);
1514 klassc = mono_class_from_mono_type (ot);
1516 if (mono_type_is_primitive (t)) {
1517 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1518 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1519 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1520 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1521 return t->type == ot->type;
1523 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1526 if (klass->valuetype)
1527 return klass == klassc;
1528 return klass->valuetype == klassc->valuetype;
1531 return mono_class_is_assignable_from (klass, klassc);
1534 ICALL_EXPORT guint32
1535 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1537 MonoClass *klass = mono_class_from_mono_type (type->type);
1538 mono_class_init_or_throw (klass);
1539 return mono_object_isinst (obj, klass) != NULL;
1542 ICALL_EXPORT guint32
1543 ves_icall_get_attributes (MonoReflectionType *type)
1545 MonoClass *klass = mono_class_from_mono_type (type->type);
1546 return klass->flags;
1549 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1550 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1552 MonoClass *klass = field->field->parent;
1553 MonoMarshalType *info;
1557 if (klass->generic_container ||
1558 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1561 ftype = mono_field_get_type (field->field);
1562 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1565 info = mono_marshal_load_type_info (klass);
1567 for (i = 0; i < info->num_fields; ++i) {
1568 if (info->fields [i].field == field->field) {
1569 if (!info->fields [i].mspec)
1572 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1579 ICALL_EXPORT MonoReflectionField*
1580 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1582 gboolean found = FALSE;
1589 klass = handle->parent;
1591 klass = mono_class_from_mono_type (type);
1593 /* Check that the field belongs to the class */
1594 for (k = klass; k; k = k->parent) {
1595 if (k == handle->parent) {
1602 /* The managed code will throw the exception */
1606 return mono_field_get_object (mono_domain_get (), klass, handle);
1609 ICALL_EXPORT MonoArray*
1610 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1613 MonoType *type = mono_field_get_type_checked (field->field, &error);
1614 mono_error_raise_exception (&error);
1616 return type_array_from_modifiers (field->field->parent->image, type, optional);
1620 vell_icall_get_method_attributes (MonoMethod *method)
1622 return method->flags;
1626 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1629 MonoDomain *domain = mono_domain_get ();
1630 MonoMethodSignature* sig;
1632 sig = mono_method_signature_checked (method, &error);
1633 if (!mono_error_ok (&error))
1634 mono_error_raise_exception (&error);
1637 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1638 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1639 info->attrs = method->flags;
1640 info->implattrs = method->iflags;
1641 if (sig->call_convention == MONO_CALL_DEFAULT)
1642 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1644 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1649 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1652 ICALL_EXPORT MonoArray*
1653 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1655 MonoDomain *domain = mono_domain_get ();
1657 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1660 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1661 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1663 MonoDomain *domain = mono_domain_get ();
1664 MonoReflectionMarshalAsAttribute* res = NULL;
1665 MonoMarshalSpec **mspecs;
1668 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1669 mono_method_get_marshal_info (method, mspecs);
1672 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1674 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1676 mono_metadata_free_marshal_spec (mspecs [i]);
1683 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1685 MonoClass *parent = field->field->parent;
1686 if (!parent->size_inited)
1687 mono_class_init (parent);
1688 mono_class_setup_fields_locking (parent);
1690 return field->field->offset - sizeof (MonoObject);
1693 ICALL_EXPORT MonoReflectionType*
1694 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1698 parent = declaring? field->field->parent: field->klass;
1700 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1703 ICALL_EXPORT MonoObject *
1704 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1706 MonoClass *fklass = field->klass;
1707 MonoClassField *cf = field->field;
1708 MonoDomain *domain = mono_object_domain (field);
1710 if (fklass->image->assembly->ref_only) {
1711 mono_set_pending_exception (mono_get_exception_invalid_operation (
1712 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1716 if (mono_security_core_clr_enabled ())
1717 mono_security_core_clr_ensure_reflection_access_field (cf);
1719 return mono_field_get_value_object (domain, cf, obj);
1723 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1726 MonoClassField *cf = field->field;
1730 if (field->klass->image->assembly->ref_only) {
1731 mono_set_pending_exception (mono_get_exception_invalid_operation (
1732 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1736 if (mono_security_core_clr_enabled ())
1737 mono_security_core_clr_ensure_reflection_access_field (cf);
1739 type = mono_field_get_type_checked (cf, &error);
1740 if (!mono_error_ok (&error))
1741 mono_error_raise_exception (&error);
1743 v = (gchar *) value;
1745 switch (type->type) {
1748 case MONO_TYPE_BOOLEAN:
1751 case MONO_TYPE_CHAR:
1760 case MONO_TYPE_VALUETYPE:
1763 v += sizeof (MonoObject);
1765 case MONO_TYPE_STRING:
1766 case MONO_TYPE_OBJECT:
1767 case MONO_TYPE_CLASS:
1768 case MONO_TYPE_ARRAY:
1769 case MONO_TYPE_SZARRAY:
1772 case MONO_TYPE_GENERICINST: {
1773 MonoGenericClass *gclass = type->data.generic_class;
1774 g_assert (!gclass->context.class_inst->is_open);
1776 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1777 MonoClass *nklass = mono_class_from_mono_type (type);
1778 MonoObject *nullable;
1781 * Convert the boxed vtype into a Nullable structure.
1782 * This is complicated by the fact that Nullables have
1783 * a variable structure.
1785 nullable = mono_object_new (mono_domain_get (), nklass);
1787 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1789 v = (gchar *)mono_object_unbox (nullable);
1792 if (gclass->container_class->valuetype && (v != NULL))
1793 v += sizeof (MonoObject);
1797 g_error ("type 0x%x not handled in "
1798 "ves_icall_FieldInfo_SetValueInternal", type->type);
1803 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1804 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1805 if (!vtable->initialized)
1806 mono_runtime_class_init (vtable);
1807 mono_field_static_set_value (vtable, cf, v);
1809 mono_field_set_value (obj, cf, v);
1814 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1823 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1824 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1828 if (MONO_TYPE_IS_REFERENCE (f->type))
1829 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1831 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1834 ICALL_EXPORT MonoObject *
1835 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1837 MonoObject *o = NULL;
1838 MonoClassField *field = rfield->field;
1840 MonoDomain *domain = mono_object_domain (rfield);
1842 MonoTypeEnum def_type;
1843 const char *def_value;
1847 mono_class_init (field->parent);
1849 t = mono_field_get_type_checked (field, &error);
1850 if (!mono_error_ok (&error))
1851 mono_error_raise_exception (&error);
1853 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1854 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1858 if (image_is_dynamic (field->parent->image)) {
1859 MonoClass *klass = field->parent;
1860 int fidx = field - klass->fields;
1862 g_assert (fidx >= 0 && fidx < klass->field.count);
1863 g_assert (klass->ext);
1864 g_assert (klass->ext->field_def_values);
1865 def_type = klass->ext->field_def_values [fidx].def_type;
1866 def_value = klass->ext->field_def_values [fidx].data;
1867 if (def_type == MONO_TYPE_END) {
1868 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1872 def_value = mono_class_get_field_default_value (field, &def_type);
1873 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1875 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1880 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1884 case MONO_TYPE_BOOLEAN:
1887 case MONO_TYPE_CHAR:
1895 case MONO_TYPE_R8: {
1898 /* boxed value type */
1899 t = g_new0 (MonoType, 1);
1901 klass = mono_class_from_mono_type (t);
1903 o = mono_object_new (domain, klass);
1904 v = ((gchar *) o) + sizeof (MonoObject);
1905 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1908 case MONO_TYPE_STRING:
1909 case MONO_TYPE_CLASS:
1910 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1913 g_assert_not_reached ();
1919 ICALL_EXPORT MonoReflectionType*
1920 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1923 MonoClassField *field = ref_field->field;
1924 MonoType *type = mono_field_get_type_checked (field, &error);
1925 if (!mono_error_ok (&error))
1926 mono_error_raise_exception (&error);
1927 return mono_type_get_object (mono_object_domain (ref_field), type);
1930 ICALL_EXPORT MonoReflectionType*
1931 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1933 MonoMethod *method = rmethod->method.method;
1935 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1938 /* From MonoProperty.cs */
1940 PInfo_Attributes = 1,
1941 PInfo_GetMethod = 1 << 1,
1942 PInfo_SetMethod = 1 << 2,
1943 PInfo_ReflectedType = 1 << 3,
1944 PInfo_DeclaringType = 1 << 4,
1949 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1951 MonoDomain *domain = mono_object_domain (property);
1952 const MonoProperty *pproperty = property->property;
1954 if ((req_info & PInfo_ReflectedType) != 0)
1955 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1956 if ((req_info & PInfo_DeclaringType) != 0)
1957 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &pproperty->parent->byval_arg));
1959 if ((req_info & PInfo_Name) != 0)
1960 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
1962 if ((req_info & PInfo_Attributes) != 0)
1963 info->attrs = pproperty->attrs;
1965 if ((req_info & PInfo_GetMethod) != 0)
1966 MONO_STRUCT_SETREF (info, get, pproperty->get &&
1967 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->get->klass == property->klass) ?
1968 mono_method_get_object (domain, pproperty->get, property->klass): NULL);
1969 if ((req_info & PInfo_SetMethod) != 0)
1970 MONO_STRUCT_SETREF (info, set, pproperty->set &&
1971 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->set->klass == property->klass) ?
1972 mono_method_get_object (domain, pproperty->set, property->klass): NULL);
1974 * There may be other methods defined for properties, though, it seems they are not exposed
1975 * in the reflection API
1980 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1982 MonoDomain *domain = mono_object_domain (event);
1984 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1985 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1987 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1988 info->attrs = event->event->attrs;
1989 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
1990 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
1991 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
1993 #ifndef MONO_SMALL_CONFIG
1994 if (event->event->other) {
1996 while (event->event->other [n])
1998 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2000 for (i = 0; i < n; i++)
2001 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2007 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2012 mono_class_setup_interfaces (klass, error);
2013 if (!mono_error_ok (error))
2016 for (i = 0; i < klass->interface_count; i++) {
2017 ic = klass->interfaces [i];
2018 g_hash_table_insert (ifaces, ic, ic);
2020 collect_interfaces (ic, ifaces, error);
2021 if (!mono_error_ok (error))
2027 MonoArray *iface_array;
2028 MonoGenericContext *context;
2032 } FillIfaceArrayData;
2035 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2037 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2038 MonoClass *ic = (MonoClass *)key;
2039 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2041 if (!mono_error_ok (data->error))
2044 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2045 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2046 if (!mono_error_ok (data->error))
2050 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2053 mono_metadata_free_type (inflated);
2057 get_interfaces_hash (gconstpointer v1)
2059 MonoClass *k = (MonoClass*)v1;
2061 return k->type_token;
2064 ICALL_EXPORT MonoArray*
2065 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2068 MonoClass *klass = mono_class_from_mono_type (type->type);
2070 FillIfaceArrayData data = { 0 };
2073 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2075 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2076 data.context = mono_class_get_context (klass);
2077 klass = klass->generic_class->container_class;
2080 for (parent = klass; parent; parent = parent->parent) {
2081 mono_class_setup_interfaces (parent, &error);
2082 if (!mono_error_ok (&error))
2084 collect_interfaces (parent, iface_hash, &error);
2085 if (!mono_error_ok (&error))
2089 data.error = &error;
2090 data.domain = mono_object_domain (type);
2092 len = g_hash_table_size (iface_hash);
2094 g_hash_table_destroy (iface_hash);
2095 if (!data.domain->empty_types)
2096 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2097 return data.domain->empty_types;
2100 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2101 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2102 if (!mono_error_ok (&error))
2105 g_hash_table_destroy (iface_hash);
2106 return data.iface_array;
2109 g_hash_table_destroy (iface_hash);
2110 mono_error_raise_exception (&error);
2115 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2117 gboolean variance_used;
2118 MonoClass *klass = mono_class_from_mono_type (type->type);
2119 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2120 MonoReflectionMethod *member;
2123 int i = 0, len, ioffset;
2126 mono_class_init_or_throw (klass);
2127 mono_class_init_or_throw (iclass);
2129 mono_class_setup_vtable (klass);
2131 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2135 len = mono_class_num_methods (iclass);
2136 domain = mono_object_domain (type);
2137 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2138 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2140 while ((method = mono_class_get_methods (iclass, &iter))) {
2141 member = mono_method_get_object (domain, method, iclass);
2142 mono_array_setref (*methods, i, member);
2143 member = mono_method_get_object (domain, klass->vtable [i + ioffset], klass);
2144 mono_array_setref (*targets, i, member);
2151 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2153 MonoClass *klass = mono_class_from_mono_type (type->type);
2154 mono_class_init_or_throw (klass);
2156 if (image_is_dynamic (klass->image)) {
2157 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2158 *packing = tb->packing_size;
2159 *size = tb->class_size;
2161 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2165 ICALL_EXPORT MonoReflectionType*
2166 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2170 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2171 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2173 klass = mono_class_from_mono_type (type->type);
2174 mono_class_init_or_throw (klass);
2176 // GetElementType should only return a type for:
2177 // Array Pointer PassedByRef
2178 if (type->type->byref)
2179 return mono_type_get_object (mono_object_domain (type), &klass->byval_arg);
2180 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2181 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2182 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2183 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2188 ICALL_EXPORT MonoReflectionType*
2189 ves_icall_get_type_parent (MonoReflectionType *type)
2191 if (type->type->byref)
2194 MonoClass *klass = mono_class_from_mono_type (type->type);
2195 return klass->parent ? mono_type_get_object (mono_object_domain (type), &klass->parent->byval_arg): NULL;
2198 ICALL_EXPORT MonoBoolean
2199 ves_icall_type_ispointer (MonoReflectionType *type)
2201 return type->type->type == MONO_TYPE_PTR;
2204 ICALL_EXPORT MonoBoolean
2205 ves_icall_type_isprimitive (MonoReflectionType *type)
2207 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)));
2210 ICALL_EXPORT MonoBoolean
2211 ves_icall_type_isbyref (MonoReflectionType *type)
2213 return type->type->byref;
2216 ICALL_EXPORT MonoBoolean
2217 ves_icall_type_iscomobject (MonoReflectionType *type)
2219 MonoClass *klass = mono_class_from_mono_type (type->type);
2220 mono_class_init_or_throw (klass);
2222 return mono_class_is_com_object (klass);
2225 ICALL_EXPORT MonoReflectionModule*
2226 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2228 MonoClass *klass = mono_class_from_mono_type (type->type);
2229 return mono_module_get_object (mono_object_domain (type), klass->image);
2232 ICALL_EXPORT MonoReflectionAssembly*
2233 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2235 MonoDomain *domain = mono_domain_get ();
2236 MonoClass *klass = mono_class_from_mono_type (type->type);
2237 return mono_assembly_get_object (domain, klass->image->assembly);
2240 ICALL_EXPORT MonoReflectionType*
2241 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2243 MonoDomain *domain = mono_domain_get ();
2246 if (type->type->byref)
2248 if (type->type->type == MONO_TYPE_VAR) {
2249 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2250 klass = param ? param->owner.klass : NULL;
2251 } else if (type->type->type == MONO_TYPE_MVAR) {
2252 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2253 klass = param ? param->owner.method->klass : NULL;
2255 klass = mono_class_from_mono_type (type->type)->nested_in;
2258 return klass ? mono_type_get_object (domain, &klass->byval_arg) : NULL;
2261 ICALL_EXPORT MonoString*
2262 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2264 MonoDomain *domain = mono_domain_get ();
2265 MonoClass *klass = mono_class_from_mono_type (type->type);
2267 if (type->type->byref) {
2268 char *n = g_strdup_printf ("%s&", klass->name);
2269 MonoString *res = mono_string_new (domain, n);
2275 return mono_string_new (domain, klass->name);
2279 ICALL_EXPORT MonoString*
2280 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2282 MonoDomain *domain = mono_domain_get ();
2283 MonoClass *klass = mono_class_from_mono_type (type->type);
2285 while (klass->nested_in)
2286 klass = klass->nested_in;
2288 if (klass->name_space [0] == '\0')
2291 return mono_string_new (domain, klass->name_space);
2295 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2299 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2300 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2304 klass = mono_class_from_mono_type (type->type);
2310 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2313 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2317 ICALL_EXPORT MonoArray*
2318 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2321 MonoClass *klass, *pklass;
2322 MonoDomain *domain = mono_object_domain (type);
2325 klass = mono_class_from_mono_type (type->type);
2327 if (klass->generic_container) {
2328 MonoGenericContainer *container = klass->generic_container;
2329 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2330 for (i = 0; i < container->type_argc; ++i) {
2331 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2332 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2334 } else if (klass->generic_class) {
2335 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2336 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2337 for (i = 0; i < inst->type_argc; ++i)
2338 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2345 ICALL_EXPORT gboolean
2346 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2350 if (!IS_MONOTYPE (type))
2353 if (type->type->byref)
2356 klass = mono_class_from_mono_type (type->type);
2357 return klass->generic_container != NULL;
2360 ICALL_EXPORT MonoReflectionType*
2361 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2365 if (type->type->byref)
2368 klass = mono_class_from_mono_type (type->type);
2370 if (klass->generic_container) {
2371 return type; /* check this one */
2373 if (klass->generic_class) {
2374 MonoClass *generic_class = klass->generic_class->container_class;
2377 tb = mono_class_get_ref_info (generic_class);
2379 if (generic_class->wastypebuilder && tb)
2380 return (MonoReflectionType *)tb;
2382 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2387 ICALL_EXPORT MonoReflectionType*
2388 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2391 MonoType *geninst, **types;
2394 g_assert (IS_MONOTYPE (type));
2395 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2397 count = mono_array_length (type_array);
2398 types = g_new0 (MonoType *, count);
2400 for (i = 0; i < count; i++) {
2401 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2402 types [i] = t->type;
2405 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2410 klass = mono_class_from_mono_type (geninst);
2412 /*we might inflate to the GTD*/
2413 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2414 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2418 return mono_type_get_object (mono_object_domain (type), geninst);
2421 ICALL_EXPORT gboolean
2422 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2426 if (!IS_MONOTYPE (type))
2429 if (type->type->byref)
2432 klass = mono_class_from_mono_type (type->type);
2433 return klass->generic_class != NULL || klass->generic_container != NULL;
2437 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2439 if (!IS_MONOTYPE (type))
2442 if (is_generic_parameter (type->type))
2443 return mono_type_get_generic_param_num (type->type);
2447 ICALL_EXPORT GenericParameterAttributes
2448 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2450 g_assert (IS_MONOTYPE (type));
2451 g_assert (is_generic_parameter (type->type));
2452 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2455 ICALL_EXPORT MonoArray *
2456 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2458 MonoGenericParamInfo *param_info;
2464 g_assert (IS_MONOTYPE (type));
2466 domain = mono_object_domain (type);
2467 param_info = mono_generic_param_info (type->type->data.generic_param);
2468 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2471 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2472 for (i = 0; i < count; i++)
2473 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2479 ICALL_EXPORT MonoBoolean
2480 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2482 return is_generic_parameter (type->type);
2485 ICALL_EXPORT MonoBoolean
2486 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2488 return is_generic_parameter (tb->type.type);
2492 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2493 MonoReflectionType *t)
2495 enumtype->type = t->type;
2498 ICALL_EXPORT MonoReflectionMethod*
2499 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2500 MonoReflectionMethod* generic)
2507 domain = ((MonoObject *)type)->vtable->domain;
2509 klass = mono_class_from_mono_type (type->type);
2510 mono_class_init_or_throw (klass);
2513 while ((method = mono_class_get_methods (klass, &iter))) {
2514 if (method->token == generic->method->token)
2515 return mono_method_get_object (domain, method, klass);
2521 ICALL_EXPORT MonoReflectionMethod *
2522 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2525 MonoType *type = ref_type->type;
2527 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2528 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2531 if (type->type == MONO_TYPE_VAR)
2534 method = mono_type_get_generic_param_owner (type)->owner.method;
2536 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2539 ICALL_EXPORT MonoBoolean
2540 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2542 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2546 ICALL_EXPORT MonoBoolean
2547 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2549 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2554 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2556 MonoDomain *domain = mono_domain_get ();
2557 MonoImage *image = method->method->klass->image;
2558 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2559 MonoTableInfo *tables = image->tables;
2560 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2561 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2562 guint32 im_cols [MONO_IMPLMAP_SIZE];
2563 guint32 scope_token;
2564 const char *import = NULL;
2565 const char *scope = NULL;
2567 if (image_is_dynamic (image)) {
2568 MonoReflectionMethodAux *method_aux =
2569 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2571 import = method_aux->dllentry;
2572 scope = method_aux->dll;
2575 if (!import || !scope) {
2576 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2581 if (piinfo->implmap_idx) {
2582 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2584 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2585 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2586 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2587 scope = mono_metadata_string_heap (image, scope_token);
2591 *flags = piinfo->piflags;
2592 *entry_point = mono_string_new (domain, import);
2593 *dll_name = mono_string_new (domain, scope);
2596 ICALL_EXPORT MonoReflectionMethod *
2597 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2599 MonoMethodInflated *imethod;
2602 if (method->method->is_generic)
2605 if (!method->method->is_inflated)
2608 imethod = (MonoMethodInflated *) method->method;
2610 result = imethod->declaring;
2611 /* Not a generic method. */
2612 if (!result->is_generic)
2615 if (image_is_dynamic (method->method->klass->image)) {
2616 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2617 MonoReflectionMethod *res;
2620 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2621 * the dynamic case as well ?
2623 mono_image_lock ((MonoImage*)image);
2624 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2625 mono_image_unlock ((MonoImage*)image);
2631 if (imethod->context.class_inst) {
2632 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2633 /*Generic methods gets the context of the GTD.*/
2634 if (mono_class_get_context (klass)) {
2636 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2637 mono_error_raise_exception (&error);
2641 return mono_method_get_object (mono_object_domain (method), result, NULL);
2644 ICALL_EXPORT gboolean
2645 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2647 return mono_method_signature (method->method)->generic_param_count != 0;
2650 ICALL_EXPORT gboolean
2651 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2653 return method->method->is_generic;
2656 ICALL_EXPORT MonoArray*
2657 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2663 domain = mono_object_domain (method);
2665 if (method->method->is_inflated) {
2666 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2669 count = inst->type_argc;
2670 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2672 for (i = 0; i < count; i++)
2673 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2679 count = mono_method_signature (method->method)->generic_param_count;
2680 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2682 for (i = 0; i < count; i++) {
2683 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2684 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2685 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2686 mono_array_setref (res, i,
2687 mono_type_get_object (domain, &pklass->byval_arg));
2693 ICALL_EXPORT MonoObject *
2694 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2697 * Invoke from reflection is supposed to always be a virtual call (the API
2698 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2699 * greater flexibility.
2701 MonoMethod *m = method->method;
2702 MonoMethodSignature *sig = mono_method_signature (m);
2705 void *obj = this_arg;
2709 if (mono_security_core_clr_enabled ())
2710 mono_security_core_clr_ensure_reflection_access_method (m);
2712 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2713 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2714 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2719 if (!mono_object_isinst (this_arg, m->klass)) {
2720 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2721 char *target_name = mono_type_get_full_name (m->klass);
2722 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2723 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2725 g_free (target_name);
2729 m = mono_object_get_virtual_method (this_arg, m);
2730 /* must pass the pointer to the value for valuetype methods */
2731 if (m->klass->valuetype)
2732 obj = mono_object_unbox (this_arg);
2733 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2734 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2739 if (sig->ret->byref) {
2740 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"));
2744 pcount = params? mono_array_length (params): 0;
2745 if (pcount != sig->param_count) {
2746 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2750 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2751 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."));
2755 image = m->klass->image;
2756 if (image->assembly->ref_only) {
2757 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."));
2761 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2762 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2766 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2769 intptr_t *lower_bounds;
2770 pcount = mono_array_length (params);
2771 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
2772 /* Note: the synthetized array .ctors have int32 as argument type */
2773 for (i = 0; i < pcount; ++i)
2774 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2776 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2777 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2778 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2780 for (i = 0; i < mono_array_length (arr); ++i) {
2781 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2783 mono_array_setref_fast (arr, i, subarray);
2785 return (MonoObject*)arr;
2788 if (m->klass->rank == pcount) {
2789 /* Only lengths provided. */
2790 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2792 g_assert (pcount == (m->klass->rank * 2));
2793 /* The arguments are lower-bound-length pairs */
2794 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
2796 for (i = 0; i < pcount / 2; ++i) {
2797 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
2798 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
2801 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2804 return mono_runtime_invoke_array (m, obj, params, NULL);
2807 #ifndef DISABLE_REMOTING
2808 ICALL_EXPORT MonoObject *
2809 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
2811 MonoDomain *domain = mono_object_domain (method);
2812 MonoMethod *m = method->method;
2813 MonoMethodSignature *sig = mono_method_signature (m);
2814 MonoArray *out_args;
2816 int i, j, outarg_count = 0;
2818 if (m->klass == mono_defaults.object_class) {
2819 if (!strcmp (m->name, "FieldGetter")) {
2820 MonoClass *k = this_arg->vtable->klass;
2824 /* If this is a proxy, then it must be a CBO */
2825 if (k == mono_defaults.transparent_proxy_class) {
2826 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2827 this_arg = tp->rp->unwrapped_server;
2828 g_assert (this_arg);
2829 k = this_arg->vtable->klass;
2832 name = mono_array_get (params, MonoString *, 1);
2833 str = mono_string_to_utf8 (name);
2836 MonoClassField* field = mono_class_get_field_from_name (k, str);
2838 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2839 if (field_klass->valuetype)
2840 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
2842 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
2844 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2845 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2846 mono_array_setref (out_args, 0, result);
2854 g_assert_not_reached ();
2856 } else if (!strcmp (m->name, "FieldSetter")) {
2857 MonoClass *k = this_arg->vtable->klass;
2863 /* If this is a proxy, then it must be a CBO */
2864 if (k == mono_defaults.transparent_proxy_class) {
2865 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2866 this_arg = tp->rp->unwrapped_server;
2867 g_assert (this_arg);
2868 k = this_arg->vtable->klass;
2871 name = mono_array_get (params, MonoString *, 1);
2872 str = mono_string_to_utf8 (name);
2875 MonoClassField* field = mono_class_get_field_from_name (k, str);
2877 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2878 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
2880 if (field_klass->valuetype) {
2881 size = mono_type_size (field->type, &align);
2882 g_assert (size == mono_class_value_size (field_klass, NULL));
2883 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2885 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
2888 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2889 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2899 g_assert_not_reached ();
2904 for (i = 0; i < mono_array_length (params); i++) {
2905 if (sig->params [i]->byref)
2909 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2911 /* handle constructors only for objects already allocated */
2912 if (!strcmp (method->method->name, ".ctor"))
2913 g_assert (this_arg);
2915 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2916 g_assert (!method->method->klass->valuetype);
2917 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
2919 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2920 if (sig->params [i]->byref) {
2922 arg = mono_array_get (params, gpointer, i);
2923 mono_array_setref (out_args, j, arg);
2928 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2935 read_enum_value (const char *mem, int type)
2938 case MONO_TYPE_BOOLEAN:
2940 return *(guint8*)mem;
2942 return *(gint8*)mem;
2943 case MONO_TYPE_CHAR:
2945 return read16 (mem);
2947 return (gint16) read16 (mem);
2949 return read32 (mem);
2951 return (gint32) read32 (mem);
2954 return read64 (mem);
2956 g_assert_not_reached ();
2962 write_enum_value (char *mem, int type, guint64 value)
2966 case MONO_TYPE_I1: {
2967 guint8 *p = (guint8*)mem;
2972 case MONO_TYPE_I2: {
2973 guint16 *p = (guint16 *)mem;
2978 case MONO_TYPE_I4: {
2979 guint32 *p = (guint32 *)mem;
2984 case MONO_TYPE_I8: {
2985 guint64 *p = (guint64 *)mem;
2990 g_assert_not_reached ();
2995 ICALL_EXPORT MonoObject *
2996 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3003 domain = mono_object_domain (enumType);
3004 enumc = mono_class_from_mono_type (enumType->type);
3006 mono_class_init_or_throw (enumc);
3008 etype = mono_class_enum_basetype (enumc);
3010 res = mono_object_new (domain, enumc);
3011 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3016 ICALL_EXPORT MonoBoolean
3017 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3019 int size = mono_class_value_size (a->vtable->klass, NULL);
3020 guint64 a_val = 0, b_val = 0;
3022 memcpy (&a_val, mono_object_unbox (a), size);
3023 memcpy (&b_val, mono_object_unbox (b), size);
3025 return (a_val & b_val) == b_val;
3028 ICALL_EXPORT MonoObject *
3029 ves_icall_System_Enum_get_value (MonoObject *eobj)
3040 g_assert (eobj->vtable->klass->enumtype);
3042 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3043 res = mono_object_new (mono_object_domain (eobj), enumc);
3044 dst = (char *)res + sizeof (MonoObject);
3045 src = (char *)eobj + sizeof (MonoObject);
3046 size = mono_class_value_size (enumc, NULL);
3048 memcpy (dst, src, size);
3053 ICALL_EXPORT MonoReflectionType *
3054 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3059 klass = mono_class_from_mono_type (type->type);
3060 mono_class_init_or_throw (klass);
3062 etype = mono_class_enum_basetype (klass);
3064 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3068 return mono_type_get_object (mono_object_domain (type), etype);
3072 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3074 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3075 gpointer odata = (char *)other + sizeof (MonoObject);
3076 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3077 g_assert (basetype);
3082 if (eobj->vtable->klass != other->vtable->klass)
3085 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3086 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3087 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3090 return me > other ? 1 : -1; \
3093 switch (basetype->type) {
3095 COMPARE_ENUM_VALUES (guint8);
3097 COMPARE_ENUM_VALUES (gint8);
3098 case MONO_TYPE_CHAR:
3100 COMPARE_ENUM_VALUES (guint16);
3102 COMPARE_ENUM_VALUES (gint16);
3104 COMPARE_ENUM_VALUES (guint32);
3106 COMPARE_ENUM_VALUES (gint32);
3108 COMPARE_ENUM_VALUES (guint64);
3110 COMPARE_ENUM_VALUES (gint64);
3114 #undef COMPARE_ENUM_VALUES
3115 /* indicates that the enum was of an unsupported unerlying type */
3120 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3122 gpointer data = (char *)eobj + sizeof (MonoObject);
3123 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3124 g_assert (basetype);
3126 switch (basetype->type) {
3127 case MONO_TYPE_I1: {
3128 gint8 value = *((gint8*)data);
3129 return ((int)value ^ (int)value << 8);
3132 return *((guint8*)data);
3133 case MONO_TYPE_CHAR:
3135 return *((guint16*)data);
3137 case MONO_TYPE_I2: {
3138 gint16 value = *((gint16*)data);
3139 return ((int)(guint16)value | (((int)value) << 16));
3142 return *((guint32*)data);
3144 return *((gint32*)data);
3146 case MONO_TYPE_I8: {
3147 gint64 value = *((gint64*)data);
3148 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3151 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3156 ICALL_EXPORT MonoBoolean
3157 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3159 MonoDomain *domain = mono_object_domain (type);
3160 MonoClass *enumc = mono_class_from_mono_type (type->type);
3161 guint j = 0, nvalues;
3163 MonoClassField *field;
3165 guint64 field_value, previous_value = 0;
3166 gboolean sorted = TRUE;
3168 mono_class_init_or_throw (enumc);
3170 if (!enumc->enumtype) {
3171 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3175 base_type = mono_class_enum_basetype (enumc)->type;
3177 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3178 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3179 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3182 while ((field = mono_class_get_fields (enumc, &iter))) {
3184 MonoTypeEnum def_type;
3186 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3188 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3190 if (mono_field_is_deleted (field))
3192 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3194 p = mono_class_get_field_default_value (field, &def_type);
3195 /* len = */ mono_metadata_decode_blob_size (p, &p);
3197 field_value = read_enum_value (p, base_type);
3198 mono_array_set (*values, guint64, j, field_value);
3200 if (previous_value > field_value)
3203 previous_value = field_value;
3211 BFLAGS_IgnoreCase = 1,
3212 BFLAGS_DeclaredOnly = 2,
3213 BFLAGS_Instance = 4,
3215 BFLAGS_Public = 0x10,
3216 BFLAGS_NonPublic = 0x20,
3217 BFLAGS_FlattenHierarchy = 0x40,
3218 BFLAGS_InvokeMethod = 0x100,
3219 BFLAGS_CreateInstance = 0x200,
3220 BFLAGS_GetField = 0x400,
3221 BFLAGS_SetField = 0x800,
3222 BFLAGS_GetProperty = 0x1000,
3223 BFLAGS_SetProperty = 0x2000,
3224 BFLAGS_ExactBinding = 0x10000,
3225 BFLAGS_SuppressChangeType = 0x20000,
3226 BFLAGS_OptionalParamBinding = 0x40000
3229 ICALL_EXPORT MonoArray*
3230 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3233 MonoClass *startklass, *klass, *refklass;
3238 char *utf8_name = NULL;
3239 int (*compare_func) (const char *s1, const char *s2) = NULL;
3240 MonoClassField *field;
3241 MonoPtrArray tmp_array;
3243 domain = ((MonoObject *)type)->vtable->domain;
3244 if (type->type->byref)
3245 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3247 klass = startklass = mono_class_from_mono_type (type->type);
3248 refklass = mono_class_from_mono_type (reftype->type);
3250 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3253 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3254 mono_ptr_array_destroy (tmp_array);
3255 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3260 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3261 guint32 flags = mono_field_get_flags (field);
3263 if (mono_field_is_deleted_with_flags (field, flags))
3265 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3266 if (bflags & BFLAGS_Public)
3268 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3269 if (bflags & BFLAGS_NonPublic) {
3276 if (flags & FIELD_ATTRIBUTE_STATIC) {
3277 if (bflags & BFLAGS_Static)
3278 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3281 if (bflags & BFLAGS_Instance)
3289 if (utf8_name == NULL) {
3290 utf8_name = mono_string_to_utf8 (name);
3291 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3294 if (compare_func (mono_field_get_name (field), utf8_name))
3298 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3299 mono_ptr_array_append (tmp_array, member);
3301 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3304 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3306 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3307 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3309 mono_ptr_array_destroy (tmp_array);
3311 if (utf8_name != NULL)
3318 method_nonpublic (MonoMethod* method, gboolean start_klass)
3320 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3321 case METHOD_ATTRIBUTE_ASSEM:
3322 return (start_klass || mono_defaults.generic_ilist_class);
3323 case METHOD_ATTRIBUTE_PRIVATE:
3325 case METHOD_ATTRIBUTE_PUBLIC:
3333 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3336 MonoClass *startklass;
3340 /*FIXME, use MonoBitSet*/
3341 guint32 method_slots_default [8];
3342 guint32 *method_slots = NULL;
3343 int (*compare_func) (const char *s1, const char *s2) = NULL;
3345 array = g_ptr_array_new ();
3350 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3352 /* An optimization for calls made from Delegate:CreateDelegate () */
3353 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3354 method = mono_get_delegate_invoke (klass);
3355 if (mono_loader_get_last_error ())
3358 g_ptr_array_add (array, method);
3362 mono_class_setup_methods (klass);
3363 mono_class_setup_vtable (klass);
3364 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3367 if (is_generic_parameter (&klass->byval_arg))
3368 nslots = mono_class_get_vtable_size (klass->parent);
3370 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3371 if (nslots >= sizeof (method_slots_default) * 8) {
3372 method_slots = g_new0 (guint32, nslots / 32 + 1);
3374 method_slots = method_slots_default;
3375 memset (method_slots, 0, sizeof (method_slots_default));
3378 mono_class_setup_methods (klass);
3379 mono_class_setup_vtable (klass);
3380 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3384 while ((method = mono_class_get_methods (klass, &iter))) {
3386 if (method->slot != -1) {
3387 g_assert (method->slot < nslots);
3388 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3390 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3391 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3394 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3396 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3397 if (bflags & BFLAGS_Public)
3399 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3405 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3406 if (bflags & BFLAGS_Static)
3407 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3410 if (bflags & BFLAGS_Instance)
3418 if (compare_func (name, method->name))
3423 g_ptr_array_add (array, method);
3425 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3427 if (method_slots != method_slots_default)
3428 g_free (method_slots);
3433 if (method_slots != method_slots_default)
3434 g_free (method_slots);
3435 g_ptr_array_free (array, TRUE);
3437 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3438 *ex = mono_class_get_exception_for_failure (klass);
3440 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3441 mono_loader_clear_error ();
3446 ICALL_EXPORT MonoArray*
3447 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3449 static MonoClass *MethodInfo_array;
3452 MonoVTable *array_vtable;
3453 MonoException *ex = NULL;
3454 const char *mname = NULL;
3455 GPtrArray *method_array;
3456 MonoClass *klass, *refklass;
3459 if (!MethodInfo_array) {
3460 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3461 mono_memory_barrier ();
3462 MethodInfo_array = klass;
3465 klass = mono_class_from_mono_type (type->type);
3466 refklass = mono_class_from_mono_type (reftype->type);
3467 domain = ((MonoObject *)type)->vtable->domain;
3468 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3469 if (type->type->byref)
3470 return mono_array_new_specific (array_vtable, 0);
3473 mname = mono_string_to_utf8 (name);
3475 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3476 g_free ((char*)mname);
3478 mono_set_pending_exception (ex);
3482 res = mono_array_new_specific (array_vtable, method_array->len);
3484 for (i = 0; i < method_array->len; ++i) {
3485 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3486 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3489 g_ptr_array_free (method_array, TRUE);
3493 ICALL_EXPORT MonoArray*
3494 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3497 static MonoClass *System_Reflection_ConstructorInfo;
3498 MonoClass *startklass, *klass, *refklass;
3503 gpointer iter = NULL;
3504 MonoPtrArray tmp_array;
3506 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3508 domain = ((MonoObject *)type)->vtable->domain;
3509 if (type->type->byref)
3510 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3511 klass = startklass = mono_class_from_mono_type (type->type);
3512 refklass = mono_class_from_mono_type (reftype->type);
3514 if (!System_Reflection_ConstructorInfo)
3515 System_Reflection_ConstructorInfo = mono_class_from_name (
3516 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3518 mono_class_setup_methods (klass);
3519 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3520 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3525 while ((method = mono_class_get_methods (klass, &iter))) {
3527 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3529 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3530 if (bflags & BFLAGS_Public)
3533 if (bflags & BFLAGS_NonPublic)
3539 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3540 if (bflags & BFLAGS_Static)
3541 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3544 if (bflags & BFLAGS_Instance)
3550 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3552 mono_ptr_array_append (tmp_array, member);
3555 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3557 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3558 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3560 mono_ptr_array_destroy (tmp_array);
3566 property_hash (gconstpointer data)
3568 MonoProperty *prop = (MonoProperty*)data;
3570 return g_str_hash (prop->name);
3574 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3576 if (method1->is_inflated)
3577 method1 = ((MonoMethodInflated*) method1)->declaring;
3578 if (method2->is_inflated)
3579 method2 = ((MonoMethodInflated*) method2)->declaring;
3581 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3585 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3587 // Properties are hide-by-name-and-signature
3588 if (!g_str_equal (prop1->name, prop2->name))
3591 /* If we see a property in a generic method, we want to
3592 compare the generic signatures, not the inflated signatures
3593 because we might conflate two properties that were
3597 public T this[T t] { getter { return t; } } // method 1
3598 public U this[U u] { getter { return u; } } // method 2
3601 If we see int Foo<int,int>::Item[int] we need to know if
3602 the indexer came from method 1 or from method 2, and we
3603 shouldn't conflate them. (Bugzilla 36283)
3605 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3608 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3615 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3620 return method_nonpublic (accessor, start_klass);
3623 ICALL_EXPORT MonoArray*
3624 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3628 static MonoClass *System_Reflection_PropertyInfo;
3629 MonoClass *startklass, *klass;
3635 gchar *propname = NULL;
3636 int (*compare_func) (const char *s1, const char *s2) = NULL;
3638 GHashTable *properties = NULL;
3639 MonoPtrArray tmp_array;
3641 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3643 if (!System_Reflection_PropertyInfo)
3644 System_Reflection_PropertyInfo = mono_class_from_name (
3645 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3647 domain = ((MonoObject *)type)->vtable->domain;
3648 if (type->type->byref)
3649 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3650 klass = startklass = mono_class_from_mono_type (type->type);
3653 propname = mono_string_to_utf8 (name);
3654 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3657 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3659 mono_class_setup_methods (klass);
3660 mono_class_setup_vtable (klass);
3661 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3665 while ((prop = mono_class_get_properties (klass, &iter))) {
3671 flags = method->flags;
3674 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3675 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3676 if (bflags & BFLAGS_Public)
3678 } else if (bflags & BFLAGS_NonPublic) {
3679 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3680 property_accessor_nonpublic(prop->set, startklass == klass)) {
3687 if (flags & METHOD_ATTRIBUTE_STATIC) {
3688 if (bflags & BFLAGS_Static)
3689 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3692 if (bflags & BFLAGS_Instance)
3701 if (compare_func (propname, prop->name))
3705 if (g_hash_table_lookup (properties, prop))
3708 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3710 g_hash_table_insert (properties, prop, prop);
3712 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3715 g_hash_table_destroy (properties);
3718 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3719 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3720 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3722 mono_ptr_array_destroy (tmp_array);
3728 g_hash_table_destroy (properties);
3731 mono_ptr_array_destroy (tmp_array);
3733 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3734 ex = mono_class_get_exception_for_failure (klass);
3736 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3737 mono_loader_clear_error ();
3739 mono_set_pending_exception (ex);
3744 event_hash (gconstpointer data)
3746 MonoEvent *event = (MonoEvent*)data;
3748 return g_str_hash (event->name);
3752 event_equal (MonoEvent *event1, MonoEvent *event2)
3754 // Events are hide-by-name
3755 return g_str_equal (event1->name, event2->name);
3758 ICALL_EXPORT MonoArray*
3759 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3763 static MonoClass *System_Reflection_EventInfo;
3764 MonoClass *startklass, *klass;
3770 char *utf8_name = NULL;
3771 int (*compare_func) (const char *s1, const char *s2) = NULL;
3772 GHashTable *events = NULL;
3773 MonoPtrArray tmp_array;
3775 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
3777 if (!System_Reflection_EventInfo)
3778 System_Reflection_EventInfo = mono_class_from_name (
3779 mono_defaults.corlib, "System.Reflection", "EventInfo");
3781 domain = mono_object_domain (type);
3782 if (type->type->byref)
3783 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3784 klass = startklass = mono_class_from_mono_type (type->type);
3786 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3788 mono_class_setup_methods (klass);
3789 mono_class_setup_vtable (klass);
3790 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3794 while ((event = mono_class_get_events (klass, &iter))) {
3796 method = event->add;
3798 method = event->remove;
3800 method = event->raise;
3802 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3803 if (bflags & BFLAGS_Public)
3805 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3806 if (bflags & BFLAGS_NonPublic)
3811 if (bflags & BFLAGS_NonPublic)
3817 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3818 if (bflags & BFLAGS_Static)
3819 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3822 if (bflags & BFLAGS_Instance)
3827 if (bflags & BFLAGS_Instance)
3833 if (utf8_name == NULL) {
3834 utf8_name = mono_string_to_utf8 (name);
3835 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3838 if (compare_func (event->name, utf8_name))
3842 if (g_hash_table_lookup (events, event))
3845 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3847 g_hash_table_insert (events, event, event);
3849 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3852 g_hash_table_destroy (events);
3854 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3856 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3857 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3859 mono_ptr_array_destroy (tmp_array);
3861 if (utf8_name != NULL)
3867 mono_ptr_array_destroy (tmp_array);
3868 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3869 ex = mono_class_get_exception_for_failure (klass);
3871 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3872 mono_loader_clear_error ();
3874 mono_set_pending_exception (ex);
3878 ICALL_EXPORT MonoArray*
3879 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
3889 MonoPtrArray tmp_array;
3891 domain = ((MonoObject *)type)->vtable->domain;
3892 if (type->type->byref)
3893 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3894 klass = mono_class_from_mono_type (type->type);
3897 * If a nested type is generic, return its generic type definition.
3898 * Note that this means that the return value is essentially the set
3899 * of nested types of the generic type definition of @klass.
3901 * A note in MSDN claims that a generic type definition can have
3902 * nested types that aren't generic. In any case, the container of that
3903 * nested type would be the generic type definition.
3905 if (klass->generic_class)
3906 klass = klass->generic_class->container_class;
3908 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
3910 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3912 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3913 if (bflags & BFLAGS_Public)
3916 if (bflags & BFLAGS_NonPublic)
3924 str = mono_string_to_utf8 (name);
3925 mono_identifier_unescape_type_name_chars (str);
3928 if (strcmp (nested->name, str))
3932 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3933 mono_ptr_array_append (tmp_array, member);
3936 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
3938 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3939 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3941 mono_ptr_array_destroy (tmp_array);
3949 ICALL_EXPORT MonoReflectionType*
3950 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3953 MonoType *type = NULL;
3954 MonoTypeNameParse info;
3955 gboolean type_resolve;
3957 /* On MS.NET, this does not fire a TypeResolve event */
3958 type_resolve = TRUE;
3959 str = mono_string_to_utf8 (name);
3960 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3961 if (!mono_reflection_parse_type (str, &info)) {
3963 mono_reflection_free_type_info (&info);
3965 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
3968 /*g_print ("failed parse\n");*/
3972 if (info.assembly.name) {
3974 mono_reflection_free_type_info (&info);
3976 /* 1.0 and 2.0 throw different exceptions */
3977 if (mono_defaults.generic_ilist_class)
3978 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
3980 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
3986 if (module != NULL) {
3988 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
3993 if (assembly_is_dynamic (assembly->assembly)) {
3994 /* Enumerate all modules */
3995 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
3999 if (abuilder->modules) {
4000 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4001 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4002 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4008 if (!type && abuilder->loaded_modules) {
4009 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4010 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4011 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4018 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4020 mono_reflection_free_type_info (&info);
4022 MonoException *e = NULL;
4025 e = mono_get_exception_type_load (name, NULL);
4027 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4028 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4030 mono_loader_clear_error ();
4033 mono_set_pending_exception (e);
4035 } else if (mono_loader_get_last_error ()) {
4037 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4040 mono_loader_clear_error ();
4043 if (type->type == MONO_TYPE_CLASS) {
4044 MonoClass *klass = mono_type_get_class (type);
4046 /* need to report exceptions ? */
4047 if (throwOnError && klass->exception_type) {
4048 /* report SecurityException (or others) that occured when loading the assembly */
4049 MonoException *exc = mono_class_get_exception_for_failure (klass);
4050 mono_loader_clear_error ();
4051 mono_set_pending_exception (exc);
4056 /* g_print ("got it\n"); */
4057 return mono_type_get_object (mono_object_domain (assembly), type);
4061 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4064 gchar *shadow_ini_file;
4067 /* Check for shadow-copied assembly */
4068 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4069 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4071 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4072 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4078 g_free (shadow_ini_file);
4079 if (content != NULL) {
4082 *filename = content;
4089 ICALL_EXPORT MonoString *
4090 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4092 MonoDomain *domain = mono_object_domain (assembly);
4093 MonoAssembly *mass = assembly->assembly;
4094 MonoString *res = NULL;
4099 if (g_path_is_absolute (mass->image->name)) {
4100 absolute = g_strdup (mass->image->name);
4101 dirname = g_path_get_dirname (absolute);
4103 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4104 dirname = g_strdup (mass->basedir);
4107 replace_shadow_path (domain, dirname, &absolute);
4112 for (i = strlen (absolute) - 1; i >= 0; i--)
4113 if (absolute [i] == '\\')
4118 uri = g_filename_to_uri (absolute, NULL, NULL);
4120 const char *prepend = "file://";
4122 if (*absolute == '/' && *(absolute + 1) == '/') {
4125 prepend = "file:///";
4128 uri = g_strconcat (prepend, absolute, NULL);
4132 res = mono_string_new (domain, uri);
4139 ICALL_EXPORT MonoBoolean
4140 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4142 MonoAssembly *mass = assembly->assembly;
4144 return mass->in_gac;
4147 ICALL_EXPORT MonoReflectionAssembly*
4148 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4152 MonoImageOpenStatus status;
4154 name = mono_string_to_utf8 (mname);
4155 res = mono_assembly_load_with_partial_name (name, &status);
4161 return mono_assembly_get_object (mono_domain_get (), res);
4164 ICALL_EXPORT MonoString *
4165 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4167 MonoDomain *domain = mono_object_domain (assembly);
4170 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4175 ICALL_EXPORT MonoBoolean
4176 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4178 return assembly->assembly->ref_only;
4181 ICALL_EXPORT MonoString *
4182 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4184 MonoDomain *domain = mono_object_domain (assembly);
4186 return mono_string_new (domain, assembly->assembly->image->version);
4189 ICALL_EXPORT MonoReflectionMethod*
4190 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4194 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4198 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4199 mono_error_raise_exception (&error);
4201 return mono_method_get_object (mono_object_domain (assembly), method, NULL);
4204 ICALL_EXPORT MonoReflectionModule*
4205 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4207 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4210 ICALL_EXPORT MonoArray*
4211 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4213 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4214 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4218 for (i = 0; i < table->rows; ++i) {
4219 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4220 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4226 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4228 static MonoClass *System_Version = NULL;
4229 static MonoMethod *create_version = NULL;
4233 if (!System_Version) {
4234 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4235 g_assert (System_Version);
4238 if (!create_version) {
4239 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4240 create_version = mono_method_desc_search_in_class (desc, System_Version);
4241 g_assert (create_version);
4242 mono_method_desc_free (desc);
4248 args [3] = &revision;
4249 result = mono_object_new (domain, System_Version);
4250 mono_runtime_invoke (create_version, result, args, NULL);
4255 ICALL_EXPORT MonoArray*
4256 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4258 static MonoClass *System_Reflection_AssemblyName;
4260 MonoDomain *domain = mono_object_domain (assembly);
4262 static MonoMethod *create_culture = NULL;
4263 MonoImage *image = assembly->assembly->image;
4266 if (!System_Reflection_AssemblyName)
4267 System_Reflection_AssemblyName = mono_class_from_name (
4268 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4270 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4273 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4275 if (count > 0 && !create_culture) {
4276 MonoMethodDesc *desc = mono_method_desc_new (
4277 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4278 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4279 g_assert (create_culture);
4280 mono_method_desc_free (desc);
4283 for (i = 0; i < count; i++) {
4284 MonoReflectionAssemblyName *aname;
4285 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4287 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4289 aname = (MonoReflectionAssemblyName *) mono_object_new (
4290 domain, System_Reflection_AssemblyName);
4292 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4294 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4295 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4296 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4297 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4298 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4299 aname->versioncompat = 1; /* SameMachine (default) */
4300 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4301 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4303 if (create_culture) {
4305 MonoBoolean assembly_ref = 1;
4306 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4307 args [1] = &assembly_ref;
4308 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4311 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4312 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4313 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4315 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4316 /* public key token isn't copied - the class library will
4317 automatically generate it from the public key if required */
4318 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4319 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4321 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4322 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4325 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4328 /* note: this function doesn't return the codebase on purpose (i.e. it can
4329 be used under partial trust as path information isn't present). */
4331 mono_array_setref (result, i, aname);
4336 /* move this in some file in mono/util/ */
4338 g_concat_dir_and_file (const char *dir, const char *file)
4340 g_return_val_if_fail (dir != NULL, NULL);
4341 g_return_val_if_fail (file != NULL, NULL);
4344 * If the directory name doesn't have a / on the end, we need
4345 * to add one so we get a proper path to the file
4347 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4348 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4350 return g_strconcat (dir, file, NULL);
4354 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4356 char *n = mono_string_to_utf8 (name);
4357 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4359 guint32 cols [MONO_MANIFEST_SIZE];
4360 guint32 impl, file_idx;
4364 for (i = 0; i < table->rows; ++i) {
4365 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4366 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4367 if (strcmp (val, n) == 0)
4371 if (i == table->rows)
4374 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4377 * this code should only be called after obtaining the
4378 * ResourceInfo and handling the other cases.
4380 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4381 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4383 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4388 module = assembly->assembly->image;
4390 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4392 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4395 ICALL_EXPORT gboolean
4396 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4398 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4400 guint32 cols [MONO_MANIFEST_SIZE];
4401 guint32 file_cols [MONO_FILE_SIZE];
4405 n = mono_string_to_utf8 (name);
4406 for (i = 0; i < table->rows; ++i) {
4407 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4408 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4409 if (strcmp (val, n) == 0)
4413 if (i == table->rows)
4416 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4417 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4420 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4421 case MONO_IMPLEMENTATION_FILE:
4422 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4423 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4424 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4425 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4426 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4427 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4430 info->location = RESOURCE_LOCATION_EMBEDDED;
4433 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4434 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4435 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4436 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4437 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4438 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4440 mono_set_pending_exception (ex);
4443 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4445 /* Obtain info recursively */
4446 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4447 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4450 case MONO_IMPLEMENTATION_EXP_TYPE:
4451 g_assert_not_reached ();
4459 ICALL_EXPORT MonoObject*
4460 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4462 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4463 MonoArray *result = NULL;
4468 /* check hash if needed */
4470 n = mono_string_to_utf8 (name);
4471 for (i = 0; i < table->rows; ++i) {
4472 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4473 if (strcmp (val, n) == 0) {
4476 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4477 fn = mono_string_new (mono_object_domain (assembly), n);
4479 return (MonoObject*)fn;
4487 for (i = 0; i < table->rows; ++i) {
4488 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4492 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4495 for (i = 0; i < table->rows; ++i) {
4496 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4497 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4498 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4499 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4504 return (MonoObject*)result;
4507 ICALL_EXPORT MonoArray*
4508 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4510 MonoDomain *domain = mono_domain_get();
4513 int i, j, file_count = 0;
4514 MonoImage **modules;
4515 guint32 module_count, real_module_count;
4516 MonoTableInfo *table;
4517 guint32 cols [MONO_FILE_SIZE];
4518 MonoImage *image = assembly->assembly->image;
4520 g_assert (image != NULL);
4521 g_assert (!assembly_is_dynamic (assembly->assembly));
4523 table = &image->tables [MONO_TABLE_FILE];
4524 file_count = table->rows;
4526 modules = image->modules;
4527 module_count = image->module_count;
4529 real_module_count = 0;
4530 for (i = 0; i < module_count; ++i)
4532 real_module_count ++;
4534 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4535 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4537 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4539 for (i = 0; i < module_count; ++i)
4541 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4545 for (i = 0; i < file_count; ++i, ++j) {
4546 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4547 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4548 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4550 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4552 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4553 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4556 mono_array_setref (res, j, mono_module_get_object (domain, m));
4563 ICALL_EXPORT MonoReflectionMethod*
4564 ves_icall_GetCurrentMethod (void)
4566 MonoMethod *m = mono_method_get_last_managed ();
4568 while (m->is_inflated)
4569 m = ((MonoMethodInflated*)m)->declaring;
4571 return mono_method_get_object (mono_domain_get (), m, NULL);
4576 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4579 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4582 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4583 //method is inflated, we should inflate it on the other class
4584 MonoGenericContext ctx;
4585 ctx.method_inst = inflated->context.method_inst;
4586 ctx.class_inst = inflated->context.class_inst;
4587 if (klass->generic_class)
4588 ctx.class_inst = klass->generic_class->context.class_inst;
4589 else if (klass->generic_container)
4590 ctx.class_inst = klass->generic_container->context.class_inst;
4591 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4592 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4596 mono_class_setup_methods (method->klass);
4597 if (method->klass->exception_type)
4599 for (i = 0; i < method->klass->method.count; ++i) {
4600 if (method->klass->methods [i] == method) {
4605 mono_class_setup_methods (klass);
4606 if (klass->exception_type)
4608 g_assert (offset >= 0 && offset < klass->method.count);
4609 return klass->methods [offset];
4612 ICALL_EXPORT MonoReflectionMethod*
4613 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4617 klass = mono_class_from_mono_type (type);
4618 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4620 if (method->klass != klass) {
4621 method = mono_method_get_equivalent_method (method, klass);
4626 klass = method->klass;
4627 return mono_method_get_object (mono_domain_get (), method, klass);
4630 ICALL_EXPORT MonoReflectionMethodBody*
4631 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4633 return mono_method_body_get_object (mono_domain_get (), method);
4636 ICALL_EXPORT MonoReflectionAssembly*
4637 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4639 MonoMethod *dest = NULL;
4641 mono_stack_walk_no_il (get_executing, &dest);
4643 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4647 ICALL_EXPORT MonoReflectionAssembly*
4648 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4650 MonoDomain* domain = mono_domain_get ();
4652 if (!domain->entry_assembly)
4655 return mono_assembly_get_object (domain, domain->entry_assembly);
4658 ICALL_EXPORT MonoReflectionAssembly*
4659 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4665 mono_stack_walk_no_il (get_executing, &dest);
4667 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
4670 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4673 ICALL_EXPORT MonoString *
4674 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4675 gboolean assembly_qualified)
4677 MonoDomain *domain = mono_object_domain (object);
4678 MonoTypeNameFormat format;
4683 format = assembly_qualified ?
4684 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4685 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4687 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4689 name = mono_type_get_name_full (object->type, format);
4693 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4698 res = mono_string_new (domain, name);
4705 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
4707 MonoClass *klass = mono_class_from_mono_type (rfield->type);
4708 mono_class_init_or_throw (klass);
4709 return mono_security_core_clr_class_level (klass);
4713 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
4715 MonoClassField *field = rfield->field;
4716 return mono_security_core_clr_field_level (field, TRUE);
4720 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
4722 MonoMethod *method = rfield->method;
4723 return mono_security_core_clr_method_level (method, TRUE);
4727 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4729 static MonoMethod *create_culture = NULL;
4732 const char *pkey_ptr;
4734 MonoBoolean assembly_ref = 0;
4736 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4737 aname->major = name->major;
4738 aname->minor = name->minor;
4739 aname->build = name->build;
4740 aname->flags = name->flags;
4741 aname->revision = name->revision;
4742 aname->hashalg = name->hash_alg;
4743 aname->versioncompat = 1; /* SameMachine (default) */
4744 aname->processor_architecture = name->arch;
4746 if (by_default_version)
4747 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4750 if (absolute != NULL && *absolute != '\0') {
4751 const gchar *prepend = "file://";
4754 codebase = g_strdup (absolute);
4759 for (i = strlen (codebase) - 1; i >= 0; i--)
4760 if (codebase [i] == '\\')
4763 if (*codebase == '/' && *(codebase + 1) == '/') {
4766 prepend = "file:///";
4770 result = g_strconcat (prepend, codebase, NULL);
4776 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4780 if (!create_culture) {
4781 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4782 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4783 g_assert (create_culture);
4784 mono_method_desc_free (desc);
4787 if (name->culture) {
4788 args [0] = mono_string_new (domain, name->culture);
4789 args [1] = &assembly_ref;
4790 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4793 if (name->public_key) {
4794 pkey_ptr = (char*)name->public_key;
4795 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4797 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4798 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4799 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4800 } else if (default_publickey) {
4801 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4802 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4805 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4806 if (name->public_key_token [0]) {
4810 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4811 p = mono_array_addr (aname->keyToken, char, 0);
4813 for (i = 0, j = 0; i < 8; i++) {
4814 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4815 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4818 } else if (default_token) {
4819 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4823 ICALL_EXPORT MonoString *
4824 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4826 MonoDomain *domain = mono_object_domain (assembly);
4827 MonoAssembly *mass = assembly->assembly;
4831 name = mono_stringify_assembly_name (&mass->aname);
4832 res = mono_string_new (domain, name);
4839 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4842 MonoAssembly *mass = assembly->assembly;
4844 if (g_path_is_absolute (mass->image->name)) {
4845 fill_reflection_assembly_name (mono_object_domain (assembly),
4846 aname, &mass->aname, mass->image->name, TRUE,
4850 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4852 fill_reflection_assembly_name (mono_object_domain (assembly),
4853 aname, &mass->aname, absolute, TRUE, TRUE,
4860 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4863 MonoImageOpenStatus status = MONO_IMAGE_OK;
4866 MonoAssemblyName name;
4869 filename = mono_string_to_utf8 (fname);
4871 dirname = g_path_get_dirname (filename);
4872 replace_shadow_path (mono_domain_get (), dirname, &filename);
4875 image = mono_image_open (filename, &status);
4881 if (status == MONO_IMAGE_IMAGE_INVALID)
4882 exc = mono_get_exception_bad_image_format2 (NULL, fname);
4884 exc = mono_get_exception_file_not_found2 (NULL, fname);
4885 mono_set_pending_exception (exc);
4889 res = mono_assembly_fill_assembly_name (image, &name);
4891 mono_image_close (image);
4893 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4897 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
4901 mono_image_close (image);
4904 ICALL_EXPORT MonoBoolean
4905 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4906 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4908 MonoBoolean result = FALSE;
4909 MonoDeclSecurityEntry entry;
4911 /* SecurityAction.RequestMinimum */
4912 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4913 *minimum = entry.blob;
4914 *minLength = entry.size;
4917 /* SecurityAction.RequestOptional */
4918 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4919 *optional = entry.blob;
4920 *optLength = entry.size;
4923 /* SecurityAction.RequestRefuse */
4924 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4925 *refused = entry.blob;
4926 *refLength = entry.size;
4934 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
4936 guint32 attrs, visibility;
4938 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
4939 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4940 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
4943 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
4949 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
4953 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4956 /* we start the count from 1 because we skip the special type <Module> */
4959 for (i = 1; i < tdef->rows; ++i) {
4960 if (mono_module_type_is_visible (tdef, image, i + 1))
4964 count = tdef->rows - 1;
4966 res = mono_array_new (domain, mono_defaults.monotype_class, count);
4967 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
4969 for (i = 1; i < tdef->rows; ++i) {
4970 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
4972 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
4973 mono_loader_assert_no_error (); /* Plug any leaks */
4976 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
4978 MonoException *ex = mono_error_convert_to_exception (&error);
4979 mono_array_setref (*exceptions, count, ex);
4988 ICALL_EXPORT MonoArray*
4989 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
4991 MonoArray *res = NULL;
4992 MonoArray *exceptions = NULL;
4993 MonoImage *image = NULL;
4994 MonoTableInfo *table = NULL;
4997 int i, len, ex_count;
4999 domain = mono_object_domain (assembly);
5001 g_assert (!assembly_is_dynamic (assembly->assembly));
5002 image = assembly->assembly->image;
5003 table = &image->tables [MONO_TABLE_FILE];
5004 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5006 /* Append data from all modules in the assembly */
5007 for (i = 0; i < table->rows; ++i) {
5008 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5009 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5012 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5013 /* Append the new types to the end of the array */
5014 if (mono_array_length (res2) > 0) {
5016 MonoArray *res3, *ex3;
5018 len1 = mono_array_length (res);
5019 len2 = mono_array_length (res2);
5021 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5022 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5023 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5026 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5027 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5028 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5035 /* the ReflectionTypeLoadException must have all the types (Types property),
5036 * NULL replacing types which throws an exception. The LoaderException must
5037 * contain all exceptions for NULL items.
5040 len = mono_array_length (res);
5043 for (i = 0; i < len; i++) {
5044 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5048 klass = mono_type_get_class (t->type);
5049 if ((klass != NULL) && klass->exception_type) {
5050 /* keep the class in the list */
5051 list = g_list_append (list, klass);
5052 /* and replace Type with NULL */
5053 mono_array_setref (res, i, NULL);
5060 if (list || ex_count) {
5062 MonoException *exc = NULL;
5063 MonoArray *exl = NULL;
5064 int j, length = g_list_length (list) + ex_count;
5066 mono_loader_clear_error ();
5068 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5069 /* Types for which mono_class_get_checked () succeeded */
5070 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5071 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5072 mono_array_setref (exl, i, exc);
5074 /* Types for which it don't */
5075 for (j = 0; j < mono_array_length (exceptions); ++j) {
5076 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5078 g_assert (i < length);
5079 mono_array_setref (exl, i, exc);
5086 exc = mono_get_exception_reflection_type_load (res, exl);
5087 mono_loader_clear_error ();
5088 mono_set_pending_exception (exc);
5095 ICALL_EXPORT gboolean
5096 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5098 MonoAssemblyName aname;
5099 MonoDomain *domain = mono_object_domain (name);
5101 gboolean is_version_defined;
5102 gboolean is_token_defined;
5104 aname.public_key = NULL;
5105 val = mono_string_to_utf8 (assname);
5106 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5107 g_free ((guint8*) aname.public_key);
5112 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5113 FALSE, is_token_defined);
5115 mono_assembly_name_free (&aname);
5116 g_free ((guint8*) aname.public_key);
5122 ICALL_EXPORT MonoReflectionType*
5123 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5126 MonoDomain *domain = mono_object_domain (module);
5129 g_assert (module->image);
5131 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5132 /* These images do not have a global type */
5135 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5136 mono_error_raise_exception (&error);
5137 return mono_type_get_object (domain, &klass->byval_arg);
5141 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5143 /*if (module->image)
5144 mono_image_close (module->image);*/
5147 ICALL_EXPORT MonoString*
5148 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5150 MonoDomain *domain = mono_object_domain (module);
5152 g_assert (module->image);
5153 return mono_string_new (domain, module->image->guid);
5156 ICALL_EXPORT gpointer
5157 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5160 if (module->image && module->image->is_module_handle)
5161 return module->image->raw_data;
5164 return (gpointer) (-1);
5168 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5170 if (image_is_dynamic (image)) {
5171 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5172 *pe_kind = dyn->pe_kind;
5173 *machine = dyn->machine;
5176 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5177 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5182 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5184 return (image->md_version_major << 16) | (image->md_version_minor);
5187 ICALL_EXPORT MonoArray*
5188 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5190 MonoArray *exceptions;
5194 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5196 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5197 for (i = 0; i < mono_array_length (exceptions); ++i) {
5198 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5200 mono_set_pending_exception (ex);
5209 mono_memberref_is_method (MonoImage *image, guint32 token)
5211 if (!image_is_dynamic (image)) {
5212 guint32 cols [MONO_MEMBERREF_SIZE];
5214 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5215 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5216 mono_metadata_decode_blob_size (sig, &sig);
5217 return (*sig != 0x6);
5219 MonoClass *handle_class;
5221 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5224 return mono_defaults.methodhandle_class == handle_class;
5229 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5232 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5233 mono_array_addr (type_args, MonoType*, 0));
5235 context->class_inst = NULL;
5237 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5238 mono_array_addr (method_args, MonoType*, 0));
5240 context->method_inst = NULL;
5243 ICALL_EXPORT MonoType*
5244 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5247 int table = mono_metadata_token_table (token);
5248 int index = mono_metadata_token_index (token);
5249 MonoGenericContext context;
5252 *resolve_error = ResolveTokenError_Other;
5254 /* Validate token */
5255 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5256 (table != MONO_TABLE_TYPESPEC)) {
5257 *resolve_error = ResolveTokenError_BadTable;
5261 if (image_is_dynamic (image)) {
5262 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5263 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5264 return klass ? &klass->byval_arg : NULL;
5267 init_generic_context_from_args (&context, type_args, method_args);
5268 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5269 return klass ? &klass->byval_arg : NULL;
5272 if ((index <= 0) || (index > image->tables [table].rows)) {
5273 *resolve_error = ResolveTokenError_OutOfRange;
5277 init_generic_context_from_args (&context, type_args, method_args);
5278 klass = mono_class_get_checked (image, token, &error);
5280 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5281 mono_error_raise_exception (&error);
5284 return &klass->byval_arg;
5289 ICALL_EXPORT MonoMethod*
5290 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5293 int table = mono_metadata_token_table (token);
5294 int index = mono_metadata_token_index (token);
5295 MonoGenericContext context;
5298 *resolve_error = ResolveTokenError_Other;
5300 /* Validate token */
5301 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5302 (table != MONO_TABLE_MEMBERREF)) {
5303 *resolve_error = ResolveTokenError_BadTable;
5307 if (image_is_dynamic (image)) {
5308 if (table == MONO_TABLE_METHOD)
5309 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5311 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5312 *resolve_error = ResolveTokenError_BadTable;
5316 init_generic_context_from_args (&context, type_args, method_args);
5317 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5320 if ((index <= 0) || (index > image->tables [table].rows)) {
5321 *resolve_error = ResolveTokenError_OutOfRange;
5324 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5325 *resolve_error = ResolveTokenError_BadTable;
5329 init_generic_context_from_args (&context, type_args, method_args);
5330 method = mono_get_method_checked (image, token, NULL, &context, &error);
5331 mono_error_raise_exception (&error);
5336 ICALL_EXPORT MonoString*
5337 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5339 int index = mono_metadata_token_index (token);
5341 *error = ResolveTokenError_Other;
5343 /* Validate token */
5344 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5345 *error = ResolveTokenError_BadTable;
5349 if (image_is_dynamic (image))
5350 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5352 if ((index <= 0) || (index >= image->heap_us.size)) {
5353 *error = ResolveTokenError_OutOfRange;
5357 /* FIXME: What to do if the index points into the middle of a string ? */
5359 return mono_ldstr (mono_domain_get (), image, index);
5362 ICALL_EXPORT MonoClassField*
5363 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5367 int table = mono_metadata_token_table (token);
5368 int index = mono_metadata_token_index (token);
5369 MonoGenericContext context;
5370 MonoClassField *field;
5372 *resolve_error = ResolveTokenError_Other;
5374 /* Validate token */
5375 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5376 *resolve_error = ResolveTokenError_BadTable;
5380 if (image_is_dynamic (image)) {
5381 if (table == MONO_TABLE_FIELD)
5382 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5384 if (mono_memberref_is_method (image, token)) {
5385 *resolve_error = ResolveTokenError_BadTable;
5389 init_generic_context_from_args (&context, type_args, method_args);
5390 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5393 if ((index <= 0) || (index > image->tables [table].rows)) {
5394 *resolve_error = ResolveTokenError_OutOfRange;
5397 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5398 *resolve_error = ResolveTokenError_BadTable;
5402 init_generic_context_from_args (&context, type_args, method_args);
5403 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5404 mono_error_raise_exception (&error);
5410 ICALL_EXPORT MonoObject*
5411 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5413 int table = mono_metadata_token_table (token);
5415 *error = ResolveTokenError_Other;
5418 case MONO_TABLE_TYPEDEF:
5419 case MONO_TABLE_TYPEREF:
5420 case MONO_TABLE_TYPESPEC: {
5421 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5423 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5427 case MONO_TABLE_METHOD:
5428 case MONO_TABLE_METHODSPEC: {
5429 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5431 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5435 case MONO_TABLE_FIELD: {
5436 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5438 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5442 case MONO_TABLE_MEMBERREF:
5443 if (mono_memberref_is_method (image, token)) {
5444 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5446 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5451 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5453 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5460 *error = ResolveTokenError_BadTable;
5466 ICALL_EXPORT MonoArray*
5467 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5469 int table = mono_metadata_token_table (token);
5470 int idx = mono_metadata_token_index (token);
5471 MonoTableInfo *tables = image->tables;
5476 *error = ResolveTokenError_OutOfRange;
5478 /* FIXME: Support other tables ? */
5479 if (table != MONO_TABLE_STANDALONESIG)
5482 if (image_is_dynamic (image))
5485 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5488 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5490 ptr = mono_metadata_blob_heap (image, sig);
5491 len = mono_metadata_decode_blob_size (ptr, &ptr);
5493 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5494 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5498 ICALL_EXPORT MonoReflectionType*
5499 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5502 int isbyref = 0, rank;
5503 char *str = mono_string_to_utf8 (smodifiers);
5506 klass = mono_class_from_mono_type (tb->type.type);
5508 /* logic taken from mono_reflection_parse_type(): keep in sync */
5512 if (isbyref) { /* only one level allowed by the spec */
5519 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5522 klass = mono_ptr_class_get (&klass->byval_arg);
5523 mono_class_init (klass);
5534 else if (*p != '*') { /* '*' means unknown lower bound */
5545 klass = mono_array_class_get (klass, rank);
5546 mono_class_init (klass);
5553 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5556 ICALL_EXPORT MonoBoolean
5557 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5563 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5569 check_for_invalid_type (MonoClass *klass)
5573 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5576 name = mono_type_get_full_name (klass);
5577 str = mono_string_new (mono_domain_get (), name);
5579 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5582 ICALL_EXPORT MonoReflectionType *
5583 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5585 MonoClass *klass, *aklass;
5587 klass = mono_class_from_mono_type (type->type);
5588 check_for_invalid_type (klass);
5590 if (rank == 0) //single dimentional array
5591 aklass = mono_array_class_get (klass, 1);
5593 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5595 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5598 ICALL_EXPORT MonoReflectionType *
5599 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5603 klass = mono_class_from_mono_type (type->type);
5604 mono_class_init_or_throw (klass);
5605 check_for_invalid_type (klass);
5607 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5610 ICALL_EXPORT MonoReflectionType *
5611 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5613 MonoClass *klass, *pklass;
5615 klass = mono_class_from_mono_type (type->type);
5616 mono_class_init_or_throw (klass);
5617 check_for_invalid_type (klass);
5619 pklass = mono_ptr_class_get (type->type);
5621 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5624 ICALL_EXPORT MonoObject *
5625 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5626 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5628 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5629 MonoObject *delegate;
5631 MonoMethod *method = info->method;
5633 mono_class_init_or_throw (delegate_class);
5635 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5637 if (mono_security_core_clr_enabled ()) {
5638 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5642 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5644 if (method_is_dynamic (method)) {
5645 /* Creating a trampoline would leak memory */
5646 func = mono_compile_method (method);
5648 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5649 method = mono_object_get_virtual_method (target, method);
5650 func = mono_create_ftnptr (mono_domain_get (),
5651 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5654 mono_delegate_ctor_with_method (delegate, target, func, method);
5659 ICALL_EXPORT MonoMulticastDelegate *
5660 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
5662 MonoMulticastDelegate *ret;
5664 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
5666 ret = (MonoMulticastDelegate*) mono_object_new (mono_object_domain (delegate), mono_object_class (delegate));
5667 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
5672 ICALL_EXPORT MonoReflectionMethod*
5673 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
5675 return mono_method_get_object (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target));
5680 static inline gint32
5681 mono_array_get_byte_length (MonoArray *array)
5687 klass = array->obj.vtable->klass;
5689 if (array->bounds == NULL)
5690 length = array->max_length;
5693 for (i = 0; i < klass->rank; ++ i)
5694 length *= array->bounds [i].length;
5697 switch (klass->element_class->byval_arg.type) {
5700 case MONO_TYPE_BOOLEAN:
5704 case MONO_TYPE_CHAR:
5712 return length * sizeof (gpointer);
5723 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
5725 return mono_array_get_byte_length (array);
5729 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
5731 return mono_array_get (array, gint8, idx);
5735 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
5737 mono_array_set (array, gint8, idx, value);
5740 ICALL_EXPORT MonoBoolean
5741 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
5743 guint8 *src_buf, *dest_buf;
5746 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
5750 g_assert (count >= 0);
5752 /* This is called directly from the class libraries without going through the managed wrapper */
5753 MONO_CHECK_ARG_NULL (src, FALSE);
5754 MONO_CHECK_ARG_NULL (dest, FALSE);
5756 /* watch out for integer overflow */
5757 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5760 src_buf = (guint8 *)src->vector + src_offset;
5761 dest_buf = (guint8 *)dest->vector + dest_offset;
5764 memcpy (dest_buf, src_buf, count);
5766 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5771 #ifndef DISABLE_REMOTING
5772 ICALL_EXPORT MonoObject *
5773 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
5775 MonoDomain *domain = mono_object_domain (this_obj);
5777 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
5778 MonoTransparentProxy *tp;
5782 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5783 tp = (MonoTransparentProxy*) res;
5785 MONO_OBJECT_SETREF (tp, rp, rp);
5786 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5787 klass = mono_class_from_mono_type (type);
5789 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
5790 mono_class_setup_vtable (klass);
5791 if (klass->exception_type)
5792 mono_raise_exception (mono_class_get_exception_for_failure (klass));
5794 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
5795 tp->remote_class = mono_remote_class (domain, class_name, klass);
5797 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
5801 ICALL_EXPORT MonoReflectionType *
5802 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5804 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5808 /* System.Environment */
5811 ves_icall_System_Environment_get_UserName (void)
5813 /* using glib is more portable */
5814 return mono_string_new (mono_domain_get (), g_get_user_name ());
5818 ICALL_EXPORT MonoString *
5819 ves_icall_System_Environment_get_MachineName (void)
5821 #if defined (HOST_WIN32)
5826 len = MAX_COMPUTERNAME_LENGTH + 1;
5827 buf = g_new (gunichar2, len);
5830 if (GetComputerName (buf, (PDWORD) &len))
5831 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5835 #elif !defined(DISABLE_SOCKETS)
5839 #if defined _SC_HOST_NAME_MAX
5840 n = sysconf (_SC_HOST_NAME_MAX);
5844 buf = g_malloc (n+1);
5846 if (gethostname (buf, n) == 0){
5848 result = mono_string_new (mono_domain_get (), buf);
5855 return mono_string_new (mono_domain_get (), "mono");
5860 ves_icall_System_Environment_get_Platform (void)
5862 #if defined (TARGET_WIN32)
5865 #elif defined(__MACH__)
5868 // Notice that the value is hidden from user code, and only exposed
5869 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
5870 // define and making assumptions based on Unix/128/4 values before there
5871 // was a MacOS define. Lots of code would assume that not-Unix meant
5872 // Windows, but in this case, it would be OSX.
5881 ICALL_EXPORT MonoString *
5882 ves_icall_System_Environment_get_NewLine (void)
5884 #if defined (HOST_WIN32)
5885 return mono_string_new (mono_domain_get (), "\r\n");
5887 return mono_string_new (mono_domain_get (), "\n");
5891 ICALL_EXPORT MonoString *
5892 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5900 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5901 value = g_getenv (utf8_name);
5908 return mono_string_new (mono_domain_get (), value);
5912 * There is no standard way to get at environ.
5915 #ifndef __MINGW32_VERSION
5916 #if defined(__APPLE__)
5917 #if defined (TARGET_OSX)
5918 /* Apple defines this in crt_externs.h but doesn't provide that header for
5919 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
5920 * in fact exist on all implementations (so far)
5922 gchar ***_NSGetEnviron(void);
5923 #define environ (*_NSGetEnviron())
5925 static char *mono_environ[1] = { NULL };
5926 #define environ mono_environ
5927 #endif /* defined (TARGET_OSX) */
5935 ICALL_EXPORT MonoArray *
5936 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
5947 env_strings = GetEnvironmentStrings();
5950 env_string = env_strings;
5951 while (*env_string != '\0') {
5952 /* weird case that MS seems to skip */
5953 if (*env_string != '=')
5955 while (*env_string != '\0')
5961 domain = mono_domain_get ();
5962 names = mono_array_new (domain, mono_defaults.string_class, n);
5966 env_string = env_strings;
5967 while (*env_string != '\0') {
5968 /* weird case that MS seems to skip */
5969 if (*env_string != '=') {
5970 equal_str = wcschr(env_string, '=');
5971 g_assert(equal_str);
5972 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
5973 mono_array_setref (names, n, str);
5976 while (*env_string != '\0')
5981 FreeEnvironmentStrings (env_strings);
5994 for (e = environ; *e != 0; ++ e)
5997 domain = mono_domain_get ();
5998 names = mono_array_new (domain, mono_defaults.string_class, n);
6001 for (e = environ; *e != 0; ++ e) {
6002 parts = g_strsplit (*e, "=", 2);
6004 str = mono_string_new (domain, *parts);
6005 mono_array_setref (names, n, str);
6018 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6020 #if !GLIB_CHECK_VERSION(2,4,0)
6021 #define g_setenv(a,b,c) setenv(a,b,c)
6022 #define g_unsetenv(a) unsetenv(a)
6026 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6029 gunichar2 *utf16_name, *utf16_value;
6031 gchar *utf8_name, *utf8_value;
6036 utf16_name = mono_string_to_utf16 (name);
6037 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6038 SetEnvironmentVariable (utf16_name, NULL);
6039 g_free (utf16_name);
6043 utf16_value = mono_string_to_utf16 (value);
6045 SetEnvironmentVariable (utf16_name, utf16_value);
6047 g_free (utf16_name);
6048 g_free (utf16_value);
6050 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6052 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6053 g_unsetenv (utf8_name);
6058 utf8_value = mono_string_to_utf8_checked (value, &error);
6059 if (!mono_error_ok (&error)) {
6061 mono_error_raise_exception (&error);
6063 g_setenv (utf8_name, utf8_value, TRUE);
6066 g_free (utf8_value);
6071 ves_icall_System_Environment_Exit (int result)
6073 mono_environment_exitcode_set (result);
6075 /* FIXME: There are some cleanup hangs that should be worked out, but
6076 * if the program is going to exit, everything will be cleaned up when
6077 * NaCl exits anyway.
6079 #ifndef __native_client__
6080 if (!mono_runtime_try_shutdown ())
6081 mono_thread_exit ();
6083 /* Suspend all managed threads since the runtime is going away */
6084 mono_thread_suspend_all_other_threads ();
6086 mono_runtime_quit ();
6089 /* we may need to do some cleanup here... */
6093 ICALL_EXPORT MonoString*
6094 ves_icall_System_Environment_GetGacPath (void)
6096 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6099 ICALL_EXPORT MonoString*
6100 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6102 #if defined (HOST_WIN32)
6103 #ifndef CSIDL_FLAG_CREATE
6104 #define CSIDL_FLAG_CREATE 0x8000
6107 WCHAR path [MAX_PATH];
6108 /* Create directory if no existing */
6109 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6113 return mono_string_new_utf16 (mono_domain_get (), path, len);
6116 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6118 return mono_string_new (mono_domain_get (), "");
6121 ICALL_EXPORT MonoArray *
6122 ves_icall_System_Environment_GetLogicalDrives (void)
6124 gunichar2 buf [256], *ptr, *dname;
6126 guint initial_size = 127, size = 128;
6129 MonoString *drivestr;
6130 MonoDomain *domain = mono_domain_get ();
6136 while (size > initial_size) {
6137 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6138 if (size > initial_size) {
6141 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6142 initial_size = size;
6156 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6161 while (*u16) { u16++; len ++; }
6162 drivestr = mono_string_new_utf16 (domain, dname, len);
6163 mono_array_setref (result, ndrives++, drivestr);
6173 ICALL_EXPORT MonoString *
6174 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6176 gunichar2 volume_name [MAX_PATH + 1];
6178 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6180 return mono_string_from_utf16 (volume_name);
6183 ICALL_EXPORT MonoString *
6184 ves_icall_System_Environment_InternalGetHome (void)
6186 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6189 static const char *encodings [] = {
6191 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6192 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6193 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6195 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6196 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6197 "x_unicode_2_0_utf_7",
6199 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6200 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6202 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6205 "unicodefffe", "utf_16be",
6212 * Returns the internal codepage, if the value of "int_code_page" is
6213 * 1 at entry, and we can not compute a suitable code page number,
6214 * returns the code page as a string
6216 ICALL_EXPORT MonoString*
6217 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6222 char *codepage = NULL;
6224 int want_name = *int_code_page;
6227 *int_code_page = -1;
6229 g_get_charset (&cset);
6230 c = codepage = strdup (cset);
6231 for (c = codepage; *c; c++){
6232 if (isascii (*c) && isalpha (*c))
6237 /* g_print ("charset: %s\n", cset); */
6239 /* handle some common aliases */
6242 for (i = 0; p != 0; ){
6245 p = encodings [++i];
6248 if (strcmp (p, codepage) == 0){
6249 *int_code_page = code;
6252 p = encodings [++i];
6255 if (strstr (codepage, "utf_8") != NULL)
6256 *int_code_page |= 0x10000000;
6259 if (want_name && *int_code_page == -1)
6260 return mono_string_new (mono_domain_get (), cset);
6265 ICALL_EXPORT MonoBoolean
6266 ves_icall_System_Environment_get_HasShutdownStarted (void)
6268 if (mono_runtime_is_shutting_down ())
6271 if (mono_domain_is_unloading (mono_domain_get ()))
6278 ves_icall_System_Environment_BroadcastSettingChange (void)
6281 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6286 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6292 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6293 MonoReflectionMethod *method,
6294 MonoArray *out_args)
6296 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6299 #ifndef DISABLE_REMOTING
6300 ICALL_EXPORT MonoBoolean
6301 ves_icall_IsTransparentProxy (MonoObject *proxy)
6306 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6312 ICALL_EXPORT MonoReflectionMethod *
6313 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6314 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6318 MonoMethod **vtable;
6319 MonoMethod *res = NULL;
6321 MONO_CHECK_ARG_NULL (rtype, NULL);
6322 MONO_CHECK_ARG_NULL (rmethod, NULL);
6324 method = rmethod->method;
6325 klass = mono_class_from_mono_type (rtype->type);
6326 mono_class_init_or_throw (klass);
6328 if (MONO_CLASS_IS_INTERFACE (klass))
6331 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6334 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6335 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6341 mono_class_setup_vtable (klass);
6342 vtable = klass->vtable;
6344 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6345 gboolean variance_used = FALSE;
6346 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6347 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6349 res = vtable [offs + method->slot];
6351 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6354 if (method->slot != -1)
6355 res = vtable [method->slot];
6361 return mono_method_get_object (mono_domain_get (), res, NULL);
6365 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6370 klass = mono_class_from_mono_type (type->type);
6371 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6373 mono_vtable_set_is_remote (vtable, enable);
6376 #else /* DISABLE_REMOTING */
6379 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6381 g_assert_not_reached ();
6386 ICALL_EXPORT MonoObject *
6387 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6392 domain = mono_object_domain (type);
6393 klass = mono_class_from_mono_type (type->type);
6394 mono_class_init_or_throw (klass);
6396 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6397 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6401 if (klass->rank >= 1) {
6402 g_assert (klass->rank == 1);
6403 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6405 /* Bypass remoting object creation check */
6406 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6410 ICALL_EXPORT MonoString *
6411 ves_icall_System_IO_get_temp_path (void)
6413 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6416 #ifndef PLATFORM_NO_DRIVEINFO
6417 ICALL_EXPORT MonoBoolean
6418 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6419 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6423 ULARGE_INTEGER wapi_free_bytes_avail;
6424 ULARGE_INTEGER wapi_total_number_of_bytes;
6425 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6427 *error = ERROR_SUCCESS;
6428 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6429 &wapi_total_number_of_free_bytes);
6432 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6433 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6434 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6436 *free_bytes_avail = 0;
6437 *total_number_of_bytes = 0;
6438 *total_number_of_free_bytes = 0;
6439 *error = GetLastError ();
6445 ICALL_EXPORT guint32
6446 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6448 return GetDriveType (mono_string_chars (root_path_name));
6452 ICALL_EXPORT gpointer
6453 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6455 return mono_compile_method (method);
6458 ICALL_EXPORT MonoString *
6459 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6464 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6466 #if defined (HOST_WIN32)
6467 /* Avoid mixing '/' and '\\' */
6470 for (i = strlen (path) - 1; i >= 0; i--)
6471 if (path [i] == '/')
6475 mcpath = mono_string_new (mono_domain_get (), path);
6482 get_bundled_app_config (void)
6484 const gchar *app_config;
6487 gchar *config_file_name, *config_file_path;
6488 gsize len, config_file_path_length, config_ext_length;
6491 domain = mono_domain_get ();
6492 file = domain->setup->configuration_file;
6493 if (!file || file->length == 0)
6496 // Retrieve config file and remove the extension
6497 config_file_name = mono_string_to_utf8 (file);
6498 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6499 if (!config_file_path)
6500 config_file_path = config_file_name;
6502 config_file_path_length = strlen (config_file_path);
6503 config_ext_length = strlen (".config");
6504 if (config_file_path_length <= config_ext_length)
6507 len = config_file_path_length - config_ext_length;
6508 module = (gchar *)g_malloc0 (len + 1);
6509 memcpy (module, config_file_path, len);
6510 // Get the config file from the module name
6511 app_config = mono_config_string_for_assembly_file (module);
6514 if (config_file_name != config_file_path)
6515 g_free (config_file_name);
6516 g_free (config_file_path);
6521 return mono_string_new (mono_domain_get (), app_config);
6525 get_bundled_machine_config (void)
6527 const gchar *machine_config;
6529 machine_config = mono_get_machine_config ();
6531 if (!machine_config)
6534 return mono_string_new (mono_domain_get (), machine_config);
6537 ICALL_EXPORT MonoString *
6538 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6543 path = g_path_get_dirname (mono_get_config_dir ());
6545 #if defined (HOST_WIN32)
6546 /* Avoid mixing '/' and '\\' */
6549 for (i = strlen (path) - 1; i >= 0; i--)
6550 if (path [i] == '/')
6554 ipath = mono_string_new (mono_domain_get (), path);
6560 ICALL_EXPORT gboolean
6561 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6563 MonoPEResourceDataEntry *entry;
6566 if (!assembly || !result || !size)
6571 image = assembly->assembly->image;
6572 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6576 *result = mono_image_rva_map (image, entry->rde_data_offset);
6581 *size = entry->rde_size;
6586 ICALL_EXPORT MonoBoolean
6587 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6589 return mono_is_debugger_attached ();
6592 ICALL_EXPORT MonoBoolean
6593 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
6595 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
6596 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
6602 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
6604 if (mono_get_runtime_callbacks ()->debug_log)
6605 mono_get_runtime_callbacks ()->debug_log (level, category, message);
6609 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6611 #if defined (HOST_WIN32)
6612 OutputDebugString (mono_string_chars (message));
6614 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6618 /* Only used for value types */
6619 ICALL_EXPORT MonoObject *
6620 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6625 domain = mono_object_domain (type);
6626 klass = mono_class_from_mono_type (type->type);
6627 mono_class_init_or_throw (klass);
6629 if (mono_class_is_nullable (klass))
6630 /* No arguments -> null */
6633 return mono_object_new (domain, klass);
6636 ICALL_EXPORT MonoReflectionMethod *
6637 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6639 MonoClass *klass, *parent;
6640 MonoGenericContext *generic_inst = NULL;
6641 MonoMethod *method = m->method;
6642 MonoMethod *result = NULL;
6645 if (method->klass == NULL)
6648 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6649 MONO_CLASS_IS_INTERFACE (method->klass) ||
6650 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6653 slot = mono_method_get_vtable_slot (method);
6657 klass = method->klass;
6658 if (klass->generic_class) {
6659 generic_inst = mono_class_get_context (klass);
6660 klass = klass->generic_class->container_class;
6664 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6665 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6666 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6667 or klass is the generic container class and generic_inst is the instantiation.
6669 when we go to the parent, if the parent is an open constructed type, we need to
6670 replace the type parameters by the definitions from the generic_inst, and then take it
6671 apart again into the klass and the generic_inst.
6673 For cases like this:
6674 class C<T> : B<T, int> {
6675 public override void Foo () { ... }
6677 class B<U,V> : A<HashMap<U,V>> {
6678 public override void Foo () { ... }
6681 public virtual void Foo () { ... }
6684 if at each iteration the parent isn't open, we can skip inflating it. if at some
6685 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6688 MonoGenericContext *parent_inst = NULL;
6689 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
6691 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
6692 mono_error_raise_exception(&error);
6694 if (parent->generic_class) {
6695 parent_inst = mono_class_get_context (parent);
6696 parent = parent->generic_class->container_class;
6699 mono_class_setup_vtable (parent);
6700 if (parent->vtable_size <= slot)
6703 generic_inst = parent_inst;
6706 klass = klass->parent;
6709 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
6711 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6712 mono_error_raise_exception(&error);
6714 generic_inst = NULL;
6716 if (klass->generic_class) {
6717 generic_inst = mono_class_get_context (klass);
6718 klass = klass->generic_class->container_class;
6725 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6726 mono_error_raise_exception(&error);
6729 if (klass == method->klass)
6732 /*This is possible if definition == FALSE.
6733 * Do it here to be really sure we don't read invalid memory.
6735 if (slot >= klass->vtable_size)
6738 mono_class_setup_vtable (klass);
6740 result = klass->vtable [slot];
6741 if (result == NULL) {
6742 /* It is an abstract method */
6743 gpointer iter = NULL;
6744 while ((result = mono_class_get_methods (klass, &iter)))
6745 if (result->slot == slot)
6752 return mono_method_get_object (mono_domain_get (), result, NULL);
6755 ICALL_EXPORT MonoString*
6756 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6758 MonoMethod *method = m->method;
6760 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6765 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6767 iter->sig = *(MonoMethodSignature**)argsp;
6769 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6770 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6773 /* FIXME: it's not documented what start is exactly... */
6777 iter->args = argsp + sizeof (gpointer);
6779 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6781 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6784 ICALL_EXPORT MonoTypedRef
6785 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6787 guint32 i, arg_size;
6791 i = iter->sig->sentinelpos + iter->next_arg;
6793 g_assert (i < iter->sig->param_count);
6795 res.type = iter->sig->params [i];
6796 res.klass = mono_class_from_mono_type (res.type);
6797 arg_size = mono_type_stack_size (res.type, &align);
6798 #if defined(__arm__) || defined(__mips__)
6799 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6801 res.value = iter->args;
6802 #if defined(__native_client__) && SIZEOF_REGISTER == 8
6803 /* Values are stored as 8 byte register sized objects, but 'value'
6804 * is dereferenced as a pointer in other routines.
6806 res.value = (char*)res.value + 4;
6808 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6809 if (arg_size <= sizeof (gpointer)) {
6811 int padding = arg_size - mono_type_size (res.type, &dummy);
6812 res.value = (guint8*)res.value + padding;
6815 iter->args = (char*)iter->args + arg_size;
6818 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6823 ICALL_EXPORT MonoTypedRef
6824 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6826 guint32 i, arg_size;
6830 i = iter->sig->sentinelpos + iter->next_arg;
6832 g_assert (i < iter->sig->param_count);
6834 while (i < iter->sig->param_count) {
6835 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6837 res.type = iter->sig->params [i];
6838 res.klass = mono_class_from_mono_type (res.type);
6839 /* FIXME: endianess issue... */
6840 arg_size = mono_type_stack_size (res.type, &align);
6841 #if defined(__arm__) || defined(__mips__)
6842 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6844 res.value = iter->args;
6845 iter->args = (char*)iter->args + arg_size;
6847 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6850 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6858 ICALL_EXPORT MonoType*
6859 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6863 i = iter->sig->sentinelpos + iter->next_arg;
6865 g_assert (i < iter->sig->param_count);
6867 return iter->sig->params [i];
6870 ICALL_EXPORT MonoObject*
6871 mono_TypedReference_ToObject (MonoTypedRef* tref)
6873 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
6874 MonoObject** objp = (MonoObject **)tref->value;
6878 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
6881 ICALL_EXPORT MonoTypedRef
6882 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
6885 MonoReflectionField *f;
6887 MonoType *ftype = NULL;
6891 memset (&res, 0, sizeof (res));
6894 g_assert (mono_array_length (fields) > 0);
6896 klass = target->vtable->klass;
6898 for (i = 0; i < mono_array_length (fields); ++i) {
6899 f = mono_array_get (fields, MonoReflectionField*, i);
6901 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
6904 if (f->field->parent != klass) {
6905 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
6909 p = (guint8*)target + f->field->offset;
6911 p += f->field->offset - sizeof (MonoObject);
6912 klass = mono_class_from_mono_type (f->field->type);
6913 ftype = f->field->type;
6917 res.klass = mono_class_from_mono_type (ftype);
6924 prelink_method (MonoMethod *method)
6926 const char *exc_class, *exc_arg;
6927 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6929 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6931 mono_raise_exception(
6932 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6934 /* create the wrapper, too? */
6938 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6940 prelink_method (method->method);
6944 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6946 MonoClass *klass = mono_class_from_mono_type (type->type);
6948 gpointer iter = NULL;
6950 mono_class_init_or_throw (klass);
6952 while ((m = mono_class_get_methods (klass, &iter)))
6956 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
6958 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
6959 gint32 const **exponents,
6960 gunichar2 const **digitLowerTable,
6961 gunichar2 const **digitUpperTable,
6962 gint64 const **tenPowersList,
6963 gint32 const **decHexDigits)
6965 *mantissas = Formatter_MantissaBitsTable;
6966 *exponents = Formatter_TensExponentTable;
6967 *digitLowerTable = Formatter_DigitLowerTable;
6968 *digitUpperTable = Formatter_DigitUpperTable;
6969 *tenPowersList = Formatter_TenPowersList;
6970 *decHexDigits = Formatter_DecHexDigits;
6974 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
6975 * and avoid useless allocations.
6980 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
6984 for (i = 0; i < type->num_mods; ++i) {
6985 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
6990 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
6992 for (i = 0; i < type->num_mods; ++i) {
6993 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
6995 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
6996 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
6997 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7004 ICALL_EXPORT MonoArray*
7005 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7007 MonoType *type = param->ClassImpl->type;
7008 MonoClass *member_class = mono_object_class (param->MemberImpl);
7009 MonoMethod *method = NULL;
7012 MonoMethodSignature *sig;
7014 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7015 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7016 method = rmethod->method;
7017 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7018 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7019 if (!(method = prop->property->get))
7020 method = prop->property->set;
7023 char *type_name = mono_type_get_full_name (member_class);
7024 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7025 MonoException *ex = mono_get_exception_not_supported (msg);
7028 mono_set_pending_exception (ex);
7032 image = method->klass->image;
7033 pos = param->PositionImpl;
7034 sig = mono_method_signature (method);
7038 type = sig->params [pos];
7040 return type_array_from_modifiers (image, type, optional);
7044 get_property_type (MonoProperty *prop)
7046 MonoMethodSignature *sig;
7048 sig = mono_method_signature (prop->get);
7050 } else if (prop->set) {
7051 sig = mono_method_signature (prop->set);
7052 return sig->params [sig->param_count - 1];
7057 ICALL_EXPORT MonoArray*
7058 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7060 MonoType *type = get_property_type (property->property);
7061 MonoImage *image = property->klass->image;
7065 return type_array_from_modifiers (image, type, optional);
7069 *Construct a MonoType suited to be used to decode a constant blob object.
7071 * @type is the target type which will be constructed
7072 * @blob_type is the blob type, for example, that comes from the constant table
7073 * @real_type is the expected constructed type.
7076 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7078 type->type = blob_type;
7079 type->data.klass = NULL;
7080 if (blob_type == MONO_TYPE_CLASS)
7081 type->data.klass = mono_defaults.object_class;
7082 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7083 /* For enums, we need to use the base type */
7084 type->type = MONO_TYPE_VALUETYPE;
7085 type->data.klass = mono_class_from_mono_type (real_type);
7087 type->data.klass = mono_class_from_mono_type (real_type);
7090 ICALL_EXPORT MonoObject*
7091 property_info_get_default_value (MonoReflectionProperty *property)
7094 MonoProperty *prop = property->property;
7095 MonoType *type = get_property_type (prop);
7096 MonoDomain *domain = mono_object_domain (property);
7097 MonoTypeEnum def_type;
7098 const char *def_value;
7101 mono_class_init (prop->parent);
7103 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7104 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7108 def_value = mono_class_get_property_default_value (prop, &def_type);
7110 mono_type_from_blob_type (&blob_type, def_type, type);
7111 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7116 ICALL_EXPORT MonoBoolean
7117 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7119 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7120 MonoCustomAttrInfo *cinfo;
7123 mono_class_init_or_throw (attr_class);
7125 cinfo = mono_reflection_get_custom_attrs_info (obj);
7128 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7130 mono_custom_attrs_free (cinfo);
7134 ICALL_EXPORT MonoArray*
7135 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7137 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7142 mono_class_init_or_throw (attr_class);
7144 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7145 mono_error_raise_exception (&error);
7147 if (mono_loader_get_last_error ()) {
7148 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7155 ICALL_EXPORT MonoString*
7156 ves_icall_Mono_Runtime_GetDisplayName (void)
7159 MonoString *display_name;
7161 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7162 display_name = mono_string_new (mono_domain_get (), info);
7164 return display_name;
7167 ICALL_EXPORT MonoString*
7168 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7170 MonoString *message;
7174 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7175 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7178 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7180 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7187 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7190 char *path_str = mono_string_to_utf8 (path);
7192 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7200 #ifndef DISABLE_ICALL_TABLES
7202 #define ICALL_TYPE(id,name,first)
7203 #define ICALL(id,name,func) Icall_ ## id,
7206 #include "metadata/icall-def.h"
7212 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7213 #define ICALL(id,name,func)
7215 #include "metadata/icall-def.h"
7221 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7222 #define ICALL(id,name,func)
7224 guint16 first_icall;
7227 static const IcallTypeDesc
7228 icall_type_descs [] = {
7229 #include "metadata/icall-def.h"
7233 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7236 #define ICALL_TYPE(id,name,first)
7239 #ifdef HAVE_ARRAY_ELEM_INIT
7240 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7241 #define MSGSTRFIELD1(line) str##line
7243 static const struct msgstrtn_t {
7244 #define ICALL(id,name,func)
7246 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7247 #include "metadata/icall-def.h"
7249 } icall_type_names_str = {
7250 #define ICALL_TYPE(id,name,first) (name),
7251 #include "metadata/icall-def.h"
7254 static const guint16 icall_type_names_idx [] = {
7255 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7256 #include "metadata/icall-def.h"
7259 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7261 static const struct msgstr_t {
7263 #define ICALL_TYPE(id,name,first)
7264 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7265 #include "metadata/icall-def.h"
7267 } icall_names_str = {
7268 #define ICALL(id,name,func) (name),
7269 #include "metadata/icall-def.h"
7272 static const guint16 icall_names_idx [] = {
7273 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7274 #include "metadata/icall-def.h"
7277 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7283 #define ICALL_TYPE(id,name,first) name,
7284 #define ICALL(id,name,func)
7285 static const char* const
7286 icall_type_names [] = {
7287 #include "metadata/icall-def.h"
7291 #define icall_type_name_get(id) (icall_type_names [(id)])
7295 #define ICALL_TYPE(id,name,first)
7296 #define ICALL(id,name,func) name,
7297 static const char* const
7299 #include "metadata/icall-def.h"
7302 #define icall_name_get(id) icall_names [(id)]
7304 #endif /* !HAVE_ARRAY_ELEM_INIT */
7308 #define ICALL_TYPE(id,name,first)
7309 #define ICALL(id,name,func) func,
7310 static const gconstpointer
7311 icall_functions [] = {
7312 #include "metadata/icall-def.h"
7316 #ifdef ENABLE_ICALL_SYMBOL_MAP
7319 #define ICALL_TYPE(id,name,first)
7320 #define ICALL(id,name,func) #func,
7321 static const gconstpointer
7322 icall_symbols [] = {
7323 #include "metadata/icall-def.h"
7328 #endif /* DISABLE_ICALL_TABLES */
7330 static mono_mutex_t icall_mutex;
7331 static GHashTable *icall_hash = NULL;
7332 static GHashTable *jit_icall_hash_name = NULL;
7333 static GHashTable *jit_icall_hash_addr = NULL;
7336 mono_icall_init (void)
7338 #ifndef DISABLE_ICALL_TABLES
7341 /* check that tables are sorted: disable in release */
7344 const char *prev_class = NULL;
7345 const char *prev_method;
7347 for (i = 0; i < Icall_type_num; ++i) {
7348 const IcallTypeDesc *desc;
7351 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7352 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7353 prev_class = icall_type_name_get (i);
7354 desc = &icall_type_descs [i];
7355 num_icalls = icall_desc_num_icalls (desc);
7356 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7357 for (j = 0; j < num_icalls; ++j) {
7358 const char *methodn = icall_name_get (desc->first_icall + j);
7359 if (prev_method && strcmp (prev_method, methodn) >= 0)
7360 g_print ("method %s should come before method %s\n", methodn, prev_method);
7361 prev_method = methodn;
7367 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7368 mono_os_mutex_init (&icall_mutex);
7372 mono_icall_lock (void)
7374 mono_locks_os_acquire (&icall_mutex, IcallLock);
7378 mono_icall_unlock (void)
7380 mono_locks_os_release (&icall_mutex, IcallLock);
7384 mono_icall_cleanup (void)
7386 g_hash_table_destroy (icall_hash);
7387 g_hash_table_destroy (jit_icall_hash_name);
7388 g_hash_table_destroy (jit_icall_hash_addr);
7389 mono_os_mutex_destroy (&icall_mutex);
7393 mono_add_internal_call (const char *name, gconstpointer method)
7397 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7399 mono_icall_unlock ();
7402 #ifndef DISABLE_ICALL_TABLES
7404 #ifdef HAVE_ARRAY_ELEM_INIT
7406 compare_method_imap (const void *key, const void *elem)
7408 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7409 return strcmp (key, method_name);
7413 find_method_icall (const IcallTypeDesc *imap, const char *name)
7415 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);
7418 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7422 compare_class_imap (const void *key, const void *elem)
7424 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7425 return strcmp (key, class_name);
7428 static const IcallTypeDesc*
7429 find_class_icalls (const char *name)
7431 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);
7434 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7437 #else /* HAVE_ARRAY_ELEM_INIT */
7440 compare_method_imap (const void *key, const void *elem)
7442 const char** method_name = (const char**)elem;
7443 return strcmp (key, *method_name);
7447 find_method_icall (const IcallTypeDesc *imap, const char *name)
7449 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7452 return (gpointer)icall_functions [(nameslot - icall_names)];
7456 compare_class_imap (const void *key, const void *elem)
7458 const char** class_name = (const char**)elem;
7459 return strcmp (key, *class_name);
7462 static const IcallTypeDesc*
7463 find_class_icalls (const char *name)
7465 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7468 return &icall_type_descs [nameslot - icall_type_names];
7471 #endif /* HAVE_ARRAY_ELEM_INIT */
7473 #endif /* DISABLE_ICALL_TABLES */
7476 * we should probably export this as an helper (handle nested types).
7477 * Returns the number of chars written in buf.
7480 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7482 int nspacelen, cnamelen;
7483 nspacelen = strlen (klass->name_space);
7484 cnamelen = strlen (klass->name);
7485 if (nspacelen + cnamelen + 2 > bufsize)
7488 memcpy (buf, klass->name_space, nspacelen);
7489 buf [nspacelen ++] = '.';
7491 memcpy (buf + nspacelen, klass->name, cnamelen);
7492 buf [nspacelen + cnamelen] = 0;
7493 return nspacelen + cnamelen;
7496 #ifdef DISABLE_ICALL_TABLES
7498 no_icall_table (void)
7500 g_assert_not_reached ();
7505 mono_lookup_internal_call (MonoMethod *method)
7510 int typelen = 0, mlen, siglen;
7512 #ifndef DISABLE_ICALL_TABLES
7513 const IcallTypeDesc *imap = NULL;
7516 g_assert (method != NULL);
7518 if (method->is_inflated)
7519 method = ((MonoMethodInflated *) method)->declaring;
7521 if (method->klass->nested_in) {
7522 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7526 mname [pos++] = '/';
7529 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7535 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7540 #ifndef DISABLE_ICALL_TABLES
7541 imap = find_class_icalls (mname);
7544 mname [typelen] = ':';
7545 mname [typelen + 1] = ':';
7547 mlen = strlen (method->name);
7548 memcpy (mname + typelen + 2, method->name, mlen);
7549 sigstart = mname + typelen + 2 + mlen;
7552 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7553 siglen = strlen (tmpsig);
7554 if (typelen + mlen + siglen + 6 > sizeof (mname))
7557 memcpy (sigstart + 1, tmpsig, siglen);
7558 sigstart [siglen + 1] = ')';
7559 sigstart [siglen + 2] = 0;
7564 res = g_hash_table_lookup (icall_hash, mname);
7566 mono_icall_unlock ();;
7569 /* try without signature */
7571 res = g_hash_table_lookup (icall_hash, mname);
7573 mono_icall_unlock ();
7577 #ifdef DISABLE_ICALL_TABLES
7578 mono_icall_unlock ();
7579 /* Fail only when the result is actually used */
7580 /* mono_marshal_get_native_wrapper () depends on this */
7581 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
7582 return ves_icall_System_String_ctor_RedirectToCreateString;
7584 return no_icall_table;
7586 /* it wasn't found in the static call tables */
7588 mono_icall_unlock ();
7591 res = find_method_icall (imap, sigstart - mlen);
7593 mono_icall_unlock ();
7596 /* try _with_ signature */
7598 res = find_method_icall (imap, sigstart - mlen);
7600 mono_icall_unlock ();
7604 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7605 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7606 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7607 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
7608 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");
7609 g_print ("If you see other errors or faults after this message they are probably related\n");
7610 g_print ("and you need to fix your mono install first.\n");
7612 mono_icall_unlock ();
7618 #ifdef ENABLE_ICALL_SYMBOL_MAP
7620 func_cmp (gconstpointer key, gconstpointer p)
7622 return (gsize)key - (gsize)*(gsize*)p;
7627 * mono_lookup_icall_symbol:
7629 * Given the icall METHOD, returns its C symbol.
7632 mono_lookup_icall_symbol (MonoMethod *m)
7634 #ifdef DISABLE_ICALL_TABLES
7635 g_assert_not_reached ();
7638 #ifdef ENABLE_ICALL_SYMBOL_MAP
7642 static gconstpointer *functions_sorted;
7643 static const char**symbols_sorted;
7644 static gboolean inited;
7649 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7650 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7651 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7652 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7653 /* Bubble sort the two arrays */
7657 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
7658 if (functions_sorted [i] > functions_sorted [i + 1]) {
7661 tmp = functions_sorted [i];
7662 functions_sorted [i] = functions_sorted [i + 1];
7663 functions_sorted [i + 1] = tmp;
7664 tmp = symbols_sorted [i];
7665 symbols_sorted [i] = symbols_sorted [i + 1];
7666 symbols_sorted [i + 1] = tmp;
7673 func = mono_lookup_internal_call (m);
7676 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
7680 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
7682 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
7683 g_assert_not_reached ();
7690 type_from_typename (char *type_name)
7692 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7694 if (!strcmp (type_name, "int"))
7695 klass = mono_defaults.int_class;
7696 else if (!strcmp (type_name, "ptr"))
7697 klass = mono_defaults.int_class;
7698 else if (!strcmp (type_name, "void"))
7699 klass = mono_defaults.void_class;
7700 else if (!strcmp (type_name, "int32"))
7701 klass = mono_defaults.int32_class;
7702 else if (!strcmp (type_name, "uint32"))
7703 klass = mono_defaults.uint32_class;
7704 else if (!strcmp (type_name, "int8"))
7705 klass = mono_defaults.sbyte_class;
7706 else if (!strcmp (type_name, "uint8"))
7707 klass = mono_defaults.byte_class;
7708 else if (!strcmp (type_name, "int16"))
7709 klass = mono_defaults.int16_class;
7710 else if (!strcmp (type_name, "uint16"))
7711 klass = mono_defaults.uint16_class;
7712 else if (!strcmp (type_name, "long"))
7713 klass = mono_defaults.int64_class;
7714 else if (!strcmp (type_name, "ulong"))
7715 klass = mono_defaults.uint64_class;
7716 else if (!strcmp (type_name, "float"))
7717 klass = mono_defaults.single_class;
7718 else if (!strcmp (type_name, "double"))
7719 klass = mono_defaults.double_class;
7720 else if (!strcmp (type_name, "object"))
7721 klass = mono_defaults.object_class;
7722 else if (!strcmp (type_name, "obj"))
7723 klass = mono_defaults.object_class;
7724 else if (!strcmp (type_name, "string"))
7725 klass = mono_defaults.string_class;
7726 else if (!strcmp (type_name, "bool"))
7727 klass = mono_defaults.boolean_class;
7728 else if (!strcmp (type_name, "boolean"))
7729 klass = mono_defaults.boolean_class;
7731 g_error ("%s", type_name);
7732 g_assert_not_reached ();
7734 return &klass->byval_arg;
7738 * LOCKING: Take the corlib image lock.
7740 MonoMethodSignature*
7741 mono_create_icall_signature (const char *sigstr)
7746 MonoMethodSignature *res, *res2;
7747 MonoImage *corlib = mono_defaults.corlib;
7749 mono_image_lock (corlib);
7750 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7751 mono_image_unlock (corlib);
7756 parts = g_strsplit (sigstr, " ", 256);
7765 res = mono_metadata_signature_alloc (corlib, len - 1);
7770 * Under windows, the default pinvoke calling convention is STDCALL but
7773 res->call_convention = MONO_CALL_C;
7776 res->ret = type_from_typename (parts [0]);
7777 for (i = 1; i < len; ++i) {
7778 res->params [i - 1] = type_from_typename (parts [i]);
7783 mono_image_lock (corlib);
7784 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7786 res = res2; /*Value is allocated in the image pool*/
7788 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
7789 mono_image_unlock (corlib);
7795 mono_find_jit_icall_by_name (const char *name)
7797 MonoJitICallInfo *info;
7798 g_assert (jit_icall_hash_name);
7801 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7802 mono_icall_unlock ();
7807 mono_find_jit_icall_by_addr (gconstpointer addr)
7809 MonoJitICallInfo *info;
7810 g_assert (jit_icall_hash_addr);
7813 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7814 mono_icall_unlock ();
7820 * mono_get_jit_icall_info:
7822 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7823 * caller should access it while holding the icall lock.
7826 mono_get_jit_icall_info (void)
7828 return jit_icall_hash_name;
7832 * mono_lookup_jit_icall_symbol:
7834 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
7837 mono_lookup_jit_icall_symbol (const char *name)
7839 MonoJitICallInfo *info;
7840 const char *res = NULL;
7843 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7845 res = info->c_symbol;
7846 mono_icall_unlock ();
7851 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7854 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7855 mono_icall_unlock ();
7859 * 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
7860 * icalls without wrappers in some cases.
7863 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
7865 MonoJitICallInfo *info;
7872 if (!jit_icall_hash_name) {
7873 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7874 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7877 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7878 g_warning ("jit icall already defined \"%s\"\n", name);
7879 g_assert_not_reached ();
7882 info = g_new0 (MonoJitICallInfo, 1);
7887 info->c_symbol = c_symbol;
7888 info->no_raise = no_raise;
7891 info->wrapper = func;
7893 info->wrapper = NULL;
7896 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7897 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7899 mono_icall_unlock ();
7904 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7906 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);