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 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
104 #include <sys/utsname.h>
107 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
109 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
114 static inline MonoBoolean
115 is_generic_parameter (MonoType *type)
117 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
121 mono_class_init_or_throw (MonoClass *klass)
123 if (!mono_class_init (klass))
124 mono_raise_exception (mono_class_get_exception_for_failure (klass));
127 ICALL_EXPORT MonoObject *
128 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
134 ac = (MonoClass *)arr->obj.vtable->klass;
136 esize = mono_array_element_size (ac);
137 ea = (gpointer*)((char*)arr->vector + (pos * esize));
139 if (ac->element_class->valuetype)
140 return mono_value_box (arr->obj.vtable->domain, ac->element_class, ea);
142 return (MonoObject *)*ea;
145 ICALL_EXPORT MonoObject *
146 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
152 MONO_CHECK_ARG_NULL (idxs, NULL);
155 ic = (MonoClass *)io->obj.vtable->klass;
157 ac = (MonoClass *)arr->obj.vtable->klass;
159 g_assert (ic->rank == 1);
160 if (io->bounds != NULL || io->max_length != ac->rank) {
161 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
165 ind = (gint32 *)io->vector;
167 if (arr->bounds == NULL) {
168 if (*ind < 0 || *ind >= arr->max_length) {
169 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
173 return ves_icall_System_Array_GetValueImpl (arr, *ind);
176 for (i = 0; i < ac->rank; i++) {
177 if ((ind [i] < arr->bounds [i].lower_bound) ||
178 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
179 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
184 pos = ind [0] - arr->bounds [0].lower_bound;
185 for (i = 1; i < ac->rank; i++)
186 pos = pos * arr->bounds [i].length + ind [i] -
187 arr->bounds [i].lower_bound;
189 return ves_icall_System_Array_GetValueImpl (arr, pos);
193 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
195 MonoClass *ac, *vc, *ec;
205 vc = value->vtable->klass;
209 ac = arr->obj.vtable->klass;
210 ec = ac->element_class;
212 esize = mono_array_element_size (ac);
213 ea = (gpointer*)((char*)arr->vector + (pos * esize));
214 va = (gpointer*)((char*)value + sizeof (MonoObject));
216 if (mono_class_is_nullable (ec)) {
217 mono_nullable_init ((guint8*)ea, value, ec);
222 mono_gc_bzero_atomic (ea, esize);
226 #define NO_WIDENING_CONVERSION G_STMT_START{\
227 mono_set_pending_exception (mono_get_exception_argument ( \
228 "value", "not a widening conversion")); \
232 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
233 if (esize < vsize + (extra)) { \
234 mono_set_pending_exception (mono_get_exception_argument ( \
235 "value", "not a widening conversion")); \
240 #define INVALID_CAST G_STMT_START{ \
241 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
242 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
246 /* Check element (destination) type. */
247 switch (ec->byval_arg.type) {
248 case MONO_TYPE_STRING:
249 switch (vc->byval_arg.type) {
250 case MONO_TYPE_STRING:
256 case MONO_TYPE_BOOLEAN:
257 switch (vc->byval_arg.type) {
258 case MONO_TYPE_BOOLEAN:
271 NO_WIDENING_CONVERSION;
280 if (!ec->valuetype) {
281 if (!mono_object_isinst (value, ec))
283 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
287 if (mono_object_isinst (value, ec)) {
288 if (ec->has_references)
289 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
291 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
298 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
300 et = ec->byval_arg.type;
301 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
302 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
304 vt = vc->byval_arg.type;
305 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
306 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
308 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
314 case MONO_TYPE_CHAR: \
315 CHECK_WIDENING_CONVERSION(0); \
316 *(etype *) ea = (etype) u64; \
318 /* You can't assign a signed value to an unsigned array. */ \
323 /* You can't assign a floating point number to an integer array. */ \
326 NO_WIDENING_CONVERSION; \
330 #define ASSIGN_SIGNED(etype) G_STMT_START{\
336 CHECK_WIDENING_CONVERSION(0); \
337 *(etype *) ea = (etype) i64; \
339 /* You can assign an unsigned value to a signed array if the array's */ \
340 /* element size is larger than the value size. */ \
345 case MONO_TYPE_CHAR: \
346 CHECK_WIDENING_CONVERSION(1); \
347 *(etype *) ea = (etype) u64; \
349 /* You can't assign a floating point number to an integer array. */ \
352 NO_WIDENING_CONVERSION; \
356 #define ASSIGN_REAL(etype) G_STMT_START{\
360 CHECK_WIDENING_CONVERSION(0); \
361 *(etype *) ea = (etype) r64; \
363 /* All integer values fit into a floating point array, so we don't */ \
364 /* need to CHECK_WIDENING_CONVERSION here. */ \
369 *(etype *) ea = (etype) i64; \
375 case MONO_TYPE_CHAR: \
376 *(etype *) ea = (etype) u64; \
383 u64 = *(guint8 *) va;
386 u64 = *(guint16 *) va;
389 u64 = *(guint32 *) va;
392 u64 = *(guint64 *) va;
398 i64 = *(gint16 *) va;
401 i64 = *(gint32 *) va;
404 i64 = *(gint64 *) va;
407 r64 = *(gfloat *) va;
410 r64 = *(gdouble *) va;
413 u64 = *(guint16 *) va;
415 case MONO_TYPE_BOOLEAN:
416 /* Boolean is only compatible with itself. */
429 NO_WIDENING_CONVERSION;
436 /* If we can't do a direct copy, let's try a widening conversion. */
439 ASSIGN_UNSIGNED (guint16);
441 ASSIGN_UNSIGNED (guint8);
443 ASSIGN_UNSIGNED (guint16);
445 ASSIGN_UNSIGNED (guint32);
447 ASSIGN_UNSIGNED (guint64);
449 ASSIGN_SIGNED (gint8);
451 ASSIGN_SIGNED (gint16);
453 ASSIGN_SIGNED (gint32);
455 ASSIGN_SIGNED (gint64);
457 ASSIGN_REAL (gfloat);
459 ASSIGN_REAL (gdouble);
463 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
467 #undef NO_WIDENING_CONVERSION
468 #undef CHECK_WIDENING_CONVERSION
469 #undef ASSIGN_UNSIGNED
475 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
481 MONO_CHECK_ARG_NULL (idxs,);
483 ic = idxs->obj.vtable->klass;
484 ac = arr->obj.vtable->klass;
486 g_assert (ic->rank == 1);
487 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
488 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
492 ind = (gint32 *)idxs->vector;
494 if (arr->bounds == NULL) {
495 if (*ind < 0 || *ind >= arr->max_length) {
496 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
500 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
504 for (i = 0; i < ac->rank; i++)
505 if ((ind [i] < arr->bounds [i].lower_bound) ||
506 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
507 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
511 pos = ind [0] - arr->bounds [0].lower_bound;
512 for (i = 1; i < ac->rank; i++)
513 pos = pos * arr->bounds [i].length + ind [i] -
514 arr->bounds [i].lower_bound;
516 ves_icall_System_Array_SetValueImpl (arr, value, pos);
519 ICALL_EXPORT MonoArray *
520 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
523 MonoClass *aklass, *klass;
526 gboolean bounded = FALSE;
528 MONO_CHECK_ARG_NULL (type, NULL);
529 MONO_CHECK_ARG_NULL (lengths, NULL);
531 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
533 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
535 for (i = 0; i < mono_array_length (lengths); i++) {
536 if (mono_array_get (lengths, gint32, i) < 0) {
537 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
542 klass = mono_class_from_mono_type (type->type);
543 mono_class_init_or_throw (klass);
545 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
546 /* vectors are not the same as one dimensional arrays with no-zero bounds */
551 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
553 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
554 for (i = 0; i < aklass->rank; ++i) {
555 sizes [i] = mono_array_get (lengths, guint32, i);
557 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
559 sizes [i + aklass->rank] = 0;
562 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
563 mono_error_raise_exception (&error);
568 ICALL_EXPORT MonoArray *
569 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
572 MonoClass *aklass, *klass;
575 gboolean bounded = FALSE;
577 MONO_CHECK_ARG_NULL (type, NULL);
578 MONO_CHECK_ARG_NULL (lengths, NULL);
580 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
582 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
584 for (i = 0; i < mono_array_length (lengths); i++) {
585 if ((mono_array_get (lengths, gint64, i) < 0) ||
586 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
587 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
592 klass = mono_class_from_mono_type (type->type);
593 mono_class_init_or_throw (klass);
595 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
596 /* vectors are not the same as one dimensional arrays with no-zero bounds */
601 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
603 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
604 for (i = 0; i < aklass->rank; ++i) {
605 sizes [i] = mono_array_get (lengths, guint64, i);
607 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
609 sizes [i + aklass->rank] = 0;
612 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
613 mono_error_raise_exception (&error);
619 ves_icall_System_Array_GetRank (MonoObject *arr)
621 return arr->vtable->klass->rank;
625 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
627 gint32 rank = arr->obj.vtable->klass->rank;
630 if ((dimension < 0) || (dimension >= rank)) {
631 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
635 if (arr->bounds == NULL)
636 length = arr->max_length;
638 length = arr->bounds [dimension].length;
640 #ifdef MONO_BIG_ARRAYS
641 if (length > G_MAXINT32) {
642 mono_set_pending_exception (mono_get_exception_overflow ());
650 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
652 gint32 rank = arr->obj.vtable->klass->rank;
654 if ((dimension < 0) || (dimension >= rank)) {
655 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
659 if (arr->bounds == NULL)
660 return arr->max_length;
662 return arr->bounds [dimension].length;
666 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
668 gint32 rank = arr->obj.vtable->klass->rank;
670 if ((dimension < 0) || (dimension >= rank)) {
671 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
675 if (arr->bounds == NULL)
678 return arr->bounds [dimension].lower_bound;
682 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
684 int sz = mono_array_element_size (mono_object_class (arr));
685 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
688 ICALL_EXPORT gboolean
689 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
694 MonoVTable *src_vtable;
695 MonoVTable *dest_vtable;
696 MonoClass *src_class;
697 MonoClass *dest_class;
699 src_vtable = source->obj.vtable;
700 dest_vtable = dest->obj.vtable;
702 if (src_vtable->rank != dest_vtable->rank)
705 if (source->bounds || dest->bounds)
708 /* there's no integer overflow since mono_array_length returns an unsigned integer */
709 if ((dest_idx + length > mono_array_length_fast (dest)) ||
710 (source_idx + length > mono_array_length_fast (source)))
713 src_class = src_vtable->klass->element_class;
714 dest_class = dest_vtable->klass->element_class;
717 * Handle common cases.
720 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
721 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
723 if (src_class == mono_defaults.object_class && dest_class->valuetype)
726 /* Check if we're copying a char[] <==> (u)short[] */
727 if (src_class != dest_class) {
728 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
731 /* 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. */
732 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
736 if (dest_class->valuetype) {
737 element_size = mono_array_element_size (source->obj.vtable->klass);
738 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
739 if (dest_class->has_references) {
740 mono_value_copy_array (dest, dest_idx, source_addr, length);
742 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
743 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
746 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
753 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
759 ac = (MonoClass *)arr->obj.vtable->klass;
761 esize = mono_array_element_size (ac);
762 ea = (gpointer*)((char*)arr->vector + (pos * esize));
764 mono_gc_memmove_atomic (value, ea, esize);
768 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
774 ac = (MonoClass *)arr->obj.vtable->klass;
775 ec = ac->element_class;
777 esize = mono_array_element_size (ac);
778 ea = (gpointer*)((char*)arr->vector + (pos * esize));
780 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
781 g_assert (esize == sizeof (gpointer));
782 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
784 g_assert (ec->inited);
785 g_assert (esize == mono_class_value_size (ec, NULL));
786 if (ec->has_references)
787 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
789 mono_gc_memmove_atomic (ea, value, esize);
794 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
796 MonoClass *klass = array->obj.vtable->klass;
797 guint32 size = mono_array_element_size (klass);
798 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
800 const char *field_data;
802 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
803 MonoException *exc = mono_get_exception_argument("array",
804 "Cannot initialize array of non-primitive type.");
805 mono_set_pending_exception (exc);
809 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
810 MonoException *exc = mono_get_exception_argument("field_handle",
811 "Field doesn't have an RVA");
812 mono_set_pending_exception (exc);
816 size *= array->max_length;
817 field_data = mono_field_get_data (field_handle);
819 if (size > mono_type_size (field_handle->type, &align)) {
820 MonoException *exc = mono_get_exception_argument("field_handle",
821 "Field not large enough to fill array");
822 mono_set_pending_exception (exc);
826 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
828 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
829 guint ## n *src = (guint ## n *) field_data; \
832 for (i = 0; i < (size / sizeof(guint ## n)); i++) { \
833 data[i] = read ## n (&src[i]); \
837 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
839 switch (type->type) {
856 memcpy (mono_array_addr (array, char, 0), field_data, size);
860 memcpy (mono_array_addr (array, char, 0), field_data, size);
865 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
867 return offsetof (MonoString, chars);
870 ICALL_EXPORT MonoObject *
871 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
873 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
877 MonoObject *ret = mono_object_clone_checked (obj, &error);
878 mono_error_raise_exception (&error);
885 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
890 MONO_CHECK_ARG_NULL (handle,);
892 klass = mono_class_from_mono_type (handle);
893 MONO_CHECK_ARG (handle, klass,);
895 if (klass->generic_container)
898 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
900 /* This will call the type constructor */
901 mono_runtime_class_init (vtable);
905 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
909 mono_image_check_for_module_cctor (image);
910 if (image->has_module_cctor) {
911 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
912 mono_error_raise_exception (&error);
913 /*It's fine to raise the exception here*/
914 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
918 ICALL_EXPORT MonoBoolean
919 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
924 /* later make this configurable and per-arch */
925 int min_size = 4096 * 4 * sizeof (void*);
926 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
927 /* if we have no info we are optimistic and assume there is enough room */
931 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
935 current = (guint8 *)&stack_addr;
936 if (current > stack_addr) {
937 if ((current - stack_addr) < min_size)
940 if (current - (stack_addr - stack_size) < min_size)
946 ICALL_EXPORT MonoObject *
947 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
950 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
951 mono_error_raise_exception (&error);
957 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
960 MonoObject **values = NULL;
963 gint32 result = (int)(gsize)mono_defaults.int32_class;
964 MonoClassField* field;
967 klass = mono_object_class (this_obj);
969 if (mono_class_num_fields (klass) == 0)
973 * Compute the starting value of the hashcode for fields of primitive
974 * types, and return the remaining fields in an array to the managed side.
975 * This way, we can avoid costly reflection operations in managed code.
978 while ((field = mono_class_get_fields (klass, &iter))) {
979 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
981 if (mono_field_is_deleted (field))
983 /* FIXME: Add more types */
984 switch (field->type->type) {
986 result ^= *(gint32*)((guint8*)this_obj + field->offset);
988 case MONO_TYPE_STRING: {
990 s = *(MonoString**)((guint8*)this_obj + field->offset);
992 result ^= mono_string_hash (s);
997 values = g_newa (MonoObject*, mono_class_num_fields (klass));
998 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
999 values [count++] = o;
1005 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1006 for (i = 0; i < count; ++i)
1007 mono_array_setref (*fields, i, values [i]);
1014 ICALL_EXPORT MonoBoolean
1015 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1018 MonoObject **values = NULL;
1020 MonoClassField* field;
1024 MONO_CHECK_ARG_NULL (that, FALSE);
1026 if (this_obj->vtable != that->vtable)
1029 klass = mono_object_class (this_obj);
1031 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1032 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1035 * Do the comparison for fields of primitive type and return a result if
1036 * possible. Otherwise, return the remaining fields in an array to the
1037 * managed side. This way, we can avoid costly reflection operations in
1042 while ((field = mono_class_get_fields (klass, &iter))) {
1043 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1045 if (mono_field_is_deleted (field))
1047 /* FIXME: Add more types */
1048 switch (field->type->type) {
1051 case MONO_TYPE_BOOLEAN:
1052 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1057 case MONO_TYPE_CHAR:
1058 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1063 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1068 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1072 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1076 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1081 case MONO_TYPE_STRING: {
1082 MonoString *s1, *s2;
1083 guint32 s1len, s2len;
1084 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1085 s2 = *(MonoString**)((guint8*)that + field->offset);
1088 if ((s1 == NULL) || (s2 == NULL))
1090 s1len = mono_string_length (s1);
1091 s2len = mono_string_length (s2);
1095 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1101 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1102 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1103 values [count++] = o;
1104 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1105 values [count++] = o;
1108 if (klass->enumtype)
1109 /* enums only have one non-static field */
1115 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1116 for (i = 0; i < count; ++i)
1117 mono_array_setref_fast (*fields, i, values [i]);
1124 ICALL_EXPORT MonoReflectionType *
1125 ves_icall_System_Object_GetType (MonoObject *obj)
1127 #ifndef DISABLE_REMOTING
1128 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1129 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1132 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1136 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1138 mtype->type = &obj->vtable->klass->byval_arg;
1139 g_assert (mtype->type->type);
1143 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1145 MONO_CHECK_ARG_NULL (obj, 0);
1147 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1151 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1152 MonoReflectionMethod *method,
1153 MonoArray *opt_param_types)
1155 MONO_CHECK_ARG_NULL (method, 0);
1157 return mono_image_create_method_token (
1158 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1162 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1164 mono_image_create_pefile (mb, file);
1168 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1170 mono_image_build_metadata (mb);
1174 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1176 mono_image_register_token (mb->dynamic_image, token, obj);
1179 ICALL_EXPORT MonoObject*
1180 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1184 mono_loader_lock ();
1185 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1186 mono_loader_unlock ();
1192 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1194 MonoMethod **dest = (MonoMethod **)data;
1196 /* skip unmanaged frames */
1212 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1214 MonoMethod **dest = (MonoMethod **)data;
1216 /* skip unmanaged frames */
1221 if (!strcmp (m->klass->name_space, "System.Reflection"))
1230 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1232 MonoMethod **dest = (MonoMethod **)data;
1234 /* skip unmanaged frames */
1238 if (m->wrapper_type != MONO_WRAPPER_NONE)
1241 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1255 static MonoReflectionType *
1256 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1258 MonoMethod *m, *dest;
1260 MonoType *type = NULL;
1261 MonoAssembly *assembly = NULL;
1262 gboolean type_resolve = FALSE;
1265 * We must compute the calling assembly as type loading must happen under a metadata context.
1266 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1267 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1269 m = mono_method_get_last_managed ();
1272 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1277 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1278 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1279 * to crash. This only seems to happen in some strange remoting
1280 * scenarios and I was unable to figure out what's happening there.
1281 * Dec 10, 2005 - Martin.
1285 assembly = dest->klass->image->assembly;
1286 type_resolve = TRUE;
1288 g_warning (G_STRLOC);
1291 if (info->assembly.name)
1292 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1296 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1297 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1300 if (!info->assembly.name && !type) /* try mscorlib */
1301 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1303 if (assembly && !type && type_resolve) {
1304 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1305 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1311 return mono_type_get_object (mono_domain_get (), type);
1315 MonoReflectionType *
1316 mono_type_get (const char *str)
1318 char *copy = g_strdup (str);
1319 MonoTypeNameParse info;
1320 MonoReflectionType *type;
1323 parsedOk = mono_reflection_parse_type(copy, &info);
1325 mono_reflection_free_type_info (&info);
1330 type = type_from_parsed_name (&info, FALSE);
1332 mono_reflection_free_type_info (&info);
1339 ICALL_EXPORT MonoReflectionType*
1340 ves_icall_type_from_name (MonoString *name,
1341 MonoBoolean throwOnError,
1342 MonoBoolean ignoreCase)
1344 char *str = mono_string_to_utf8 (name);
1345 MonoTypeNameParse info;
1346 MonoReflectionType *type;
1349 parsedOk = mono_reflection_parse_type (str, &info);
1351 /* mono_reflection_parse_type() mangles the string */
1353 mono_reflection_free_type_info (&info);
1356 mono_set_pending_exception(mono_get_exception_argument("typeName", "failed parse"));
1361 type = type_from_parsed_name (&info, ignoreCase);
1363 mono_reflection_free_type_info (&info);
1367 MonoException *e = NULL;
1370 e = mono_get_exception_type_load (name, NULL);
1372 mono_loader_clear_error ();
1374 mono_set_pending_exception (e);
1383 ICALL_EXPORT MonoReflectionType*
1384 ves_icall_type_from_handle (MonoType *handle)
1386 MonoDomain *domain = mono_domain_get ();
1388 return mono_type_get_object (domain, handle);
1391 /* System.TypeCode */
1410 TYPECODE_STRING = 18
1413 ICALL_EXPORT guint32
1414 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1416 int t = type->type->type;
1418 if (type->type->byref)
1419 return TYPECODE_OBJECT;
1423 case MONO_TYPE_VOID:
1424 return TYPECODE_OBJECT;
1425 case MONO_TYPE_BOOLEAN:
1426 return TYPECODE_BOOLEAN;
1428 return TYPECODE_BYTE;
1430 return TYPECODE_SBYTE;
1432 return TYPECODE_UINT16;
1434 return TYPECODE_INT16;
1435 case MONO_TYPE_CHAR:
1436 return TYPECODE_CHAR;
1440 return TYPECODE_OBJECT;
1442 return TYPECODE_UINT32;
1444 return TYPECODE_INT32;
1446 return TYPECODE_UINT64;
1448 return TYPECODE_INT64;
1450 return TYPECODE_SINGLE;
1452 return TYPECODE_DOUBLE;
1453 case MONO_TYPE_VALUETYPE: {
1454 MonoClass *klass = type->type->data.klass;
1456 if (klass->enumtype) {
1457 t = mono_class_enum_basetype (klass)->type;
1459 } else if (mono_is_corlib_image (klass->image)) {
1460 if (strcmp (klass->name_space, "System") == 0) {
1461 if (strcmp (klass->name, "Decimal") == 0)
1462 return TYPECODE_DECIMAL;
1463 else if (strcmp (klass->name, "DateTime") == 0)
1464 return TYPECODE_DATETIME;
1467 return TYPECODE_OBJECT;
1469 case MONO_TYPE_STRING:
1470 return TYPECODE_STRING;
1471 case MONO_TYPE_SZARRAY:
1472 case MONO_TYPE_ARRAY:
1473 case MONO_TYPE_OBJECT:
1475 case MONO_TYPE_MVAR:
1476 case MONO_TYPE_TYPEDBYREF:
1477 return TYPECODE_OBJECT;
1478 case MONO_TYPE_CLASS:
1480 MonoClass *klass = type->type->data.klass;
1481 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1482 if (strcmp (klass->name, "DBNull") == 0)
1483 return TYPECODE_DBNULL;
1486 return TYPECODE_OBJECT;
1487 case MONO_TYPE_GENERICINST:
1488 return TYPECODE_OBJECT;
1490 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1496 mono_type_is_primitive (MonoType *type)
1498 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1499 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1503 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1505 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1506 return mono_class_enum_basetype (type->data.klass);
1507 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1508 return mono_class_enum_basetype (type->data.generic_class->container_class);
1512 ICALL_EXPORT guint32
1513 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1518 g_assert (type != NULL);
1520 klass = mono_class_from_mono_type (type->type);
1521 klassc = mono_class_from_mono_type (c->type);
1523 if (type->type->byref ^ c->type->byref)
1526 if (type->type->byref) {
1527 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1528 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1530 klass = mono_class_from_mono_type (t);
1531 klassc = mono_class_from_mono_type (ot);
1533 if (mono_type_is_primitive (t)) {
1534 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1535 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1536 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1537 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1538 return t->type == ot->type;
1540 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1543 if (klass->valuetype)
1544 return klass == klassc;
1545 return klass->valuetype == klassc->valuetype;
1548 return mono_class_is_assignable_from (klass, klassc);
1551 ICALL_EXPORT guint32
1552 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1554 MonoClass *klass = mono_class_from_mono_type (type->type);
1555 mono_class_init_or_throw (klass);
1556 return mono_object_isinst (obj, klass) != NULL;
1559 ICALL_EXPORT guint32
1560 ves_icall_get_attributes (MonoReflectionType *type)
1562 MonoClass *klass = mono_class_from_mono_type (type->type);
1563 return klass->flags;
1566 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1567 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1569 MonoClass *klass = field->field->parent;
1570 MonoMarshalType *info;
1574 if (klass->generic_container ||
1575 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1578 ftype = mono_field_get_type (field->field);
1579 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1582 info = mono_marshal_load_type_info (klass);
1584 for (i = 0; i < info->num_fields; ++i) {
1585 if (info->fields [i].field == field->field) {
1586 if (!info->fields [i].mspec)
1589 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1596 ICALL_EXPORT MonoReflectionField*
1597 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1599 gboolean found = FALSE;
1606 klass = handle->parent;
1608 klass = mono_class_from_mono_type (type);
1610 /* Check that the field belongs to the class */
1611 for (k = klass; k; k = k->parent) {
1612 if (k == handle->parent) {
1619 /* The managed code will throw the exception */
1623 return mono_field_get_object (mono_domain_get (), klass, handle);
1626 ICALL_EXPORT MonoArray*
1627 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1630 MonoType *type = mono_field_get_type_checked (field->field, &error);
1631 mono_error_raise_exception (&error);
1633 return type_array_from_modifiers (field->field->parent->image, type, optional);
1637 vell_icall_get_method_attributes (MonoMethod *method)
1639 return method->flags;
1643 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1646 MonoDomain *domain = mono_domain_get ();
1647 MonoMethodSignature* sig;
1649 sig = mono_method_signature_checked (method, &error);
1650 if (!mono_error_ok (&error))
1651 mono_error_raise_exception (&error);
1654 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1655 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1656 info->attrs = method->flags;
1657 info->implattrs = method->iflags;
1658 if (sig->call_convention == MONO_CALL_DEFAULT)
1659 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1661 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1666 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1669 ICALL_EXPORT MonoArray*
1670 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1672 MonoDomain *domain = mono_domain_get ();
1674 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1677 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1678 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1680 MonoDomain *domain = mono_domain_get ();
1681 MonoReflectionMarshalAsAttribute* res = NULL;
1682 MonoMarshalSpec **mspecs;
1685 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1686 mono_method_get_marshal_info (method, mspecs);
1689 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1691 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1693 mono_metadata_free_marshal_spec (mspecs [i]);
1700 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1702 MonoClass *parent = field->field->parent;
1703 if (!parent->size_inited)
1704 mono_class_init (parent);
1705 mono_class_setup_fields_locking (parent);
1707 return field->field->offset - sizeof (MonoObject);
1710 ICALL_EXPORT MonoReflectionType*
1711 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1715 parent = declaring? field->field->parent: field->klass;
1717 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1720 ICALL_EXPORT MonoObject *
1721 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1723 MonoClass *fklass = field->klass;
1724 MonoClassField *cf = field->field;
1725 MonoDomain *domain = mono_object_domain (field);
1727 if (fklass->image->assembly->ref_only) {
1728 mono_set_pending_exception (mono_get_exception_invalid_operation (
1729 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1733 if (mono_security_core_clr_enabled ())
1734 mono_security_core_clr_ensure_reflection_access_field (cf);
1736 return mono_field_get_value_object (domain, cf, obj);
1740 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1743 MonoClassField *cf = field->field;
1747 if (field->klass->image->assembly->ref_only) {
1748 mono_set_pending_exception (mono_get_exception_invalid_operation (
1749 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1753 if (mono_security_core_clr_enabled ())
1754 mono_security_core_clr_ensure_reflection_access_field (cf);
1756 type = mono_field_get_type_checked (cf, &error);
1757 if (!mono_error_ok (&error))
1758 mono_error_raise_exception (&error);
1760 v = (gchar *) value;
1762 switch (type->type) {
1765 case MONO_TYPE_BOOLEAN:
1768 case MONO_TYPE_CHAR:
1777 case MONO_TYPE_VALUETYPE:
1780 v += sizeof (MonoObject);
1782 case MONO_TYPE_STRING:
1783 case MONO_TYPE_OBJECT:
1784 case MONO_TYPE_CLASS:
1785 case MONO_TYPE_ARRAY:
1786 case MONO_TYPE_SZARRAY:
1789 case MONO_TYPE_GENERICINST: {
1790 MonoGenericClass *gclass = type->data.generic_class;
1791 g_assert (!gclass->context.class_inst->is_open);
1793 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1794 MonoClass *nklass = mono_class_from_mono_type (type);
1795 MonoObject *nullable;
1798 * Convert the boxed vtype into a Nullable structure.
1799 * This is complicated by the fact that Nullables have
1800 * a variable structure.
1802 nullable = mono_object_new (mono_domain_get (), nklass);
1804 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1806 v = (gchar *)mono_object_unbox (nullable);
1809 if (gclass->container_class->valuetype && (v != NULL))
1810 v += sizeof (MonoObject);
1814 g_error ("type 0x%x not handled in "
1815 "ves_icall_FieldInfo_SetValueInternal", type->type);
1820 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1821 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1822 if (!vtable->initialized)
1823 mono_runtime_class_init (vtable);
1824 mono_field_static_set_value (vtable, cf, v);
1826 mono_field_set_value (obj, cf, v);
1831 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1840 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1841 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1845 if (MONO_TYPE_IS_REFERENCE (f->type))
1846 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1848 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1851 ICALL_EXPORT MonoObject *
1852 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1854 MonoObject *o = NULL;
1855 MonoClassField *field = rfield->field;
1857 MonoDomain *domain = mono_object_domain (rfield);
1859 MonoTypeEnum def_type;
1860 const char *def_value;
1864 mono_class_init (field->parent);
1866 t = mono_field_get_type_checked (field, &error);
1867 if (!mono_error_ok (&error))
1868 mono_error_raise_exception (&error);
1870 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1871 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1875 if (image_is_dynamic (field->parent->image)) {
1876 MonoClass *klass = field->parent;
1877 int fidx = field - klass->fields;
1879 g_assert (fidx >= 0 && fidx < klass->field.count);
1880 g_assert (klass->ext);
1881 g_assert (klass->ext->field_def_values);
1882 def_type = klass->ext->field_def_values [fidx].def_type;
1883 def_value = klass->ext->field_def_values [fidx].data;
1884 if (def_type == MONO_TYPE_END) {
1885 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1889 def_value = mono_class_get_field_default_value (field, &def_type);
1890 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1892 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1897 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1901 case MONO_TYPE_BOOLEAN:
1904 case MONO_TYPE_CHAR:
1912 case MONO_TYPE_R8: {
1915 /* boxed value type */
1916 t = g_new0 (MonoType, 1);
1918 klass = mono_class_from_mono_type (t);
1920 o = mono_object_new (domain, klass);
1921 v = ((gchar *) o) + sizeof (MonoObject);
1922 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1925 case MONO_TYPE_STRING:
1926 case MONO_TYPE_CLASS:
1927 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1930 g_assert_not_reached ();
1936 ICALL_EXPORT MonoReflectionType*
1937 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1940 MonoClassField *field = ref_field->field;
1941 MonoType *type = mono_field_get_type_checked (field, &error);
1942 if (!mono_error_ok (&error))
1943 mono_error_raise_exception (&error);
1944 return mono_type_get_object (mono_object_domain (ref_field), type);
1947 /* From MonoProperty.cs */
1949 PInfo_Attributes = 1,
1950 PInfo_GetMethod = 1 << 1,
1951 PInfo_SetMethod = 1 << 2,
1952 PInfo_ReflectedType = 1 << 3,
1953 PInfo_DeclaringType = 1 << 4,
1958 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1960 MonoDomain *domain = mono_object_domain (property);
1961 const MonoProperty *pproperty = property->property;
1963 if ((req_info & PInfo_ReflectedType) != 0)
1964 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1965 if ((req_info & PInfo_DeclaringType) != 0)
1966 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &pproperty->parent->byval_arg));
1968 if ((req_info & PInfo_Name) != 0)
1969 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
1971 if ((req_info & PInfo_Attributes) != 0)
1972 info->attrs = pproperty->attrs;
1974 if ((req_info & PInfo_GetMethod) != 0)
1975 MONO_STRUCT_SETREF (info, get, pproperty->get &&
1976 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->get->klass == property->klass) ?
1977 mono_method_get_object (domain, pproperty->get, property->klass): NULL);
1978 if ((req_info & PInfo_SetMethod) != 0)
1979 MONO_STRUCT_SETREF (info, set, pproperty->set &&
1980 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->set->klass == property->klass) ?
1981 mono_method_get_object (domain, pproperty->set, property->klass): NULL);
1983 * There may be other methods defined for properties, though, it seems they are not exposed
1984 * in the reflection API
1989 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1991 MonoDomain *domain = mono_object_domain (event);
1993 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1994 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1996 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1997 info->attrs = event->event->attrs;
1998 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
1999 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2000 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2002 #ifndef MONO_SMALL_CONFIG
2003 if (event->event->other) {
2005 while (event->event->other [n])
2007 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2009 for (i = 0; i < n; i++)
2010 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2016 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2021 mono_class_setup_interfaces (klass, error);
2022 if (!mono_error_ok (error))
2025 for (i = 0; i < klass->interface_count; i++) {
2026 ic = klass->interfaces [i];
2027 g_hash_table_insert (ifaces, ic, ic);
2029 collect_interfaces (ic, ifaces, error);
2030 if (!mono_error_ok (error))
2036 MonoArray *iface_array;
2037 MonoGenericContext *context;
2041 } FillIfaceArrayData;
2044 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2046 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2047 MonoClass *ic = (MonoClass *)key;
2048 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2050 if (!mono_error_ok (data->error))
2053 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2054 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2055 if (!mono_error_ok (data->error))
2059 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2062 mono_metadata_free_type (inflated);
2066 get_interfaces_hash (gconstpointer v1)
2068 MonoClass *k = (MonoClass*)v1;
2070 return k->type_token;
2073 ICALL_EXPORT MonoArray*
2074 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2077 MonoClass *klass = mono_class_from_mono_type (type->type);
2079 FillIfaceArrayData data = { 0 };
2082 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2084 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2085 data.context = mono_class_get_context (klass);
2086 klass = klass->generic_class->container_class;
2089 for (parent = klass; parent; parent = parent->parent) {
2090 mono_class_setup_interfaces (parent, &error);
2091 if (!mono_error_ok (&error))
2093 collect_interfaces (parent, iface_hash, &error);
2094 if (!mono_error_ok (&error))
2098 data.error = &error;
2099 data.domain = mono_object_domain (type);
2101 len = g_hash_table_size (iface_hash);
2103 g_hash_table_destroy (iface_hash);
2104 if (!data.domain->empty_types)
2105 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2106 return data.domain->empty_types;
2109 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2110 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2111 if (!mono_error_ok (&error))
2114 g_hash_table_destroy (iface_hash);
2115 return data.iface_array;
2118 g_hash_table_destroy (iface_hash);
2119 mono_error_raise_exception (&error);
2124 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2126 gboolean variance_used;
2127 MonoClass *klass = mono_class_from_mono_type (type->type);
2128 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2129 MonoReflectionMethod *member;
2132 int i = 0, len, ioffset;
2135 mono_class_init_or_throw (klass);
2136 mono_class_init_or_throw (iclass);
2138 mono_class_setup_vtable (klass);
2140 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2144 len = mono_class_num_methods (iclass);
2145 domain = mono_object_domain (type);
2146 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2147 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2149 while ((method = mono_class_get_methods (iclass, &iter))) {
2150 member = mono_method_get_object (domain, method, iclass);
2151 mono_array_setref (*methods, i, member);
2152 member = mono_method_get_object (domain, klass->vtable [i + ioffset], klass);
2153 mono_array_setref (*targets, i, member);
2160 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2162 MonoClass *klass = mono_class_from_mono_type (type->type);
2163 mono_class_init_or_throw (klass);
2165 if (image_is_dynamic (klass->image)) {
2166 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2167 *packing = tb->packing_size;
2168 *size = tb->class_size;
2170 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2174 ICALL_EXPORT MonoReflectionType*
2175 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2179 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2180 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2182 klass = mono_class_from_mono_type (type->type);
2183 mono_class_init_or_throw (klass);
2185 // GetElementType should only return a type for:
2186 // Array Pointer PassedByRef
2187 if (type->type->byref)
2188 return mono_type_get_object (mono_object_domain (type), &klass->byval_arg);
2189 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2190 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2191 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2192 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2197 ICALL_EXPORT MonoReflectionType*
2198 ves_icall_get_type_parent (MonoReflectionType *type)
2200 if (type->type->byref)
2203 MonoClass *klass = mono_class_from_mono_type (type->type);
2204 return klass->parent ? mono_type_get_object (mono_object_domain (type), &klass->parent->byval_arg): NULL;
2207 ICALL_EXPORT MonoBoolean
2208 ves_icall_type_ispointer (MonoReflectionType *type)
2210 return type->type->type == MONO_TYPE_PTR;
2213 ICALL_EXPORT MonoBoolean
2214 ves_icall_type_isprimitive (MonoReflectionType *type)
2216 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)));
2219 ICALL_EXPORT MonoBoolean
2220 ves_icall_type_isbyref (MonoReflectionType *type)
2222 return type->type->byref;
2225 ICALL_EXPORT MonoBoolean
2226 ves_icall_type_iscomobject (MonoReflectionType *type)
2228 MonoClass *klass = mono_class_from_mono_type (type->type);
2229 mono_class_init_or_throw (klass);
2231 return mono_class_is_com_object (klass);
2234 ICALL_EXPORT MonoReflectionModule*
2235 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2237 MonoClass *klass = mono_class_from_mono_type (type->type);
2238 return mono_module_get_object (mono_object_domain (type), klass->image);
2241 ICALL_EXPORT MonoReflectionAssembly*
2242 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2244 MonoDomain *domain = mono_domain_get ();
2245 MonoClass *klass = mono_class_from_mono_type (type->type);
2246 return mono_assembly_get_object (domain, klass->image->assembly);
2249 ICALL_EXPORT MonoReflectionType*
2250 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2252 MonoDomain *domain = mono_domain_get ();
2255 if (type->type->byref)
2257 if (type->type->type == MONO_TYPE_VAR) {
2258 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2259 klass = param ? param->owner.klass : NULL;
2260 } else if (type->type->type == MONO_TYPE_MVAR) {
2261 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2262 klass = param ? param->owner.method->klass : NULL;
2264 klass = mono_class_from_mono_type (type->type)->nested_in;
2267 return klass ? mono_type_get_object (domain, &klass->byval_arg) : NULL;
2270 ICALL_EXPORT MonoString*
2271 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2273 MonoDomain *domain = mono_domain_get ();
2274 MonoClass *klass = mono_class_from_mono_type (type->type);
2276 if (type->type->byref) {
2277 char *n = g_strdup_printf ("%s&", klass->name);
2278 MonoString *res = mono_string_new (domain, n);
2284 return mono_string_new (domain, klass->name);
2288 ICALL_EXPORT MonoString*
2289 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2291 MonoDomain *domain = mono_domain_get ();
2292 MonoClass *klass = mono_class_from_mono_type (type->type);
2294 while (klass->nested_in)
2295 klass = klass->nested_in;
2297 if (klass->name_space [0] == '\0')
2300 return mono_string_new (domain, klass->name_space);
2304 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2308 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2309 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2313 klass = mono_class_from_mono_type (type->type);
2319 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2322 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2326 ICALL_EXPORT MonoArray*
2327 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2330 MonoClass *klass, *pklass;
2331 MonoDomain *domain = mono_object_domain (type);
2334 klass = mono_class_from_mono_type (type->type);
2336 if (klass->generic_container) {
2337 MonoGenericContainer *container = klass->generic_container;
2338 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2339 for (i = 0; i < container->type_argc; ++i) {
2340 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2341 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2343 } else if (klass->generic_class) {
2344 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2345 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2346 for (i = 0; i < inst->type_argc; ++i)
2347 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2354 ICALL_EXPORT gboolean
2355 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2359 if (!IS_MONOTYPE (type))
2362 if (type->type->byref)
2365 klass = mono_class_from_mono_type (type->type);
2366 return klass->generic_container != NULL;
2369 ICALL_EXPORT MonoReflectionType*
2370 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2374 if (type->type->byref)
2377 klass = mono_class_from_mono_type (type->type);
2379 if (klass->generic_container) {
2380 return type; /* check this one */
2382 if (klass->generic_class) {
2383 MonoClass *generic_class = klass->generic_class->container_class;
2386 tb = mono_class_get_ref_info (generic_class);
2388 if (generic_class->wastypebuilder && tb)
2389 return (MonoReflectionType *)tb;
2391 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2396 ICALL_EXPORT MonoReflectionType*
2397 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2400 MonoType *geninst, **types;
2403 g_assert (IS_MONOTYPE (type));
2404 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2406 count = mono_array_length (type_array);
2407 types = g_new0 (MonoType *, count);
2409 for (i = 0; i < count; i++) {
2410 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2411 types [i] = t->type;
2414 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2419 klass = mono_class_from_mono_type (geninst);
2421 /*we might inflate to the GTD*/
2422 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2423 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2427 return mono_type_get_object (mono_object_domain (type), geninst);
2430 ICALL_EXPORT gboolean
2431 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2435 if (!IS_MONOTYPE (type))
2438 if (type->type->byref)
2441 klass = mono_class_from_mono_type (type->type);
2442 return klass->generic_class != NULL || klass->generic_container != NULL;
2446 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2448 if (!IS_MONOTYPE (type))
2451 if (is_generic_parameter (type->type))
2452 return mono_type_get_generic_param_num (type->type);
2456 ICALL_EXPORT GenericParameterAttributes
2457 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2459 g_assert (IS_MONOTYPE (type));
2460 g_assert (is_generic_parameter (type->type));
2461 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2464 ICALL_EXPORT MonoArray *
2465 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2467 MonoGenericParamInfo *param_info;
2473 g_assert (IS_MONOTYPE (type));
2475 domain = mono_object_domain (type);
2476 param_info = mono_generic_param_info (type->type->data.generic_param);
2477 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2480 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2481 for (i = 0; i < count; i++)
2482 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2488 ICALL_EXPORT MonoBoolean
2489 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2491 return is_generic_parameter (type->type);
2494 ICALL_EXPORT MonoBoolean
2495 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2497 return is_generic_parameter (tb->type.type);
2501 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2502 MonoReflectionType *t)
2504 enumtype->type = t->type;
2507 ICALL_EXPORT MonoReflectionMethod*
2508 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2509 MonoReflectionMethod* generic)
2516 domain = ((MonoObject *)type)->vtable->domain;
2518 klass = mono_class_from_mono_type (type->type);
2519 mono_class_init_or_throw (klass);
2522 while ((method = mono_class_get_methods (klass, &iter))) {
2523 if (method->token == generic->method->token)
2524 return mono_method_get_object (domain, method, klass);
2530 ICALL_EXPORT MonoReflectionMethod *
2531 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2534 MonoType *type = ref_type->type;
2536 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2537 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2540 if (type->type == MONO_TYPE_VAR)
2543 method = mono_type_get_generic_param_owner (type)->owner.method;
2545 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2548 ICALL_EXPORT MonoBoolean
2549 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2551 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2555 ICALL_EXPORT MonoBoolean
2556 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2558 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2563 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2565 MonoDomain *domain = mono_domain_get ();
2566 MonoImage *image = method->method->klass->image;
2567 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2568 MonoTableInfo *tables = image->tables;
2569 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2570 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2571 guint32 im_cols [MONO_IMPLMAP_SIZE];
2572 guint32 scope_token;
2573 const char *import = NULL;
2574 const char *scope = NULL;
2576 if (image_is_dynamic (image)) {
2577 MonoReflectionMethodAux *method_aux =
2578 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2580 import = method_aux->dllentry;
2581 scope = method_aux->dll;
2584 if (!import || !scope) {
2585 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2590 if (piinfo->implmap_idx) {
2591 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2593 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2594 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2595 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2596 scope = mono_metadata_string_heap (image, scope_token);
2600 *flags = piinfo->piflags;
2601 *entry_point = mono_string_new (domain, import);
2602 *dll_name = mono_string_new (domain, scope);
2605 ICALL_EXPORT MonoReflectionMethod *
2606 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2608 MonoMethodInflated *imethod;
2611 if (method->method->is_generic)
2614 if (!method->method->is_inflated)
2617 imethod = (MonoMethodInflated *) method->method;
2619 result = imethod->declaring;
2620 /* Not a generic method. */
2621 if (!result->is_generic)
2624 if (image_is_dynamic (method->method->klass->image)) {
2625 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2626 MonoReflectionMethod *res;
2629 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2630 * the dynamic case as well ?
2632 mono_image_lock ((MonoImage*)image);
2633 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2634 mono_image_unlock ((MonoImage*)image);
2640 if (imethod->context.class_inst) {
2641 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2642 /*Generic methods gets the context of the GTD.*/
2643 if (mono_class_get_context (klass)) {
2645 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2646 mono_error_raise_exception (&error);
2650 return mono_method_get_object (mono_object_domain (method), result, NULL);
2653 ICALL_EXPORT gboolean
2654 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2656 return mono_method_signature (method->method)->generic_param_count != 0;
2659 ICALL_EXPORT gboolean
2660 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2662 return method->method->is_generic;
2665 ICALL_EXPORT MonoArray*
2666 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2672 domain = mono_object_domain (method);
2674 if (method->method->is_inflated) {
2675 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2678 count = inst->type_argc;
2679 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2681 for (i = 0; i < count; i++)
2682 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2688 count = mono_method_signature (method->method)->generic_param_count;
2689 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2691 for (i = 0; i < count; i++) {
2692 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2693 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2694 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2695 mono_array_setref (res, i,
2696 mono_type_get_object (domain, &pklass->byval_arg));
2702 ICALL_EXPORT MonoObject *
2703 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2707 * Invoke from reflection is supposed to always be a virtual call (the API
2708 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2709 * greater flexibility.
2711 MonoMethod *m = method->method;
2712 MonoMethodSignature *sig = mono_method_signature (m);
2715 void *obj = this_arg;
2719 if (mono_security_core_clr_enabled ())
2720 mono_security_core_clr_ensure_reflection_access_method (m);
2722 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2723 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2724 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2729 if (!mono_object_isinst (this_arg, m->klass)) {
2730 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2731 char *target_name = mono_type_get_full_name (m->klass);
2732 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2733 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2735 g_free (target_name);
2739 m = mono_object_get_virtual_method (this_arg, m);
2740 /* must pass the pointer to the value for valuetype methods */
2741 if (m->klass->valuetype)
2742 obj = mono_object_unbox (this_arg);
2743 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2744 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2749 if (sig->ret->byref) {
2750 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"));
2754 pcount = params? mono_array_length (params): 0;
2755 if (pcount != sig->param_count) {
2756 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2760 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2761 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."));
2765 image = m->klass->image;
2766 if (image->assembly->ref_only) {
2767 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."));
2771 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2772 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2776 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2780 intptr_t *lower_bounds;
2781 pcount = mono_array_length (params);
2782 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
2783 /* Note: the synthetized array .ctors have int32 as argument type */
2784 for (i = 0; i < pcount; ++i)
2785 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2787 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2788 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2789 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
2790 mono_error_raise_exception (&error);
2792 for (i = 0; i < mono_array_length (arr); ++i) {
2793 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
2794 mono_error_raise_exception (&error);
2796 mono_array_setref_fast (arr, i, subarray);
2798 return (MonoObject*)arr;
2801 if (m->klass->rank == pcount) {
2802 /* Only lengths provided. */
2803 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
2804 mono_error_raise_exception (&error);
2806 return (MonoObject*)arr;
2808 g_assert (pcount == (m->klass->rank * 2));
2809 /* The arguments are lower-bound-length pairs */
2810 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
2812 for (i = 0; i < pcount / 2; ++i) {
2813 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
2814 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
2817 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
2818 mono_error_raise_exception (&error);
2820 return (MonoObject*)arr;
2823 return mono_runtime_invoke_array (m, obj, params, NULL);
2826 #ifndef DISABLE_REMOTING
2827 ICALL_EXPORT MonoObject *
2828 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
2830 MonoDomain *domain = mono_object_domain (method);
2831 MonoMethod *m = method->method;
2832 MonoMethodSignature *sig = mono_method_signature (m);
2833 MonoArray *out_args;
2835 int i, j, outarg_count = 0;
2837 if (m->klass == mono_defaults.object_class) {
2838 if (!strcmp (m->name, "FieldGetter")) {
2839 MonoClass *k = this_arg->vtable->klass;
2843 /* If this is a proxy, then it must be a CBO */
2844 if (k == mono_defaults.transparent_proxy_class) {
2845 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2846 this_arg = tp->rp->unwrapped_server;
2847 g_assert (this_arg);
2848 k = this_arg->vtable->klass;
2851 name = mono_array_get (params, MonoString *, 1);
2852 str = mono_string_to_utf8 (name);
2855 MonoClassField* field = mono_class_get_field_from_name (k, str);
2857 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2858 if (field_klass->valuetype)
2859 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
2861 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
2863 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2864 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2865 mono_array_setref (out_args, 0, result);
2873 g_assert_not_reached ();
2875 } else if (!strcmp (m->name, "FieldSetter")) {
2876 MonoClass *k = this_arg->vtable->klass;
2882 /* If this is a proxy, then it must be a CBO */
2883 if (k == mono_defaults.transparent_proxy_class) {
2884 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2885 this_arg = tp->rp->unwrapped_server;
2886 g_assert (this_arg);
2887 k = this_arg->vtable->klass;
2890 name = mono_array_get (params, MonoString *, 1);
2891 str = mono_string_to_utf8 (name);
2894 MonoClassField* field = mono_class_get_field_from_name (k, str);
2896 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2897 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
2899 if (field_klass->valuetype) {
2900 size = mono_type_size (field->type, &align);
2901 g_assert (size == mono_class_value_size (field_klass, NULL));
2902 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2904 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
2907 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2908 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2918 g_assert_not_reached ();
2923 for (i = 0; i < mono_array_length (params); i++) {
2924 if (sig->params [i]->byref)
2928 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2930 /* handle constructors only for objects already allocated */
2931 if (!strcmp (method->method->name, ".ctor"))
2932 g_assert (this_arg);
2934 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2935 g_assert (!method->method->klass->valuetype);
2936 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
2938 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2939 if (sig->params [i]->byref) {
2941 arg = mono_array_get (params, gpointer, i);
2942 mono_array_setref (out_args, j, arg);
2947 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2954 read_enum_value (const char *mem, int type)
2957 case MONO_TYPE_BOOLEAN:
2959 return *(guint8*)mem;
2961 return *(gint8*)mem;
2962 case MONO_TYPE_CHAR:
2964 return read16 (mem);
2966 return (gint16) read16 (mem);
2968 return read32 (mem);
2970 return (gint32) read32 (mem);
2973 return read64 (mem);
2975 g_assert_not_reached ();
2981 write_enum_value (char *mem, int type, guint64 value)
2985 case MONO_TYPE_I1: {
2986 guint8 *p = (guint8*)mem;
2991 case MONO_TYPE_I2: {
2992 guint16 *p = (guint16 *)mem;
2997 case MONO_TYPE_I4: {
2998 guint32 *p = (guint32 *)mem;
3003 case MONO_TYPE_I8: {
3004 guint64 *p = (guint64 *)mem;
3009 g_assert_not_reached ();
3014 ICALL_EXPORT MonoObject *
3015 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3022 domain = mono_object_domain (enumType);
3023 enumc = mono_class_from_mono_type (enumType->type);
3025 mono_class_init_or_throw (enumc);
3027 etype = mono_class_enum_basetype (enumc);
3029 res = mono_object_new (domain, enumc);
3030 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3035 ICALL_EXPORT MonoBoolean
3036 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3038 int size = mono_class_value_size (a->vtable->klass, NULL);
3039 guint64 a_val = 0, b_val = 0;
3041 memcpy (&a_val, mono_object_unbox (a), size);
3042 memcpy (&b_val, mono_object_unbox (b), size);
3044 return (a_val & b_val) == b_val;
3047 ICALL_EXPORT MonoObject *
3048 ves_icall_System_Enum_get_value (MonoObject *eobj)
3059 g_assert (eobj->vtable->klass->enumtype);
3061 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3062 res = mono_object_new (mono_object_domain (eobj), enumc);
3063 dst = (char *)res + sizeof (MonoObject);
3064 src = (char *)eobj + sizeof (MonoObject);
3065 size = mono_class_value_size (enumc, NULL);
3067 memcpy (dst, src, size);
3072 ICALL_EXPORT MonoReflectionType *
3073 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3078 klass = mono_class_from_mono_type (type->type);
3079 mono_class_init_or_throw (klass);
3081 etype = mono_class_enum_basetype (klass);
3083 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3087 return mono_type_get_object (mono_object_domain (type), etype);
3091 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3093 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3094 gpointer odata = (char *)other + sizeof (MonoObject);
3095 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3096 g_assert (basetype);
3101 if (eobj->vtable->klass != other->vtable->klass)
3104 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3105 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3106 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3109 return me > other ? 1 : -1; \
3112 switch (basetype->type) {
3114 COMPARE_ENUM_VALUES (guint8);
3116 COMPARE_ENUM_VALUES (gint8);
3117 case MONO_TYPE_CHAR:
3119 COMPARE_ENUM_VALUES (guint16);
3121 COMPARE_ENUM_VALUES (gint16);
3123 COMPARE_ENUM_VALUES (guint32);
3125 COMPARE_ENUM_VALUES (gint32);
3127 COMPARE_ENUM_VALUES (guint64);
3129 COMPARE_ENUM_VALUES (gint64);
3133 #undef COMPARE_ENUM_VALUES
3134 /* indicates that the enum was of an unsupported unerlying type */
3139 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3141 gpointer data = (char *)eobj + sizeof (MonoObject);
3142 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3143 g_assert (basetype);
3145 switch (basetype->type) {
3146 case MONO_TYPE_I1: {
3147 gint8 value = *((gint8*)data);
3148 return ((int)value ^ (int)value << 8);
3151 return *((guint8*)data);
3152 case MONO_TYPE_CHAR:
3154 return *((guint16*)data);
3156 case MONO_TYPE_I2: {
3157 gint16 value = *((gint16*)data);
3158 return ((int)(guint16)value | (((int)value) << 16));
3161 return *((guint32*)data);
3163 return *((gint32*)data);
3165 case MONO_TYPE_I8: {
3166 gint64 value = *((gint64*)data);
3167 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3170 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3175 ICALL_EXPORT MonoBoolean
3176 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3178 MonoDomain *domain = mono_object_domain (type);
3179 MonoClass *enumc = mono_class_from_mono_type (type->type);
3180 guint j = 0, nvalues;
3182 MonoClassField *field;
3184 guint64 field_value, previous_value = 0;
3185 gboolean sorted = TRUE;
3187 mono_class_init_or_throw (enumc);
3189 if (!enumc->enumtype) {
3190 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3194 base_type = mono_class_enum_basetype (enumc)->type;
3196 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3197 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3198 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3201 while ((field = mono_class_get_fields (enumc, &iter))) {
3203 MonoTypeEnum def_type;
3205 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3207 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3209 if (mono_field_is_deleted (field))
3211 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3213 p = mono_class_get_field_default_value (field, &def_type);
3214 /* len = */ mono_metadata_decode_blob_size (p, &p);
3216 field_value = read_enum_value (p, base_type);
3217 mono_array_set (*values, guint64, j, field_value);
3219 if (previous_value > field_value)
3222 previous_value = field_value;
3230 BFLAGS_IgnoreCase = 1,
3231 BFLAGS_DeclaredOnly = 2,
3232 BFLAGS_Instance = 4,
3234 BFLAGS_Public = 0x10,
3235 BFLAGS_NonPublic = 0x20,
3236 BFLAGS_FlattenHierarchy = 0x40,
3237 BFLAGS_InvokeMethod = 0x100,
3238 BFLAGS_CreateInstance = 0x200,
3239 BFLAGS_GetField = 0x400,
3240 BFLAGS_SetField = 0x800,
3241 BFLAGS_GetProperty = 0x1000,
3242 BFLAGS_SetProperty = 0x2000,
3243 BFLAGS_ExactBinding = 0x10000,
3244 BFLAGS_SuppressChangeType = 0x20000,
3245 BFLAGS_OptionalParamBinding = 0x40000
3248 ICALL_EXPORT MonoArray*
3249 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3252 MonoClass *startklass, *klass, *refklass;
3257 char *utf8_name = NULL;
3258 int (*compare_func) (const char *s1, const char *s2) = NULL;
3259 MonoClassField *field;
3260 MonoPtrArray tmp_array;
3262 domain = ((MonoObject *)type)->vtable->domain;
3263 if (type->type->byref)
3264 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3266 klass = startklass = mono_class_from_mono_type (type->type);
3267 refklass = mono_class_from_mono_type (reftype->type);
3269 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3272 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3273 mono_ptr_array_destroy (tmp_array);
3274 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3279 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3280 guint32 flags = mono_field_get_flags (field);
3282 if (mono_field_is_deleted_with_flags (field, flags))
3284 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3285 if (bflags & BFLAGS_Public)
3287 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3288 if (bflags & BFLAGS_NonPublic) {
3295 if (flags & FIELD_ATTRIBUTE_STATIC) {
3296 if (bflags & BFLAGS_Static)
3297 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3300 if (bflags & BFLAGS_Instance)
3308 if (utf8_name == NULL) {
3309 utf8_name = mono_string_to_utf8 (name);
3310 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3313 if (compare_func (mono_field_get_name (field), utf8_name))
3317 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3318 mono_ptr_array_append (tmp_array, member);
3320 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3323 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3325 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3326 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3328 mono_ptr_array_destroy (tmp_array);
3330 if (utf8_name != NULL)
3337 method_nonpublic (MonoMethod* method, gboolean start_klass)
3339 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3340 case METHOD_ATTRIBUTE_ASSEM:
3341 return (start_klass || mono_defaults.generic_ilist_class);
3342 case METHOD_ATTRIBUTE_PRIVATE:
3344 case METHOD_ATTRIBUTE_PUBLIC:
3352 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3355 MonoClass *startklass;
3359 /*FIXME, use MonoBitSet*/
3360 guint32 method_slots_default [8];
3361 guint32 *method_slots = NULL;
3362 int (*compare_func) (const char *s1, const char *s2) = NULL;
3364 array = g_ptr_array_new ();
3369 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3371 /* An optimization for calls made from Delegate:CreateDelegate () */
3372 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3373 method = mono_get_delegate_invoke (klass);
3374 if (mono_loader_get_last_error ())
3377 g_ptr_array_add (array, method);
3381 mono_class_setup_methods (klass);
3382 mono_class_setup_vtable (klass);
3383 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3386 if (is_generic_parameter (&klass->byval_arg))
3387 nslots = mono_class_get_vtable_size (klass->parent);
3389 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3390 if (nslots >= sizeof (method_slots_default) * 8) {
3391 method_slots = g_new0 (guint32, nslots / 32 + 1);
3393 method_slots = method_slots_default;
3394 memset (method_slots, 0, sizeof (method_slots_default));
3397 mono_class_setup_methods (klass);
3398 mono_class_setup_vtable (klass);
3399 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3403 while ((method = mono_class_get_methods (klass, &iter))) {
3405 if (method->slot != -1) {
3406 g_assert (method->slot < nslots);
3407 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3409 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3410 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3413 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3415 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3416 if (bflags & BFLAGS_Public)
3418 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3424 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3425 if (bflags & BFLAGS_Static)
3426 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3429 if (bflags & BFLAGS_Instance)
3437 if (compare_func (name, method->name))
3442 g_ptr_array_add (array, method);
3444 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3446 if (method_slots != method_slots_default)
3447 g_free (method_slots);
3452 if (method_slots != method_slots_default)
3453 g_free (method_slots);
3454 g_ptr_array_free (array, TRUE);
3456 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3457 *ex = mono_class_get_exception_for_failure (klass);
3459 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3460 mono_loader_clear_error ();
3465 ICALL_EXPORT MonoArray*
3466 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3468 static MonoClass *MethodInfo_array;
3471 MonoVTable *array_vtable;
3472 MonoException *ex = NULL;
3473 const char *mname = NULL;
3474 GPtrArray *method_array;
3475 MonoClass *klass, *refklass;
3478 if (!MethodInfo_array) {
3479 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3480 mono_memory_barrier ();
3481 MethodInfo_array = klass;
3484 klass = mono_class_from_mono_type (type->type);
3485 refklass = mono_class_from_mono_type (reftype->type);
3486 domain = ((MonoObject *)type)->vtable->domain;
3487 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3488 if (type->type->byref)
3489 return mono_array_new_specific (array_vtable, 0);
3492 mname = mono_string_to_utf8 (name);
3494 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3495 g_free ((char*)mname);
3497 mono_set_pending_exception (ex);
3501 res = mono_array_new_specific (array_vtable, method_array->len);
3503 for (i = 0; i < method_array->len; ++i) {
3504 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3505 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3508 g_ptr_array_free (method_array, TRUE);
3512 ICALL_EXPORT MonoArray*
3513 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3516 static MonoClass *System_Reflection_ConstructorInfo;
3517 MonoClass *startklass, *klass, *refklass;
3522 gpointer iter = NULL;
3523 MonoPtrArray tmp_array;
3525 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3527 domain = ((MonoObject *)type)->vtable->domain;
3528 if (type->type->byref)
3529 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3530 klass = startklass = mono_class_from_mono_type (type->type);
3531 refklass = mono_class_from_mono_type (reftype->type);
3533 if (!System_Reflection_ConstructorInfo)
3534 System_Reflection_ConstructorInfo = mono_class_from_name (
3535 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3537 mono_class_setup_methods (klass);
3538 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3539 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3544 while ((method = mono_class_get_methods (klass, &iter))) {
3546 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3548 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3549 if (bflags & BFLAGS_Public)
3552 if (bflags & BFLAGS_NonPublic)
3558 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3559 if (bflags & BFLAGS_Static)
3560 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3563 if (bflags & BFLAGS_Instance)
3569 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3571 mono_ptr_array_append (tmp_array, member);
3574 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3576 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3577 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3579 mono_ptr_array_destroy (tmp_array);
3585 property_hash (gconstpointer data)
3587 MonoProperty *prop = (MonoProperty*)data;
3589 return g_str_hash (prop->name);
3593 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3595 if (method1->is_inflated)
3596 method1 = ((MonoMethodInflated*) method1)->declaring;
3597 if (method2->is_inflated)
3598 method2 = ((MonoMethodInflated*) method2)->declaring;
3600 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3604 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3606 // Properties are hide-by-name-and-signature
3607 if (!g_str_equal (prop1->name, prop2->name))
3610 /* If we see a property in a generic method, we want to
3611 compare the generic signatures, not the inflated signatures
3612 because we might conflate two properties that were
3616 public T this[T t] { getter { return t; } } // method 1
3617 public U this[U u] { getter { return u; } } // method 2
3620 If we see int Foo<int,int>::Item[int] we need to know if
3621 the indexer came from method 1 or from method 2, and we
3622 shouldn't conflate them. (Bugzilla 36283)
3624 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3627 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3634 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3639 return method_nonpublic (accessor, start_klass);
3642 ICALL_EXPORT MonoArray*
3643 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3647 static MonoClass *System_Reflection_PropertyInfo;
3648 MonoClass *startklass, *klass;
3654 gchar *propname = NULL;
3655 int (*compare_func) (const char *s1, const char *s2) = NULL;
3657 GHashTable *properties = NULL;
3658 MonoPtrArray tmp_array;
3660 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3662 if (!System_Reflection_PropertyInfo)
3663 System_Reflection_PropertyInfo = mono_class_from_name (
3664 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3666 domain = ((MonoObject *)type)->vtable->domain;
3667 if (type->type->byref)
3668 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3669 klass = startklass = mono_class_from_mono_type (type->type);
3672 propname = mono_string_to_utf8 (name);
3673 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3676 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3678 mono_class_setup_methods (klass);
3679 mono_class_setup_vtable (klass);
3680 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3684 while ((prop = mono_class_get_properties (klass, &iter))) {
3690 flags = method->flags;
3693 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3694 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3695 if (bflags & BFLAGS_Public)
3697 } else if (bflags & BFLAGS_NonPublic) {
3698 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3699 property_accessor_nonpublic(prop->set, startklass == klass)) {
3706 if (flags & METHOD_ATTRIBUTE_STATIC) {
3707 if (bflags & BFLAGS_Static)
3708 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3711 if (bflags & BFLAGS_Instance)
3720 if (compare_func (propname, prop->name))
3724 if (g_hash_table_lookup (properties, prop))
3727 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3729 g_hash_table_insert (properties, prop, prop);
3731 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3734 g_hash_table_destroy (properties);
3737 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3738 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3739 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3741 mono_ptr_array_destroy (tmp_array);
3747 g_hash_table_destroy (properties);
3750 mono_ptr_array_destroy (tmp_array);
3752 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3753 ex = mono_class_get_exception_for_failure (klass);
3755 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3756 mono_loader_clear_error ();
3758 mono_set_pending_exception (ex);
3763 event_hash (gconstpointer data)
3765 MonoEvent *event = (MonoEvent*)data;
3767 return g_str_hash (event->name);
3771 event_equal (MonoEvent *event1, MonoEvent *event2)
3773 // Events are hide-by-name
3774 return g_str_equal (event1->name, event2->name);
3777 ICALL_EXPORT MonoArray*
3778 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3782 static MonoClass *System_Reflection_EventInfo;
3783 MonoClass *startklass, *klass;
3789 char *utf8_name = NULL;
3790 int (*compare_func) (const char *s1, const char *s2) = NULL;
3791 GHashTable *events = NULL;
3792 MonoPtrArray tmp_array;
3794 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
3796 if (!System_Reflection_EventInfo)
3797 System_Reflection_EventInfo = mono_class_from_name (
3798 mono_defaults.corlib, "System.Reflection", "EventInfo");
3800 domain = mono_object_domain (type);
3801 if (type->type->byref)
3802 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3803 klass = startklass = mono_class_from_mono_type (type->type);
3805 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3807 mono_class_setup_methods (klass);
3808 mono_class_setup_vtable (klass);
3809 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3813 while ((event = mono_class_get_events (klass, &iter))) {
3815 method = event->add;
3817 method = event->remove;
3819 method = event->raise;
3821 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3822 if (bflags & BFLAGS_Public)
3824 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3825 if (bflags & BFLAGS_NonPublic)
3830 if (bflags & BFLAGS_NonPublic)
3836 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3837 if (bflags & BFLAGS_Static)
3838 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3841 if (bflags & BFLAGS_Instance)
3846 if (bflags & BFLAGS_Instance)
3852 if (utf8_name == NULL) {
3853 utf8_name = mono_string_to_utf8 (name);
3854 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3857 if (compare_func (event->name, utf8_name))
3861 if (g_hash_table_lookup (events, event))
3864 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3866 g_hash_table_insert (events, event, event);
3868 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3871 g_hash_table_destroy (events);
3873 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3875 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3876 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3878 mono_ptr_array_destroy (tmp_array);
3880 if (utf8_name != NULL)
3886 mono_ptr_array_destroy (tmp_array);
3887 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3888 ex = mono_class_get_exception_for_failure (klass);
3890 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3891 mono_loader_clear_error ();
3893 mono_set_pending_exception (ex);
3897 ICALL_EXPORT MonoArray*
3898 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
3908 MonoPtrArray tmp_array;
3910 domain = ((MonoObject *)type)->vtable->domain;
3911 if (type->type->byref)
3912 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3913 klass = mono_class_from_mono_type (type->type);
3916 * If a nested type is generic, return its generic type definition.
3917 * Note that this means that the return value is essentially the set
3918 * of nested types of the generic type definition of @klass.
3920 * A note in MSDN claims that a generic type definition can have
3921 * nested types that aren't generic. In any case, the container of that
3922 * nested type would be the generic type definition.
3924 if (klass->generic_class)
3925 klass = klass->generic_class->container_class;
3927 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
3929 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3931 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3932 if (bflags & BFLAGS_Public)
3935 if (bflags & BFLAGS_NonPublic)
3943 str = mono_string_to_utf8 (name);
3944 mono_identifier_unescape_type_name_chars (str);
3947 if (strcmp (nested->name, str))
3951 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3952 mono_ptr_array_append (tmp_array, member);
3955 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
3957 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3958 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3960 mono_ptr_array_destroy (tmp_array);
3968 ICALL_EXPORT MonoReflectionType*
3969 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3972 MonoType *type = NULL;
3973 MonoTypeNameParse info;
3974 gboolean type_resolve;
3976 /* On MS.NET, this does not fire a TypeResolve event */
3977 type_resolve = TRUE;
3978 str = mono_string_to_utf8 (name);
3979 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3980 if (!mono_reflection_parse_type (str, &info)) {
3982 mono_reflection_free_type_info (&info);
3984 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
3987 /*g_print ("failed parse\n");*/
3991 if (info.assembly.name) {
3993 mono_reflection_free_type_info (&info);
3995 /* 1.0 and 2.0 throw different exceptions */
3996 if (mono_defaults.generic_ilist_class)
3997 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
3999 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4005 if (module != NULL) {
4007 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4012 if (assembly_is_dynamic (assembly->assembly)) {
4013 /* Enumerate all modules */
4014 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4018 if (abuilder->modules) {
4019 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4020 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4021 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4027 if (!type && abuilder->loaded_modules) {
4028 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4029 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4030 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4037 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4039 mono_reflection_free_type_info (&info);
4041 MonoException *e = NULL;
4044 e = mono_get_exception_type_load (name, NULL);
4046 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4047 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4049 mono_loader_clear_error ();
4052 mono_set_pending_exception (e);
4054 } else if (mono_loader_get_last_error ()) {
4056 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4059 mono_loader_clear_error ();
4062 if (type->type == MONO_TYPE_CLASS) {
4063 MonoClass *klass = mono_type_get_class (type);
4065 /* need to report exceptions ? */
4066 if (throwOnError && klass->exception_type) {
4067 /* report SecurityException (or others) that occured when loading the assembly */
4068 MonoException *exc = mono_class_get_exception_for_failure (klass);
4069 mono_loader_clear_error ();
4070 mono_set_pending_exception (exc);
4075 /* g_print ("got it\n"); */
4076 return mono_type_get_object (mono_object_domain (assembly), type);
4080 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4083 gchar *shadow_ini_file;
4086 /* Check for shadow-copied assembly */
4087 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4088 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4090 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4091 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4097 g_free (shadow_ini_file);
4098 if (content != NULL) {
4101 *filename = content;
4108 ICALL_EXPORT MonoString *
4109 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4111 MonoDomain *domain = mono_object_domain (assembly);
4112 MonoAssembly *mass = assembly->assembly;
4113 MonoString *res = NULL;
4118 if (g_path_is_absolute (mass->image->name)) {
4119 absolute = g_strdup (mass->image->name);
4120 dirname = g_path_get_dirname (absolute);
4122 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4123 dirname = g_strdup (mass->basedir);
4126 replace_shadow_path (domain, dirname, &absolute);
4131 for (i = strlen (absolute) - 1; i >= 0; i--)
4132 if (absolute [i] == '\\')
4137 uri = g_filename_to_uri (absolute, NULL, NULL);
4139 const char *prepend = "file://";
4141 if (*absolute == '/' && *(absolute + 1) == '/') {
4144 prepend = "file:///";
4147 uri = g_strconcat (prepend, absolute, NULL);
4151 res = mono_string_new (domain, uri);
4158 ICALL_EXPORT MonoBoolean
4159 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4161 MonoAssembly *mass = assembly->assembly;
4163 return mass->in_gac;
4166 ICALL_EXPORT MonoReflectionAssembly*
4167 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4171 MonoImageOpenStatus status;
4173 name = mono_string_to_utf8 (mname);
4174 res = mono_assembly_load_with_partial_name (name, &status);
4180 return mono_assembly_get_object (mono_domain_get (), res);
4183 ICALL_EXPORT MonoString *
4184 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4186 MonoDomain *domain = mono_object_domain (assembly);
4189 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4194 ICALL_EXPORT MonoBoolean
4195 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4197 return assembly->assembly->ref_only;
4200 ICALL_EXPORT MonoString *
4201 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4203 MonoDomain *domain = mono_object_domain (assembly);
4205 return mono_string_new (domain, assembly->assembly->image->version);
4208 ICALL_EXPORT MonoReflectionMethod*
4209 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4213 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4217 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4218 mono_error_raise_exception (&error);
4220 return mono_method_get_object (mono_object_domain (assembly), method, NULL);
4223 ICALL_EXPORT MonoReflectionModule*
4224 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4226 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4229 ICALL_EXPORT MonoArray*
4230 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4232 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4233 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4237 for (i = 0; i < table->rows; ++i) {
4238 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4239 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4245 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4247 static MonoClass *System_Version = NULL;
4248 static MonoMethod *create_version = NULL;
4252 if (!System_Version) {
4253 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4254 g_assert (System_Version);
4257 if (!create_version) {
4258 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4259 create_version = mono_method_desc_search_in_class (desc, System_Version);
4260 g_assert (create_version);
4261 mono_method_desc_free (desc);
4267 args [3] = &revision;
4268 result = mono_object_new (domain, System_Version);
4269 mono_runtime_invoke (create_version, result, args, NULL);
4274 ICALL_EXPORT MonoArray*
4275 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4277 static MonoClass *System_Reflection_AssemblyName;
4279 MonoDomain *domain = mono_object_domain (assembly);
4281 static MonoMethod *create_culture = NULL;
4282 MonoImage *image = assembly->assembly->image;
4285 if (!System_Reflection_AssemblyName)
4286 System_Reflection_AssemblyName = mono_class_from_name (
4287 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4289 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4292 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4294 if (count > 0 && !create_culture) {
4295 MonoMethodDesc *desc = mono_method_desc_new (
4296 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4297 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4298 g_assert (create_culture);
4299 mono_method_desc_free (desc);
4302 for (i = 0; i < count; i++) {
4303 MonoReflectionAssemblyName *aname;
4304 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4306 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4308 aname = (MonoReflectionAssemblyName *) mono_object_new (
4309 domain, System_Reflection_AssemblyName);
4311 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4313 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4314 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4315 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4316 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4317 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4318 aname->versioncompat = 1; /* SameMachine (default) */
4319 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4320 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4322 if (create_culture) {
4324 MonoBoolean assembly_ref = 1;
4325 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4326 args [1] = &assembly_ref;
4327 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4330 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4331 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4332 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4334 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4335 /* public key token isn't copied - the class library will
4336 automatically generate it from the public key if required */
4337 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4338 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4340 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4341 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4344 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4347 /* note: this function doesn't return the codebase on purpose (i.e. it can
4348 be used under partial trust as path information isn't present). */
4350 mono_array_setref (result, i, aname);
4355 /* move this in some file in mono/util/ */
4357 g_concat_dir_and_file (const char *dir, const char *file)
4359 g_return_val_if_fail (dir != NULL, NULL);
4360 g_return_val_if_fail (file != NULL, NULL);
4363 * If the directory name doesn't have a / on the end, we need
4364 * to add one so we get a proper path to the file
4366 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4367 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4369 return g_strconcat (dir, file, NULL);
4373 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4375 char *n = mono_string_to_utf8 (name);
4376 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4378 guint32 cols [MONO_MANIFEST_SIZE];
4379 guint32 impl, file_idx;
4383 for (i = 0; i < table->rows; ++i) {
4384 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4385 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4386 if (strcmp (val, n) == 0)
4390 if (i == table->rows)
4393 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4396 * this code should only be called after obtaining the
4397 * ResourceInfo and handling the other cases.
4399 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4400 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4402 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4407 module = assembly->assembly->image;
4409 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4411 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4414 ICALL_EXPORT gboolean
4415 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4417 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4419 guint32 cols [MONO_MANIFEST_SIZE];
4420 guint32 file_cols [MONO_FILE_SIZE];
4424 n = mono_string_to_utf8 (name);
4425 for (i = 0; i < table->rows; ++i) {
4426 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4427 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4428 if (strcmp (val, n) == 0)
4432 if (i == table->rows)
4435 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4436 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4439 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4440 case MONO_IMPLEMENTATION_FILE:
4441 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4442 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4443 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4444 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4445 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4446 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4449 info->location = RESOURCE_LOCATION_EMBEDDED;
4452 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4453 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4454 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4455 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4456 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4457 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4459 mono_set_pending_exception (ex);
4462 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4464 /* Obtain info recursively */
4465 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4466 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4469 case MONO_IMPLEMENTATION_EXP_TYPE:
4470 g_assert_not_reached ();
4478 ICALL_EXPORT MonoObject*
4479 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4481 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4482 MonoArray *result = NULL;
4487 /* check hash if needed */
4489 n = mono_string_to_utf8 (name);
4490 for (i = 0; i < table->rows; ++i) {
4491 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4492 if (strcmp (val, n) == 0) {
4495 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4496 fn = mono_string_new (mono_object_domain (assembly), n);
4498 return (MonoObject*)fn;
4506 for (i = 0; i < table->rows; ++i) {
4507 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4511 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4514 for (i = 0; i < table->rows; ++i) {
4515 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4516 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4517 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4518 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4523 return (MonoObject*)result;
4526 ICALL_EXPORT MonoArray*
4527 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4529 MonoDomain *domain = mono_domain_get();
4532 int i, j, file_count = 0;
4533 MonoImage **modules;
4534 guint32 module_count, real_module_count;
4535 MonoTableInfo *table;
4536 guint32 cols [MONO_FILE_SIZE];
4537 MonoImage *image = assembly->assembly->image;
4539 g_assert (image != NULL);
4540 g_assert (!assembly_is_dynamic (assembly->assembly));
4542 table = &image->tables [MONO_TABLE_FILE];
4543 file_count = table->rows;
4545 modules = image->modules;
4546 module_count = image->module_count;
4548 real_module_count = 0;
4549 for (i = 0; i < module_count; ++i)
4551 real_module_count ++;
4553 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4554 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4556 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4558 for (i = 0; i < module_count; ++i)
4560 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4564 for (i = 0; i < file_count; ++i, ++j) {
4565 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4566 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4567 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4569 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4571 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4572 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4575 mono_array_setref (res, j, mono_module_get_object (domain, m));
4582 ICALL_EXPORT MonoReflectionMethod*
4583 ves_icall_GetCurrentMethod (void)
4585 MonoMethod *m = mono_method_get_last_managed ();
4588 mono_raise_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4590 while (m->is_inflated)
4591 m = ((MonoMethodInflated*)m)->declaring;
4593 return mono_method_get_object (mono_domain_get (), m, NULL);
4598 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4601 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4604 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4605 //method is inflated, we should inflate it on the other class
4606 MonoGenericContext ctx;
4607 ctx.method_inst = inflated->context.method_inst;
4608 ctx.class_inst = inflated->context.class_inst;
4609 if (klass->generic_class)
4610 ctx.class_inst = klass->generic_class->context.class_inst;
4611 else if (klass->generic_container)
4612 ctx.class_inst = klass->generic_container->context.class_inst;
4613 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4614 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4618 mono_class_setup_methods (method->klass);
4619 if (method->klass->exception_type)
4621 for (i = 0; i < method->klass->method.count; ++i) {
4622 if (method->klass->methods [i] == method) {
4627 mono_class_setup_methods (klass);
4628 if (klass->exception_type)
4630 g_assert (offset >= 0 && offset < klass->method.count);
4631 return klass->methods [offset];
4634 ICALL_EXPORT MonoReflectionMethod*
4635 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4639 klass = mono_class_from_mono_type (type);
4640 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4642 if (method->klass != klass) {
4643 method = mono_method_get_equivalent_method (method, klass);
4648 klass = method->klass;
4649 return mono_method_get_object (mono_domain_get (), method, klass);
4652 ICALL_EXPORT MonoReflectionMethodBody*
4653 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4655 return mono_method_body_get_object (mono_domain_get (), method);
4658 ICALL_EXPORT MonoReflectionAssembly*
4659 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4661 MonoMethod *dest = NULL;
4663 mono_stack_walk_no_il (get_executing, &dest);
4665 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4669 ICALL_EXPORT MonoReflectionAssembly*
4670 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4672 MonoDomain* domain = mono_domain_get ();
4674 if (!domain->entry_assembly)
4677 return mono_assembly_get_object (domain, domain->entry_assembly);
4680 ICALL_EXPORT MonoReflectionAssembly*
4681 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4687 mono_stack_walk_no_il (get_executing, &dest);
4689 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
4693 mono_raise_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4694 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4697 ICALL_EXPORT MonoString *
4698 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4699 gboolean assembly_qualified)
4701 MonoDomain *domain = mono_object_domain (object);
4702 MonoTypeNameFormat format;
4707 format = assembly_qualified ?
4708 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4709 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4711 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4713 name = mono_type_get_name_full (object->type, format);
4717 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4722 res = mono_string_new (domain, name);
4729 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
4731 MonoClass *klass = mono_class_from_mono_type (rfield->type);
4732 mono_class_init_or_throw (klass);
4733 return mono_security_core_clr_class_level (klass);
4737 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
4739 MonoClassField *field = rfield->field;
4740 return mono_security_core_clr_field_level (field, TRUE);
4744 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
4746 MonoMethod *method = rfield->method;
4747 return mono_security_core_clr_method_level (method, TRUE);
4751 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4753 static MonoMethod *create_culture = NULL;
4756 const char *pkey_ptr;
4758 MonoBoolean assembly_ref = 0;
4760 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4761 aname->major = name->major;
4762 aname->minor = name->minor;
4763 aname->build = name->build;
4764 aname->flags = name->flags;
4765 aname->revision = name->revision;
4766 aname->hashalg = name->hash_alg;
4767 aname->versioncompat = 1; /* SameMachine (default) */
4768 aname->processor_architecture = name->arch;
4770 if (by_default_version)
4771 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4774 if (absolute != NULL && *absolute != '\0') {
4775 const gchar *prepend = "file://";
4778 codebase = g_strdup (absolute);
4783 for (i = strlen (codebase) - 1; i >= 0; i--)
4784 if (codebase [i] == '\\')
4787 if (*codebase == '/' && *(codebase + 1) == '/') {
4790 prepend = "file:///";
4794 result = g_strconcat (prepend, codebase, NULL);
4800 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4804 if (!create_culture) {
4805 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4806 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4807 g_assert (create_culture);
4808 mono_method_desc_free (desc);
4811 if (name->culture) {
4812 args [0] = mono_string_new (domain, name->culture);
4813 args [1] = &assembly_ref;
4814 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4817 if (name->public_key) {
4818 pkey_ptr = (char*)name->public_key;
4819 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4821 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4822 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4823 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4824 } else if (default_publickey) {
4825 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4826 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4829 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4830 if (name->public_key_token [0]) {
4834 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4835 p = mono_array_addr (aname->keyToken, char, 0);
4837 for (i = 0, j = 0; i < 8; i++) {
4838 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4839 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4842 } else if (default_token) {
4843 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4847 ICALL_EXPORT MonoString *
4848 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4850 MonoDomain *domain = mono_object_domain (assembly);
4851 MonoAssembly *mass = assembly->assembly;
4855 name = mono_stringify_assembly_name (&mass->aname);
4856 res = mono_string_new (domain, name);
4863 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4866 MonoAssembly *mass = assembly->assembly;
4868 if (g_path_is_absolute (mass->image->name)) {
4869 fill_reflection_assembly_name (mono_object_domain (assembly),
4870 aname, &mass->aname, mass->image->name, TRUE,
4874 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4876 fill_reflection_assembly_name (mono_object_domain (assembly),
4877 aname, &mass->aname, absolute, TRUE, TRUE,
4884 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4887 MonoImageOpenStatus status = MONO_IMAGE_OK;
4890 MonoAssemblyName name;
4893 filename = mono_string_to_utf8 (fname);
4895 dirname = g_path_get_dirname (filename);
4896 replace_shadow_path (mono_domain_get (), dirname, &filename);
4899 image = mono_image_open (filename, &status);
4905 if (status == MONO_IMAGE_IMAGE_INVALID)
4906 exc = mono_get_exception_bad_image_format2 (NULL, fname);
4908 exc = mono_get_exception_file_not_found2 (NULL, fname);
4909 mono_set_pending_exception (exc);
4913 res = mono_assembly_fill_assembly_name (image, &name);
4915 mono_image_close (image);
4917 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4921 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
4925 mono_image_close (image);
4928 ICALL_EXPORT MonoBoolean
4929 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4930 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4932 MonoBoolean result = FALSE;
4933 MonoDeclSecurityEntry entry;
4935 /* SecurityAction.RequestMinimum */
4936 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4937 *minimum = entry.blob;
4938 *minLength = entry.size;
4941 /* SecurityAction.RequestOptional */
4942 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4943 *optional = entry.blob;
4944 *optLength = entry.size;
4947 /* SecurityAction.RequestRefuse */
4948 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4949 *refused = entry.blob;
4950 *refLength = entry.size;
4958 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
4960 guint32 attrs, visibility;
4962 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
4963 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4964 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
4967 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
4973 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
4977 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4980 /* we start the count from 1 because we skip the special type <Module> */
4983 for (i = 1; i < tdef->rows; ++i) {
4984 if (mono_module_type_is_visible (tdef, image, i + 1))
4988 count = tdef->rows - 1;
4990 res = mono_array_new (domain, mono_defaults.monotype_class, count);
4991 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
4993 for (i = 1; i < tdef->rows; ++i) {
4994 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
4996 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
4997 mono_loader_assert_no_error (); /* Plug any leaks */
5000 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5002 MonoException *ex = mono_error_convert_to_exception (&error);
5003 mono_array_setref (*exceptions, count, ex);
5012 ICALL_EXPORT MonoArray*
5013 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5015 MonoArray *res = NULL;
5016 MonoArray *exceptions = NULL;
5017 MonoImage *image = NULL;
5018 MonoTableInfo *table = NULL;
5021 int i, len, ex_count;
5023 domain = mono_object_domain (assembly);
5025 g_assert (!assembly_is_dynamic (assembly->assembly));
5026 image = assembly->assembly->image;
5027 table = &image->tables [MONO_TABLE_FILE];
5028 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5030 /* Append data from all modules in the assembly */
5031 for (i = 0; i < table->rows; ++i) {
5032 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5033 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5036 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5037 /* Append the new types to the end of the array */
5038 if (mono_array_length (res2) > 0) {
5040 MonoArray *res3, *ex3;
5042 len1 = mono_array_length (res);
5043 len2 = mono_array_length (res2);
5045 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5046 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5047 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5050 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5051 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5052 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5059 /* the ReflectionTypeLoadException must have all the types (Types property),
5060 * NULL replacing types which throws an exception. The LoaderException must
5061 * contain all exceptions for NULL items.
5064 len = mono_array_length (res);
5067 for (i = 0; i < len; i++) {
5068 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5072 klass = mono_type_get_class (t->type);
5073 if ((klass != NULL) && klass->exception_type) {
5074 /* keep the class in the list */
5075 list = g_list_append (list, klass);
5076 /* and replace Type with NULL */
5077 mono_array_setref (res, i, NULL);
5084 if (list || ex_count) {
5086 MonoException *exc = NULL;
5087 MonoArray *exl = NULL;
5088 int j, length = g_list_length (list) + ex_count;
5090 mono_loader_clear_error ();
5092 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5093 /* Types for which mono_class_get_checked () succeeded */
5094 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5095 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5096 mono_array_setref (exl, i, exc);
5098 /* Types for which it don't */
5099 for (j = 0; j < mono_array_length (exceptions); ++j) {
5100 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5102 g_assert (i < length);
5103 mono_array_setref (exl, i, exc);
5110 exc = mono_get_exception_reflection_type_load (res, exl);
5111 mono_loader_clear_error ();
5112 mono_set_pending_exception (exc);
5119 ICALL_EXPORT gboolean
5120 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5122 MonoAssemblyName aname;
5123 MonoDomain *domain = mono_object_domain (name);
5125 gboolean is_version_defined;
5126 gboolean is_token_defined;
5128 aname.public_key = NULL;
5129 val = mono_string_to_utf8 (assname);
5130 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5131 g_free ((guint8*) aname.public_key);
5136 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5137 FALSE, is_token_defined);
5139 mono_assembly_name_free (&aname);
5140 g_free ((guint8*) aname.public_key);
5146 ICALL_EXPORT MonoReflectionType*
5147 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5150 MonoDomain *domain = mono_object_domain (module);
5153 g_assert (module->image);
5155 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5156 /* These images do not have a global type */
5159 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5160 mono_error_raise_exception (&error);
5161 return mono_type_get_object (domain, &klass->byval_arg);
5165 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5167 /*if (module->image)
5168 mono_image_close (module->image);*/
5171 ICALL_EXPORT MonoString*
5172 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5174 MonoDomain *domain = mono_object_domain (module);
5176 g_assert (module->image);
5177 return mono_string_new (domain, module->image->guid);
5180 ICALL_EXPORT gpointer
5181 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5184 if (module->image && module->image->is_module_handle)
5185 return module->image->raw_data;
5188 return (gpointer) (-1);
5192 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5194 if (image_is_dynamic (image)) {
5195 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5196 *pe_kind = dyn->pe_kind;
5197 *machine = dyn->machine;
5200 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5201 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5206 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5208 return (image->md_version_major << 16) | (image->md_version_minor);
5211 ICALL_EXPORT MonoArray*
5212 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5214 MonoArray *exceptions;
5218 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5220 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5221 for (i = 0; i < mono_array_length (exceptions); ++i) {
5222 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5224 mono_set_pending_exception (ex);
5233 mono_memberref_is_method (MonoImage *image, guint32 token)
5235 if (!image_is_dynamic (image)) {
5236 guint32 cols [MONO_MEMBERREF_SIZE];
5238 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5239 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5240 mono_metadata_decode_blob_size (sig, &sig);
5241 return (*sig != 0x6);
5243 MonoClass *handle_class;
5245 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5248 return mono_defaults.methodhandle_class == handle_class;
5253 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5256 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5257 mono_array_addr (type_args, MonoType*, 0));
5259 context->class_inst = NULL;
5261 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5262 mono_array_addr (method_args, MonoType*, 0));
5264 context->method_inst = NULL;
5267 ICALL_EXPORT MonoType*
5268 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5271 int table = mono_metadata_token_table (token);
5272 int index = mono_metadata_token_index (token);
5273 MonoGenericContext context;
5276 *resolve_error = ResolveTokenError_Other;
5278 /* Validate token */
5279 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5280 (table != MONO_TABLE_TYPESPEC)) {
5281 *resolve_error = ResolveTokenError_BadTable;
5285 if (image_is_dynamic (image)) {
5286 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5287 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5288 return klass ? &klass->byval_arg : NULL;
5291 init_generic_context_from_args (&context, type_args, method_args);
5292 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5293 return klass ? &klass->byval_arg : NULL;
5296 if ((index <= 0) || (index > image->tables [table].rows)) {
5297 *resolve_error = ResolveTokenError_OutOfRange;
5301 init_generic_context_from_args (&context, type_args, method_args);
5302 klass = mono_class_get_checked (image, token, &error);
5304 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5305 mono_error_raise_exception (&error);
5308 return &klass->byval_arg;
5313 ICALL_EXPORT MonoMethod*
5314 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5317 int table = mono_metadata_token_table (token);
5318 int index = mono_metadata_token_index (token);
5319 MonoGenericContext context;
5322 *resolve_error = ResolveTokenError_Other;
5324 /* Validate token */
5325 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5326 (table != MONO_TABLE_MEMBERREF)) {
5327 *resolve_error = ResolveTokenError_BadTable;
5331 if (image_is_dynamic (image)) {
5332 if (table == MONO_TABLE_METHOD)
5333 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5335 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5336 *resolve_error = ResolveTokenError_BadTable;
5340 init_generic_context_from_args (&context, type_args, method_args);
5341 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5344 if ((index <= 0) || (index > image->tables [table].rows)) {
5345 *resolve_error = ResolveTokenError_OutOfRange;
5348 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5349 *resolve_error = ResolveTokenError_BadTable;
5353 init_generic_context_from_args (&context, type_args, method_args);
5354 method = mono_get_method_checked (image, token, NULL, &context, &error);
5355 mono_error_raise_exception (&error);
5360 ICALL_EXPORT MonoString*
5361 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5363 int index = mono_metadata_token_index (token);
5365 *error = ResolveTokenError_Other;
5367 /* Validate token */
5368 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5369 *error = ResolveTokenError_BadTable;
5373 if (image_is_dynamic (image))
5374 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5376 if ((index <= 0) || (index >= image->heap_us.size)) {
5377 *error = ResolveTokenError_OutOfRange;
5381 /* FIXME: What to do if the index points into the middle of a string ? */
5383 return mono_ldstr (mono_domain_get (), image, index);
5386 ICALL_EXPORT MonoClassField*
5387 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5391 int table = mono_metadata_token_table (token);
5392 int index = mono_metadata_token_index (token);
5393 MonoGenericContext context;
5394 MonoClassField *field;
5396 *resolve_error = ResolveTokenError_Other;
5398 /* Validate token */
5399 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5400 *resolve_error = ResolveTokenError_BadTable;
5404 if (image_is_dynamic (image)) {
5405 if (table == MONO_TABLE_FIELD)
5406 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5408 if (mono_memberref_is_method (image, token)) {
5409 *resolve_error = ResolveTokenError_BadTable;
5413 init_generic_context_from_args (&context, type_args, method_args);
5414 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5417 if ((index <= 0) || (index > image->tables [table].rows)) {
5418 *resolve_error = ResolveTokenError_OutOfRange;
5421 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5422 *resolve_error = ResolveTokenError_BadTable;
5426 init_generic_context_from_args (&context, type_args, method_args);
5427 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5428 mono_error_raise_exception (&error);
5434 ICALL_EXPORT MonoObject*
5435 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5437 int table = mono_metadata_token_table (token);
5439 *error = ResolveTokenError_Other;
5442 case MONO_TABLE_TYPEDEF:
5443 case MONO_TABLE_TYPEREF:
5444 case MONO_TABLE_TYPESPEC: {
5445 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5447 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5451 case MONO_TABLE_METHOD:
5452 case MONO_TABLE_METHODSPEC: {
5453 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5455 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5459 case MONO_TABLE_FIELD: {
5460 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5462 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5466 case MONO_TABLE_MEMBERREF:
5467 if (mono_memberref_is_method (image, token)) {
5468 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5470 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5475 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5477 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5484 *error = ResolveTokenError_BadTable;
5490 ICALL_EXPORT MonoArray*
5491 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5493 int table = mono_metadata_token_table (token);
5494 int idx = mono_metadata_token_index (token);
5495 MonoTableInfo *tables = image->tables;
5500 *error = ResolveTokenError_OutOfRange;
5502 /* FIXME: Support other tables ? */
5503 if (table != MONO_TABLE_STANDALONESIG)
5506 if (image_is_dynamic (image))
5509 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5512 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5514 ptr = mono_metadata_blob_heap (image, sig);
5515 len = mono_metadata_decode_blob_size (ptr, &ptr);
5517 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5518 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5522 ICALL_EXPORT MonoReflectionType*
5523 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5526 int isbyref = 0, rank;
5527 char *str = mono_string_to_utf8 (smodifiers);
5530 klass = mono_class_from_mono_type (tb->type.type);
5532 /* logic taken from mono_reflection_parse_type(): keep in sync */
5536 if (isbyref) { /* only one level allowed by the spec */
5543 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5546 klass = mono_ptr_class_get (&klass->byval_arg);
5547 mono_class_init (klass);
5558 else if (*p != '*') { /* '*' means unknown lower bound */
5569 klass = mono_array_class_get (klass, rank);
5570 mono_class_init (klass);
5577 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5580 ICALL_EXPORT MonoBoolean
5581 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5587 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5593 check_for_invalid_type (MonoClass *klass)
5597 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5600 name = mono_type_get_full_name (klass);
5601 str = mono_string_new (mono_domain_get (), name);
5603 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5606 ICALL_EXPORT MonoReflectionType *
5607 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5609 MonoClass *klass, *aklass;
5611 klass = mono_class_from_mono_type (type->type);
5612 check_for_invalid_type (klass);
5614 if (rank == 0) //single dimentional array
5615 aklass = mono_array_class_get (klass, 1);
5617 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5619 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5622 ICALL_EXPORT MonoReflectionType *
5623 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5627 klass = mono_class_from_mono_type (type->type);
5628 mono_class_init_or_throw (klass);
5629 check_for_invalid_type (klass);
5631 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5634 ICALL_EXPORT MonoReflectionType *
5635 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5637 MonoClass *klass, *pklass;
5639 klass = mono_class_from_mono_type (type->type);
5640 mono_class_init_or_throw (klass);
5641 check_for_invalid_type (klass);
5643 pklass = mono_ptr_class_get (type->type);
5645 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5648 ICALL_EXPORT MonoObject *
5649 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5650 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5652 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5653 MonoObject *delegate;
5655 MonoMethod *method = info->method;
5657 mono_class_init_or_throw (delegate_class);
5659 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5661 if (mono_security_core_clr_enabled ()) {
5662 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5666 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5668 if (method_is_dynamic (method)) {
5669 /* Creating a trampoline would leak memory */
5670 func = mono_compile_method (method);
5672 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5673 method = mono_object_get_virtual_method (target, method);
5674 func = mono_create_ftnptr (mono_domain_get (),
5675 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5678 mono_delegate_ctor_with_method (delegate, target, func, method);
5683 ICALL_EXPORT MonoMulticastDelegate *
5684 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
5686 MonoMulticastDelegate *ret;
5688 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
5690 ret = (MonoMulticastDelegate*) mono_object_new (mono_object_domain (delegate), mono_object_class (delegate));
5691 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
5696 ICALL_EXPORT MonoReflectionMethod*
5697 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
5699 return mono_method_get_object (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target));
5704 static inline gint32
5705 mono_array_get_byte_length (MonoArray *array)
5711 klass = array->obj.vtable->klass;
5713 if (array->bounds == NULL)
5714 length = array->max_length;
5717 for (i = 0; i < klass->rank; ++ i)
5718 length *= array->bounds [i].length;
5721 switch (klass->element_class->byval_arg.type) {
5724 case MONO_TYPE_BOOLEAN:
5728 case MONO_TYPE_CHAR:
5736 return length * sizeof (gpointer);
5747 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
5749 return mono_array_get_byte_length (array);
5753 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
5755 return mono_array_get (array, gint8, idx);
5759 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
5761 mono_array_set (array, gint8, idx, value);
5764 ICALL_EXPORT MonoBoolean
5765 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
5767 guint8 *src_buf, *dest_buf;
5770 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
5774 g_assert (count >= 0);
5776 /* This is called directly from the class libraries without going through the managed wrapper */
5777 MONO_CHECK_ARG_NULL (src, FALSE);
5778 MONO_CHECK_ARG_NULL (dest, FALSE);
5780 /* watch out for integer overflow */
5781 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5784 src_buf = (guint8 *)src->vector + src_offset;
5785 dest_buf = (guint8 *)dest->vector + dest_offset;
5788 memcpy (dest_buf, src_buf, count);
5790 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5795 #ifndef DISABLE_REMOTING
5796 ICALL_EXPORT MonoObject *
5797 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
5799 MonoDomain *domain = mono_object_domain (this_obj);
5801 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
5802 MonoTransparentProxy *tp;
5806 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5807 tp = (MonoTransparentProxy*) res;
5809 MONO_OBJECT_SETREF (tp, rp, rp);
5810 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5811 klass = mono_class_from_mono_type (type);
5813 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
5814 mono_class_setup_vtable (klass);
5815 if (klass->exception_type)
5816 mono_raise_exception (mono_class_get_exception_for_failure (klass));
5818 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
5819 tp->remote_class = mono_remote_class (domain, class_name, klass);
5821 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
5825 ICALL_EXPORT MonoReflectionType *
5826 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5828 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5832 /* System.Environment */
5835 ves_icall_System_Environment_get_UserName (void)
5837 /* using glib is more portable */
5838 return mono_string_new (mono_domain_get (), g_get_user_name ());
5842 ICALL_EXPORT MonoString *
5843 ves_icall_System_Environment_get_MachineName (void)
5845 #if defined (HOST_WIN32)
5850 len = MAX_COMPUTERNAME_LENGTH + 1;
5851 buf = g_new (gunichar2, len);
5854 if (GetComputerName (buf, (PDWORD) &len))
5855 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5859 #elif !defined(DISABLE_SOCKETS)
5863 #if defined _SC_HOST_NAME_MAX
5864 n = sysconf (_SC_HOST_NAME_MAX);
5868 buf = g_malloc (n+1);
5870 if (gethostname (buf, n) == 0){
5872 result = mono_string_new (mono_domain_get (), buf);
5879 return mono_string_new (mono_domain_get (), "mono");
5884 ves_icall_System_Environment_get_Platform (void)
5886 #if defined (TARGET_WIN32)
5889 #elif defined(__MACH__)
5892 // Notice that the value is hidden from user code, and only exposed
5893 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
5894 // define and making assumptions based on Unix/128/4 values before there
5895 // was a MacOS define. Lots of code would assume that not-Unix meant
5896 // Windows, but in this case, it would be OSX.
5905 ICALL_EXPORT MonoString *
5906 ves_icall_System_Environment_get_NewLine (void)
5908 #if defined (HOST_WIN32)
5909 return mono_string_new (mono_domain_get (), "\r\n");
5911 return mono_string_new (mono_domain_get (), "\n");
5915 ICALL_EXPORT MonoBoolean
5916 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
5918 #if SIZEOF_VOID_P == 8
5922 gboolean isWow64Process = FALSE;
5923 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
5924 return (MonoBoolean)isWow64Process;
5926 #elif defined(HAVE_SYS_UTSNAME_H)
5927 struct utsname name;
5929 if (uname (&name) >= 0) {
5930 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
5937 ICALL_EXPORT MonoString *
5938 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5946 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5947 value = g_getenv (utf8_name);
5954 return mono_string_new (mono_domain_get (), value);
5958 * There is no standard way to get at environ.
5961 #ifndef __MINGW32_VERSION
5962 #if defined(__APPLE__)
5963 #if defined (TARGET_OSX)
5964 /* Apple defines this in crt_externs.h but doesn't provide that header for
5965 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
5966 * in fact exist on all implementations (so far)
5968 gchar ***_NSGetEnviron(void);
5969 #define environ (*_NSGetEnviron())
5971 static char *mono_environ[1] = { NULL };
5972 #define environ mono_environ
5973 #endif /* defined (TARGET_OSX) */
5981 ICALL_EXPORT MonoArray *
5982 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
5993 env_strings = GetEnvironmentStrings();
5996 env_string = env_strings;
5997 while (*env_string != '\0') {
5998 /* weird case that MS seems to skip */
5999 if (*env_string != '=')
6001 while (*env_string != '\0')
6007 domain = mono_domain_get ();
6008 names = mono_array_new (domain, mono_defaults.string_class, n);
6012 env_string = env_strings;
6013 while (*env_string != '\0') {
6014 /* weird case that MS seems to skip */
6015 if (*env_string != '=') {
6016 equal_str = wcschr(env_string, '=');
6017 g_assert(equal_str);
6018 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6019 mono_array_setref (names, n, str);
6022 while (*env_string != '\0')
6027 FreeEnvironmentStrings (env_strings);
6040 for (e = environ; *e != 0; ++ e)
6043 domain = mono_domain_get ();
6044 names = mono_array_new (domain, mono_defaults.string_class, n);
6047 for (e = environ; *e != 0; ++ e) {
6048 parts = g_strsplit (*e, "=", 2);
6050 str = mono_string_new (domain, *parts);
6051 mono_array_setref (names, n, str);
6064 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6066 #if !GLIB_CHECK_VERSION(2,4,0)
6067 #define g_setenv(a,b,c) setenv(a,b,c)
6068 #define g_unsetenv(a) unsetenv(a)
6072 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6075 gunichar2 *utf16_name, *utf16_value;
6077 gchar *utf8_name, *utf8_value;
6082 utf16_name = mono_string_to_utf16 (name);
6083 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6084 SetEnvironmentVariable (utf16_name, NULL);
6085 g_free (utf16_name);
6089 utf16_value = mono_string_to_utf16 (value);
6091 SetEnvironmentVariable (utf16_name, utf16_value);
6093 g_free (utf16_name);
6094 g_free (utf16_value);
6096 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6098 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6099 g_unsetenv (utf8_name);
6104 utf8_value = mono_string_to_utf8_checked (value, &error);
6105 if (!mono_error_ok (&error)) {
6107 mono_error_raise_exception (&error);
6109 g_setenv (utf8_name, utf8_value, TRUE);
6112 g_free (utf8_value);
6117 ves_icall_System_Environment_Exit (int result)
6119 mono_environment_exitcode_set (result);
6121 /* FIXME: There are some cleanup hangs that should be worked out, but
6122 * if the program is going to exit, everything will be cleaned up when
6123 * NaCl exits anyway.
6125 #ifndef __native_client__
6126 if (!mono_runtime_try_shutdown ())
6127 mono_thread_exit ();
6129 /* Suspend all managed threads since the runtime is going away */
6130 mono_thread_suspend_all_other_threads ();
6132 mono_runtime_quit ();
6135 /* we may need to do some cleanup here... */
6139 ICALL_EXPORT MonoString*
6140 ves_icall_System_Environment_GetGacPath (void)
6142 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6145 ICALL_EXPORT MonoString*
6146 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6148 #if defined (HOST_WIN32)
6149 #ifndef CSIDL_FLAG_CREATE
6150 #define CSIDL_FLAG_CREATE 0x8000
6153 WCHAR path [MAX_PATH];
6154 /* Create directory if no existing */
6155 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6159 return mono_string_new_utf16 (mono_domain_get (), path, len);
6162 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6164 return mono_string_new (mono_domain_get (), "");
6167 ICALL_EXPORT MonoArray *
6168 ves_icall_System_Environment_GetLogicalDrives (void)
6170 gunichar2 buf [256], *ptr, *dname;
6172 guint initial_size = 127, size = 128;
6175 MonoString *drivestr;
6176 MonoDomain *domain = mono_domain_get ();
6182 while (size > initial_size) {
6183 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6184 if (size > initial_size) {
6187 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6188 initial_size = size;
6202 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6207 while (*u16) { u16++; len ++; }
6208 drivestr = mono_string_new_utf16 (domain, dname, len);
6209 mono_array_setref (result, ndrives++, drivestr);
6219 ICALL_EXPORT MonoString *
6220 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6222 gunichar2 volume_name [MAX_PATH + 1];
6224 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6226 return mono_string_from_utf16 (volume_name);
6229 ICALL_EXPORT MonoString *
6230 ves_icall_System_Environment_InternalGetHome (void)
6232 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6235 static const char *encodings [] = {
6237 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6238 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6239 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6241 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6242 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6243 "x_unicode_2_0_utf_7",
6245 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6246 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6248 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6251 "unicodefffe", "utf_16be",
6258 * Returns the internal codepage, if the value of "int_code_page" is
6259 * 1 at entry, and we can not compute a suitable code page number,
6260 * returns the code page as a string
6262 ICALL_EXPORT MonoString*
6263 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6268 char *codepage = NULL;
6270 int want_name = *int_code_page;
6273 *int_code_page = -1;
6275 g_get_charset (&cset);
6276 c = codepage = strdup (cset);
6277 for (c = codepage; *c; c++){
6278 if (isascii (*c) && isalpha (*c))
6283 /* g_print ("charset: %s\n", cset); */
6285 /* handle some common aliases */
6288 for (i = 0; p != 0; ){
6291 p = encodings [++i];
6294 if (strcmp (p, codepage) == 0){
6295 *int_code_page = code;
6298 p = encodings [++i];
6301 if (strstr (codepage, "utf_8") != NULL)
6302 *int_code_page |= 0x10000000;
6305 if (want_name && *int_code_page == -1)
6306 return mono_string_new (mono_domain_get (), cset);
6311 ICALL_EXPORT MonoBoolean
6312 ves_icall_System_Environment_get_HasShutdownStarted (void)
6314 if (mono_runtime_is_shutting_down ())
6317 if (mono_domain_is_unloading (mono_domain_get ()))
6324 ves_icall_System_Environment_BroadcastSettingChange (void)
6327 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6332 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6338 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6339 MonoReflectionMethod *method,
6340 MonoArray *out_args)
6342 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6345 #ifndef DISABLE_REMOTING
6346 ICALL_EXPORT MonoBoolean
6347 ves_icall_IsTransparentProxy (MonoObject *proxy)
6352 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6358 ICALL_EXPORT MonoReflectionMethod *
6359 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6360 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6364 MonoMethod **vtable;
6365 MonoMethod *res = NULL;
6367 MONO_CHECK_ARG_NULL (rtype, NULL);
6368 MONO_CHECK_ARG_NULL (rmethod, NULL);
6370 method = rmethod->method;
6371 klass = mono_class_from_mono_type (rtype->type);
6372 mono_class_init_or_throw (klass);
6374 if (MONO_CLASS_IS_INTERFACE (klass))
6377 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6380 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6381 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6387 mono_class_setup_vtable (klass);
6388 vtable = klass->vtable;
6390 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6391 gboolean variance_used = FALSE;
6392 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6393 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6395 res = vtable [offs + method->slot];
6397 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6400 if (method->slot != -1)
6401 res = vtable [method->slot];
6407 return mono_method_get_object (mono_domain_get (), res, NULL);
6411 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6416 klass = mono_class_from_mono_type (type->type);
6417 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6419 mono_vtable_set_is_remote (vtable, enable);
6422 #else /* DISABLE_REMOTING */
6425 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6427 g_assert_not_reached ();
6432 ICALL_EXPORT MonoObject *
6433 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6440 domain = mono_object_domain (type);
6441 klass = mono_class_from_mono_type (type->type);
6442 mono_class_init_or_throw (klass);
6444 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6445 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6449 if (klass->rank >= 1) {
6450 g_assert (klass->rank == 1);
6451 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6453 /* Bypass remoting object creation check */
6454 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6455 mono_error_raise_exception (&error);
6461 ICALL_EXPORT MonoString *
6462 ves_icall_System_IO_get_temp_path (void)
6464 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6467 #ifndef PLATFORM_NO_DRIVEINFO
6468 ICALL_EXPORT MonoBoolean
6469 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6470 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6474 ULARGE_INTEGER wapi_free_bytes_avail;
6475 ULARGE_INTEGER wapi_total_number_of_bytes;
6476 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6478 *error = ERROR_SUCCESS;
6479 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6480 &wapi_total_number_of_free_bytes);
6483 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6484 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6485 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6487 *free_bytes_avail = 0;
6488 *total_number_of_bytes = 0;
6489 *total_number_of_free_bytes = 0;
6490 *error = GetLastError ();
6496 ICALL_EXPORT guint32
6497 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6499 return GetDriveType (mono_string_chars (root_path_name));
6503 ICALL_EXPORT gpointer
6504 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6506 return mono_compile_method (method);
6509 ICALL_EXPORT MonoString *
6510 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6515 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6517 #if defined (HOST_WIN32)
6518 /* Avoid mixing '/' and '\\' */
6521 for (i = strlen (path) - 1; i >= 0; i--)
6522 if (path [i] == '/')
6526 mcpath = mono_string_new (mono_domain_get (), path);
6533 get_bundled_app_config (void)
6535 const gchar *app_config;
6538 gchar *config_file_name, *config_file_path;
6539 gsize len, config_file_path_length, config_ext_length;
6542 domain = mono_domain_get ();
6543 file = domain->setup->configuration_file;
6544 if (!file || file->length == 0)
6547 // Retrieve config file and remove the extension
6548 config_file_name = mono_string_to_utf8 (file);
6549 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6550 if (!config_file_path)
6551 config_file_path = config_file_name;
6553 config_file_path_length = strlen (config_file_path);
6554 config_ext_length = strlen (".config");
6555 if (config_file_path_length <= config_ext_length)
6558 len = config_file_path_length - config_ext_length;
6559 module = (gchar *)g_malloc0 (len + 1);
6560 memcpy (module, config_file_path, len);
6561 // Get the config file from the module name
6562 app_config = mono_config_string_for_assembly_file (module);
6565 if (config_file_name != config_file_path)
6566 g_free (config_file_name);
6567 g_free (config_file_path);
6572 return mono_string_new (mono_domain_get (), app_config);
6576 get_bundled_machine_config (void)
6578 const gchar *machine_config;
6580 machine_config = mono_get_machine_config ();
6582 if (!machine_config)
6585 return mono_string_new (mono_domain_get (), machine_config);
6588 ICALL_EXPORT MonoString *
6589 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6594 path = g_path_get_dirname (mono_get_config_dir ());
6596 #if defined (HOST_WIN32)
6597 /* Avoid mixing '/' and '\\' */
6600 for (i = strlen (path) - 1; i >= 0; i--)
6601 if (path [i] == '/')
6605 ipath = mono_string_new (mono_domain_get (), path);
6611 ICALL_EXPORT gboolean
6612 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6614 MonoPEResourceDataEntry *entry;
6617 if (!assembly || !result || !size)
6622 image = assembly->assembly->image;
6623 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6627 *result = mono_image_rva_map (image, entry->rde_data_offset);
6632 *size = entry->rde_size;
6637 ICALL_EXPORT MonoBoolean
6638 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6640 return mono_is_debugger_attached ();
6643 ICALL_EXPORT MonoBoolean
6644 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
6646 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
6647 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
6653 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
6655 if (mono_get_runtime_callbacks ()->debug_log)
6656 mono_get_runtime_callbacks ()->debug_log (level, category, message);
6660 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6662 #if defined (HOST_WIN32)
6663 OutputDebugString (mono_string_chars (message));
6665 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6669 /* Only used for value types */
6670 ICALL_EXPORT MonoObject *
6671 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6676 domain = mono_object_domain (type);
6677 klass = mono_class_from_mono_type (type->type);
6678 mono_class_init_or_throw (klass);
6680 if (mono_class_is_nullable (klass))
6681 /* No arguments -> null */
6684 return mono_object_new (domain, klass);
6687 ICALL_EXPORT MonoReflectionMethod *
6688 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6690 MonoClass *klass, *parent;
6691 MonoGenericContext *generic_inst = NULL;
6692 MonoMethod *method = m->method;
6693 MonoMethod *result = NULL;
6696 if (method->klass == NULL)
6699 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6700 MONO_CLASS_IS_INTERFACE (method->klass) ||
6701 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6704 slot = mono_method_get_vtable_slot (method);
6708 klass = method->klass;
6709 if (klass->generic_class) {
6710 generic_inst = mono_class_get_context (klass);
6711 klass = klass->generic_class->container_class;
6715 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6716 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6717 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6718 or klass is the generic container class and generic_inst is the instantiation.
6720 when we go to the parent, if the parent is an open constructed type, we need to
6721 replace the type parameters by the definitions from the generic_inst, and then take it
6722 apart again into the klass and the generic_inst.
6724 For cases like this:
6725 class C<T> : B<T, int> {
6726 public override void Foo () { ... }
6728 class B<U,V> : A<HashMap<U,V>> {
6729 public override void Foo () { ... }
6732 public virtual void Foo () { ... }
6735 if at each iteration the parent isn't open, we can skip inflating it. if at some
6736 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6739 MonoGenericContext *parent_inst = NULL;
6740 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
6742 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
6743 mono_error_raise_exception(&error);
6745 if (parent->generic_class) {
6746 parent_inst = mono_class_get_context (parent);
6747 parent = parent->generic_class->container_class;
6750 mono_class_setup_vtable (parent);
6751 if (parent->vtable_size <= slot)
6754 generic_inst = parent_inst;
6757 klass = klass->parent;
6760 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
6762 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6763 mono_error_raise_exception(&error);
6765 generic_inst = NULL;
6767 if (klass->generic_class) {
6768 generic_inst = mono_class_get_context (klass);
6769 klass = klass->generic_class->container_class;
6776 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6777 mono_error_raise_exception(&error);
6780 if (klass == method->klass)
6783 /*This is possible if definition == FALSE.
6784 * Do it here to be really sure we don't read invalid memory.
6786 if (slot >= klass->vtable_size)
6789 mono_class_setup_vtable (klass);
6791 result = klass->vtable [slot];
6792 if (result == NULL) {
6793 /* It is an abstract method */
6794 gpointer iter = NULL;
6795 while ((result = mono_class_get_methods (klass, &iter)))
6796 if (result->slot == slot)
6803 return mono_method_get_object (mono_domain_get (), result, NULL);
6806 ICALL_EXPORT MonoString*
6807 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6809 MonoMethod *method = m->method;
6811 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6816 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6818 iter->sig = *(MonoMethodSignature**)argsp;
6820 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6821 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6824 /* FIXME: it's not documented what start is exactly... */
6828 iter->args = argsp + sizeof (gpointer);
6830 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6832 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6835 ICALL_EXPORT MonoTypedRef
6836 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6838 guint32 i, arg_size;
6842 i = iter->sig->sentinelpos + iter->next_arg;
6844 g_assert (i < iter->sig->param_count);
6846 res.type = iter->sig->params [i];
6847 res.klass = mono_class_from_mono_type (res.type);
6848 arg_size = mono_type_stack_size (res.type, &align);
6849 #if defined(__arm__) || defined(__mips__)
6850 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6852 res.value = iter->args;
6853 #if defined(__native_client__) && SIZEOF_REGISTER == 8
6854 /* Values are stored as 8 byte register sized objects, but 'value'
6855 * is dereferenced as a pointer in other routines.
6857 res.value = (char*)res.value + 4;
6859 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6860 if (arg_size <= sizeof (gpointer)) {
6862 int padding = arg_size - mono_type_size (res.type, &dummy);
6863 res.value = (guint8*)res.value + padding;
6866 iter->args = (char*)iter->args + arg_size;
6869 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6874 ICALL_EXPORT MonoTypedRef
6875 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6877 guint32 i, arg_size;
6881 i = iter->sig->sentinelpos + iter->next_arg;
6883 g_assert (i < iter->sig->param_count);
6885 while (i < iter->sig->param_count) {
6886 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6888 res.type = iter->sig->params [i];
6889 res.klass = mono_class_from_mono_type (res.type);
6890 /* FIXME: endianess issue... */
6891 arg_size = mono_type_stack_size (res.type, &align);
6892 #if defined(__arm__) || defined(__mips__)
6893 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6895 res.value = iter->args;
6896 iter->args = (char*)iter->args + arg_size;
6898 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6901 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6909 ICALL_EXPORT MonoType*
6910 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6914 i = iter->sig->sentinelpos + iter->next_arg;
6916 g_assert (i < iter->sig->param_count);
6918 return iter->sig->params [i];
6921 ICALL_EXPORT MonoObject*
6922 mono_TypedReference_ToObject (MonoTypedRef* tref)
6924 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
6925 MonoObject** objp = (MonoObject **)tref->value;
6929 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
6932 ICALL_EXPORT MonoTypedRef
6933 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
6936 MonoReflectionField *f;
6938 MonoType *ftype = NULL;
6942 memset (&res, 0, sizeof (res));
6945 g_assert (mono_array_length (fields) > 0);
6947 klass = target->vtable->klass;
6949 for (i = 0; i < mono_array_length (fields); ++i) {
6950 f = mono_array_get (fields, MonoReflectionField*, i);
6952 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
6955 if (f->field->parent != klass) {
6956 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
6960 p = (guint8*)target + f->field->offset;
6962 p += f->field->offset - sizeof (MonoObject);
6963 klass = mono_class_from_mono_type (f->field->type);
6964 ftype = f->field->type;
6968 res.klass = mono_class_from_mono_type (ftype);
6975 prelink_method (MonoMethod *method)
6977 const char *exc_class, *exc_arg;
6978 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6980 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6982 mono_raise_exception(
6983 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6985 /* create the wrapper, too? */
6989 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6991 prelink_method (method->method);
6995 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6997 MonoClass *klass = mono_class_from_mono_type (type->type);
6999 gpointer iter = NULL;
7001 mono_class_init_or_throw (klass);
7003 while ((m = mono_class_get_methods (klass, &iter)))
7007 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7009 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7010 gint32 const **exponents,
7011 gunichar2 const **digitLowerTable,
7012 gunichar2 const **digitUpperTable,
7013 gint64 const **tenPowersList,
7014 gint32 const **decHexDigits)
7016 *mantissas = Formatter_MantissaBitsTable;
7017 *exponents = Formatter_TensExponentTable;
7018 *digitLowerTable = Formatter_DigitLowerTable;
7019 *digitUpperTable = Formatter_DigitUpperTable;
7020 *tenPowersList = Formatter_TenPowersList;
7021 *decHexDigits = Formatter_DecHexDigits;
7025 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7026 * and avoid useless allocations.
7031 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7035 for (i = 0; i < type->num_mods; ++i) {
7036 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7041 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7043 for (i = 0; i < type->num_mods; ++i) {
7044 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7046 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7047 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7048 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7055 ICALL_EXPORT MonoArray*
7056 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7058 MonoType *type = param->ClassImpl->type;
7059 MonoClass *member_class = mono_object_class (param->MemberImpl);
7060 MonoMethod *method = NULL;
7063 MonoMethodSignature *sig;
7065 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7066 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7067 method = rmethod->method;
7068 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7069 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7070 if (!(method = prop->property->get))
7071 method = prop->property->set;
7074 char *type_name = mono_type_get_full_name (member_class);
7075 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7076 MonoException *ex = mono_get_exception_not_supported (msg);
7079 mono_set_pending_exception (ex);
7083 image = method->klass->image;
7084 pos = param->PositionImpl;
7085 sig = mono_method_signature (method);
7089 type = sig->params [pos];
7091 return type_array_from_modifiers (image, type, optional);
7095 get_property_type (MonoProperty *prop)
7097 MonoMethodSignature *sig;
7099 sig = mono_method_signature (prop->get);
7101 } else if (prop->set) {
7102 sig = mono_method_signature (prop->set);
7103 return sig->params [sig->param_count - 1];
7108 ICALL_EXPORT MonoArray*
7109 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7111 MonoType *type = get_property_type (property->property);
7112 MonoImage *image = property->klass->image;
7116 return type_array_from_modifiers (image, type, optional);
7120 *Construct a MonoType suited to be used to decode a constant blob object.
7122 * @type is the target type which will be constructed
7123 * @blob_type is the blob type, for example, that comes from the constant table
7124 * @real_type is the expected constructed type.
7127 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7129 type->type = blob_type;
7130 type->data.klass = NULL;
7131 if (blob_type == MONO_TYPE_CLASS)
7132 type->data.klass = mono_defaults.object_class;
7133 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7134 /* For enums, we need to use the base type */
7135 type->type = MONO_TYPE_VALUETYPE;
7136 type->data.klass = mono_class_from_mono_type (real_type);
7138 type->data.klass = mono_class_from_mono_type (real_type);
7141 ICALL_EXPORT MonoObject*
7142 property_info_get_default_value (MonoReflectionProperty *property)
7145 MonoProperty *prop = property->property;
7146 MonoType *type = get_property_type (prop);
7147 MonoDomain *domain = mono_object_domain (property);
7148 MonoTypeEnum def_type;
7149 const char *def_value;
7152 mono_class_init (prop->parent);
7154 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7155 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7159 def_value = mono_class_get_property_default_value (prop, &def_type);
7161 mono_type_from_blob_type (&blob_type, def_type, type);
7162 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7167 ICALL_EXPORT MonoBoolean
7168 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7170 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7171 MonoCustomAttrInfo *cinfo;
7174 mono_class_init_or_throw (attr_class);
7176 cinfo = mono_reflection_get_custom_attrs_info (obj);
7179 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7181 mono_custom_attrs_free (cinfo);
7185 ICALL_EXPORT MonoArray*
7186 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7188 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7193 mono_class_init_or_throw (attr_class);
7195 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7196 mono_error_raise_exception (&error);
7198 if (mono_loader_get_last_error ()) {
7199 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7206 ICALL_EXPORT MonoString*
7207 ves_icall_Mono_Runtime_GetDisplayName (void)
7210 MonoString *display_name;
7212 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7213 display_name = mono_string_new (mono_domain_get (), info);
7215 return display_name;
7218 ICALL_EXPORT MonoString*
7219 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7221 MonoString *message;
7225 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7226 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7229 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7231 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7238 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7241 char *path_str = mono_string_to_utf8 (path);
7243 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7251 #ifndef DISABLE_ICALL_TABLES
7253 #define ICALL_TYPE(id,name,first)
7254 #define ICALL(id,name,func) Icall_ ## id,
7257 #include "metadata/icall-def.h"
7263 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7264 #define ICALL(id,name,func)
7266 #include "metadata/icall-def.h"
7272 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7273 #define ICALL(id,name,func)
7275 guint16 first_icall;
7278 static const IcallTypeDesc
7279 icall_type_descs [] = {
7280 #include "metadata/icall-def.h"
7284 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7287 #define ICALL_TYPE(id,name,first)
7290 #ifdef HAVE_ARRAY_ELEM_INIT
7291 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7292 #define MSGSTRFIELD1(line) str##line
7294 static const struct msgstrtn_t {
7295 #define ICALL(id,name,func)
7297 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7298 #include "metadata/icall-def.h"
7300 } icall_type_names_str = {
7301 #define ICALL_TYPE(id,name,first) (name),
7302 #include "metadata/icall-def.h"
7305 static const guint16 icall_type_names_idx [] = {
7306 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7307 #include "metadata/icall-def.h"
7310 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7312 static const struct msgstr_t {
7314 #define ICALL_TYPE(id,name,first)
7315 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7316 #include "metadata/icall-def.h"
7318 } icall_names_str = {
7319 #define ICALL(id,name,func) (name),
7320 #include "metadata/icall-def.h"
7323 static const guint16 icall_names_idx [] = {
7324 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7325 #include "metadata/icall-def.h"
7328 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7334 #define ICALL_TYPE(id,name,first) name,
7335 #define ICALL(id,name,func)
7336 static const char* const
7337 icall_type_names [] = {
7338 #include "metadata/icall-def.h"
7342 #define icall_type_name_get(id) (icall_type_names [(id)])
7346 #define ICALL_TYPE(id,name,first)
7347 #define ICALL(id,name,func) name,
7348 static const char* const
7350 #include "metadata/icall-def.h"
7353 #define icall_name_get(id) icall_names [(id)]
7355 #endif /* !HAVE_ARRAY_ELEM_INIT */
7359 #define ICALL_TYPE(id,name,first)
7360 #define ICALL(id,name,func) func,
7361 static const gconstpointer
7362 icall_functions [] = {
7363 #include "metadata/icall-def.h"
7367 #ifdef ENABLE_ICALL_SYMBOL_MAP
7370 #define ICALL_TYPE(id,name,first)
7371 #define ICALL(id,name,func) #func,
7372 static const gconstpointer
7373 icall_symbols [] = {
7374 #include "metadata/icall-def.h"
7379 #endif /* DISABLE_ICALL_TABLES */
7381 static mono_mutex_t icall_mutex;
7382 static GHashTable *icall_hash = NULL;
7383 static GHashTable *jit_icall_hash_name = NULL;
7384 static GHashTable *jit_icall_hash_addr = NULL;
7387 mono_icall_init (void)
7389 #ifndef DISABLE_ICALL_TABLES
7392 /* check that tables are sorted: disable in release */
7395 const char *prev_class = NULL;
7396 const char *prev_method;
7398 for (i = 0; i < Icall_type_num; ++i) {
7399 const IcallTypeDesc *desc;
7402 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7403 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7404 prev_class = icall_type_name_get (i);
7405 desc = &icall_type_descs [i];
7406 num_icalls = icall_desc_num_icalls (desc);
7407 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7408 for (j = 0; j < num_icalls; ++j) {
7409 const char *methodn = icall_name_get (desc->first_icall + j);
7410 if (prev_method && strcmp (prev_method, methodn) >= 0)
7411 g_print ("method %s should come before method %s\n", methodn, prev_method);
7412 prev_method = methodn;
7418 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7419 mono_os_mutex_init (&icall_mutex);
7423 mono_icall_lock (void)
7425 mono_locks_os_acquire (&icall_mutex, IcallLock);
7429 mono_icall_unlock (void)
7431 mono_locks_os_release (&icall_mutex, IcallLock);
7435 mono_icall_cleanup (void)
7437 g_hash_table_destroy (icall_hash);
7438 g_hash_table_destroy (jit_icall_hash_name);
7439 g_hash_table_destroy (jit_icall_hash_addr);
7440 mono_os_mutex_destroy (&icall_mutex);
7444 mono_add_internal_call (const char *name, gconstpointer method)
7448 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7450 mono_icall_unlock ();
7453 #ifndef DISABLE_ICALL_TABLES
7455 #ifdef HAVE_ARRAY_ELEM_INIT
7457 compare_method_imap (const void *key, const void *elem)
7459 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7460 return strcmp (key, method_name);
7464 find_method_icall (const IcallTypeDesc *imap, const char *name)
7466 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);
7469 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7473 compare_class_imap (const void *key, const void *elem)
7475 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7476 return strcmp (key, class_name);
7479 static const IcallTypeDesc*
7480 find_class_icalls (const char *name)
7482 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);
7485 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7488 #else /* HAVE_ARRAY_ELEM_INIT */
7491 compare_method_imap (const void *key, const void *elem)
7493 const char** method_name = (const char**)elem;
7494 return strcmp (key, *method_name);
7498 find_method_icall (const IcallTypeDesc *imap, const char *name)
7500 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7503 return (gpointer)icall_functions [(nameslot - icall_names)];
7507 compare_class_imap (const void *key, const void *elem)
7509 const char** class_name = (const char**)elem;
7510 return strcmp (key, *class_name);
7513 static const IcallTypeDesc*
7514 find_class_icalls (const char *name)
7516 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7519 return &icall_type_descs [nameslot - icall_type_names];
7522 #endif /* HAVE_ARRAY_ELEM_INIT */
7524 #endif /* DISABLE_ICALL_TABLES */
7527 * we should probably export this as an helper (handle nested types).
7528 * Returns the number of chars written in buf.
7531 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7533 int nspacelen, cnamelen;
7534 nspacelen = strlen (klass->name_space);
7535 cnamelen = strlen (klass->name);
7536 if (nspacelen + cnamelen + 2 > bufsize)
7539 memcpy (buf, klass->name_space, nspacelen);
7540 buf [nspacelen ++] = '.';
7542 memcpy (buf + nspacelen, klass->name, cnamelen);
7543 buf [nspacelen + cnamelen] = 0;
7544 return nspacelen + cnamelen;
7547 #ifdef DISABLE_ICALL_TABLES
7549 no_icall_table (void)
7551 g_assert_not_reached ();
7556 mono_lookup_internal_call (MonoMethod *method)
7561 int typelen = 0, mlen, siglen;
7563 #ifndef DISABLE_ICALL_TABLES
7564 const IcallTypeDesc *imap = NULL;
7567 g_assert (method != NULL);
7569 if (method->is_inflated)
7570 method = ((MonoMethodInflated *) method)->declaring;
7572 if (method->klass->nested_in) {
7573 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7577 mname [pos++] = '/';
7580 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7586 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7591 #ifndef DISABLE_ICALL_TABLES
7592 imap = find_class_icalls (mname);
7595 mname [typelen] = ':';
7596 mname [typelen + 1] = ':';
7598 mlen = strlen (method->name);
7599 memcpy (mname + typelen + 2, method->name, mlen);
7600 sigstart = mname + typelen + 2 + mlen;
7603 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7604 siglen = strlen (tmpsig);
7605 if (typelen + mlen + siglen + 6 > sizeof (mname))
7608 memcpy (sigstart + 1, tmpsig, siglen);
7609 sigstart [siglen + 1] = ')';
7610 sigstart [siglen + 2] = 0;
7615 res = g_hash_table_lookup (icall_hash, mname);
7617 mono_icall_unlock ();;
7620 /* try without signature */
7622 res = g_hash_table_lookup (icall_hash, mname);
7624 mono_icall_unlock ();
7628 #ifdef DISABLE_ICALL_TABLES
7629 mono_icall_unlock ();
7630 /* Fail only when the result is actually used */
7631 /* mono_marshal_get_native_wrapper () depends on this */
7632 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
7633 return ves_icall_System_String_ctor_RedirectToCreateString;
7635 return no_icall_table;
7637 /* it wasn't found in the static call tables */
7639 mono_icall_unlock ();
7642 res = find_method_icall (imap, sigstart - mlen);
7644 mono_icall_unlock ();
7647 /* try _with_ signature */
7649 res = find_method_icall (imap, sigstart - mlen);
7651 mono_icall_unlock ();
7655 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7656 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7657 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7658 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
7659 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");
7660 g_print ("If you see other errors or faults after this message they are probably related\n");
7661 g_print ("and you need to fix your mono install first.\n");
7663 mono_icall_unlock ();
7669 #ifdef ENABLE_ICALL_SYMBOL_MAP
7671 func_cmp (gconstpointer key, gconstpointer p)
7673 return (gsize)key - (gsize)*(gsize*)p;
7678 * mono_lookup_icall_symbol:
7680 * Given the icall METHOD, returns its C symbol.
7683 mono_lookup_icall_symbol (MonoMethod *m)
7685 #ifdef DISABLE_ICALL_TABLES
7686 g_assert_not_reached ();
7689 #ifdef ENABLE_ICALL_SYMBOL_MAP
7693 static gconstpointer *functions_sorted;
7694 static const char**symbols_sorted;
7695 static gboolean inited;
7700 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7701 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7702 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7703 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7704 /* Bubble sort the two arrays */
7708 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
7709 if (functions_sorted [i] > functions_sorted [i + 1]) {
7712 tmp = functions_sorted [i];
7713 functions_sorted [i] = functions_sorted [i + 1];
7714 functions_sorted [i + 1] = tmp;
7715 tmp = symbols_sorted [i];
7716 symbols_sorted [i] = symbols_sorted [i + 1];
7717 symbols_sorted [i + 1] = tmp;
7724 func = mono_lookup_internal_call (m);
7727 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
7731 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
7733 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
7734 g_assert_not_reached ();
7741 type_from_typename (char *type_name)
7743 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7745 if (!strcmp (type_name, "int"))
7746 klass = mono_defaults.int_class;
7747 else if (!strcmp (type_name, "ptr"))
7748 klass = mono_defaults.int_class;
7749 else if (!strcmp (type_name, "void"))
7750 klass = mono_defaults.void_class;
7751 else if (!strcmp (type_name, "int32"))
7752 klass = mono_defaults.int32_class;
7753 else if (!strcmp (type_name, "uint32"))
7754 klass = mono_defaults.uint32_class;
7755 else if (!strcmp (type_name, "int8"))
7756 klass = mono_defaults.sbyte_class;
7757 else if (!strcmp (type_name, "uint8"))
7758 klass = mono_defaults.byte_class;
7759 else if (!strcmp (type_name, "int16"))
7760 klass = mono_defaults.int16_class;
7761 else if (!strcmp (type_name, "uint16"))
7762 klass = mono_defaults.uint16_class;
7763 else if (!strcmp (type_name, "long"))
7764 klass = mono_defaults.int64_class;
7765 else if (!strcmp (type_name, "ulong"))
7766 klass = mono_defaults.uint64_class;
7767 else if (!strcmp (type_name, "float"))
7768 klass = mono_defaults.single_class;
7769 else if (!strcmp (type_name, "double"))
7770 klass = mono_defaults.double_class;
7771 else if (!strcmp (type_name, "object"))
7772 klass = mono_defaults.object_class;
7773 else if (!strcmp (type_name, "obj"))
7774 klass = mono_defaults.object_class;
7775 else if (!strcmp (type_name, "string"))
7776 klass = mono_defaults.string_class;
7777 else if (!strcmp (type_name, "bool"))
7778 klass = mono_defaults.boolean_class;
7779 else if (!strcmp (type_name, "boolean"))
7780 klass = mono_defaults.boolean_class;
7782 g_error ("%s", type_name);
7783 g_assert_not_reached ();
7785 return &klass->byval_arg;
7789 * LOCKING: Take the corlib image lock.
7791 MonoMethodSignature*
7792 mono_create_icall_signature (const char *sigstr)
7797 MonoMethodSignature *res, *res2;
7798 MonoImage *corlib = mono_defaults.corlib;
7800 mono_image_lock (corlib);
7801 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7802 mono_image_unlock (corlib);
7807 parts = g_strsplit (sigstr, " ", 256);
7816 res = mono_metadata_signature_alloc (corlib, len - 1);
7821 * Under windows, the default pinvoke calling convention is STDCALL but
7824 res->call_convention = MONO_CALL_C;
7827 res->ret = type_from_typename (parts [0]);
7828 for (i = 1; i < len; ++i) {
7829 res->params [i - 1] = type_from_typename (parts [i]);
7834 mono_image_lock (corlib);
7835 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7837 res = res2; /*Value is allocated in the image pool*/
7839 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
7840 mono_image_unlock (corlib);
7846 mono_find_jit_icall_by_name (const char *name)
7848 MonoJitICallInfo *info;
7849 g_assert (jit_icall_hash_name);
7852 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7853 mono_icall_unlock ();
7858 mono_find_jit_icall_by_addr (gconstpointer addr)
7860 MonoJitICallInfo *info;
7861 g_assert (jit_icall_hash_addr);
7864 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7865 mono_icall_unlock ();
7871 * mono_get_jit_icall_info:
7873 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7874 * caller should access it while holding the icall lock.
7877 mono_get_jit_icall_info (void)
7879 return jit_icall_hash_name;
7883 * mono_lookup_jit_icall_symbol:
7885 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
7888 mono_lookup_jit_icall_symbol (const char *name)
7890 MonoJitICallInfo *info;
7891 const char *res = NULL;
7894 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7896 res = info->c_symbol;
7897 mono_icall_unlock ();
7902 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7905 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7906 mono_icall_unlock ();
7910 * 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
7911 * icalls without wrappers in some cases.
7914 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
7916 MonoJitICallInfo *info;
7923 if (!jit_icall_hash_name) {
7924 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7925 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7928 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7929 g_warning ("jit icall already defined \"%s\"\n", name);
7930 g_assert_not_reached ();
7933 info = g_new0 (MonoJitICallInfo, 1);
7938 info->c_symbol = c_symbol;
7939 info->no_raise = no_raise;
7942 info->wrapper = func;
7944 info->wrapper = NULL;
7947 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7948 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7950 mono_icall_unlock ();
7955 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7957 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);