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; \
831 nEnt = (size / sizeof(guint ## n)); \
833 for (i = 0; i < nEnt; i++) { \
834 data[i] = read ## n (&src[i]); \
838 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
840 switch (type->type) {
857 memcpy (mono_array_addr (array, char, 0), field_data, size);
861 memcpy (mono_array_addr (array, char, 0), field_data, size);
866 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
868 return offsetof (MonoString, chars);
871 ICALL_EXPORT MonoObject *
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
874 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
878 MonoObject *ret = mono_object_clone_checked (obj, &error);
879 mono_error_raise_exception (&error);
886 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
891 MONO_CHECK_ARG_NULL (handle,);
893 klass = mono_class_from_mono_type (handle);
894 MONO_CHECK_ARG (handle, klass,);
896 if (klass->generic_container)
899 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
901 /* This will call the type constructor */
902 mono_runtime_class_init (vtable);
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
910 mono_image_check_for_module_cctor (image);
911 if (image->has_module_cctor) {
912 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
913 mono_error_raise_exception (&error);
914 /*It's fine to raise the exception here*/
915 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
919 ICALL_EXPORT MonoBoolean
920 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
925 /* later make this configurable and per-arch */
926 int min_size = 4096 * 4 * sizeof (void*);
927 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
928 /* if we have no info we are optimistic and assume there is enough room */
932 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
936 current = (guint8 *)&stack_addr;
937 if (current > stack_addr) {
938 if ((current - stack_addr) < min_size)
941 if (current - (stack_addr - stack_size) < min_size)
947 ICALL_EXPORT MonoObject *
948 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
951 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
952 mono_error_raise_exception (&error);
958 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
961 MonoObject **values = NULL;
964 gint32 result = (int)(gsize)mono_defaults.int32_class;
965 MonoClassField* field;
968 klass = mono_object_class (this_obj);
970 if (mono_class_num_fields (klass) == 0)
974 * Compute the starting value of the hashcode for fields of primitive
975 * types, and return the remaining fields in an array to the managed side.
976 * This way, we can avoid costly reflection operations in managed code.
979 while ((field = mono_class_get_fields (klass, &iter))) {
980 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
982 if (mono_field_is_deleted (field))
984 /* FIXME: Add more types */
985 switch (field->type->type) {
987 result ^= *(gint32*)((guint8*)this_obj + field->offset);
989 case MONO_TYPE_STRING: {
991 s = *(MonoString**)((guint8*)this_obj + field->offset);
993 result ^= mono_string_hash (s);
998 values = g_newa (MonoObject*, mono_class_num_fields (klass));
999 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1000 values [count++] = o;
1006 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1007 for (i = 0; i < count; ++i)
1008 mono_array_setref (*fields, i, values [i]);
1015 ICALL_EXPORT MonoBoolean
1016 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1019 MonoObject **values = NULL;
1021 MonoClassField* field;
1025 MONO_CHECK_ARG_NULL (that, FALSE);
1027 if (this_obj->vtable != that->vtable)
1030 klass = mono_object_class (this_obj);
1032 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1033 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1036 * Do the comparison for fields of primitive type and return a result if
1037 * possible. Otherwise, return the remaining fields in an array to the
1038 * managed side. This way, we can avoid costly reflection operations in
1043 while ((field = mono_class_get_fields (klass, &iter))) {
1044 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1046 if (mono_field_is_deleted (field))
1048 /* FIXME: Add more types */
1049 switch (field->type->type) {
1052 case MONO_TYPE_BOOLEAN:
1053 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1058 case MONO_TYPE_CHAR:
1059 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1064 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1069 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1073 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1077 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1082 case MONO_TYPE_STRING: {
1083 MonoString *s1, *s2;
1084 guint32 s1len, s2len;
1085 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1086 s2 = *(MonoString**)((guint8*)that + field->offset);
1089 if ((s1 == NULL) || (s2 == NULL))
1091 s1len = mono_string_length (s1);
1092 s2len = mono_string_length (s2);
1096 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1102 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1103 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1104 values [count++] = o;
1105 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1106 values [count++] = o;
1109 if (klass->enumtype)
1110 /* enums only have one non-static field */
1116 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1117 for (i = 0; i < count; ++i)
1118 mono_array_setref_fast (*fields, i, values [i]);
1125 ICALL_EXPORT MonoReflectionType *
1126 ves_icall_System_Object_GetType (MonoObject *obj)
1128 #ifndef DISABLE_REMOTING
1129 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1130 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1133 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1137 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1139 mtype->type = &obj->vtable->klass->byval_arg;
1140 g_assert (mtype->type->type);
1144 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1146 MONO_CHECK_ARG_NULL (obj, 0);
1148 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1152 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1153 MonoReflectionMethod *method,
1154 MonoArray *opt_param_types)
1156 MONO_CHECK_ARG_NULL (method, 0);
1158 return mono_image_create_method_token (
1159 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1163 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1165 mono_image_create_pefile (mb, file);
1169 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1171 mono_image_build_metadata (mb);
1175 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1177 mono_image_register_token (mb->dynamic_image, token, obj);
1180 ICALL_EXPORT MonoObject*
1181 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1185 mono_loader_lock ();
1186 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1187 mono_loader_unlock ();
1193 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1195 MonoMethod **dest = (MonoMethod **)data;
1197 /* skip unmanaged frames */
1213 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1215 MonoMethod **dest = (MonoMethod **)data;
1217 /* skip unmanaged frames */
1222 if (!strcmp (m->klass->name_space, "System.Reflection"))
1231 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1233 MonoMethod **dest = (MonoMethod **)data;
1235 /* skip unmanaged frames */
1239 if (m->wrapper_type != MONO_WRAPPER_NONE)
1242 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1256 static MonoReflectionType *
1257 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1259 MonoMethod *m, *dest;
1261 MonoType *type = NULL;
1262 MonoAssembly *assembly = NULL;
1263 gboolean type_resolve = FALSE;
1266 * We must compute the calling assembly as type loading must happen under a metadata context.
1267 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1268 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1270 m = mono_method_get_last_managed ();
1273 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1278 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1279 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1280 * to crash. This only seems to happen in some strange remoting
1281 * scenarios and I was unable to figure out what's happening there.
1282 * Dec 10, 2005 - Martin.
1286 assembly = dest->klass->image->assembly;
1287 type_resolve = TRUE;
1289 g_warning (G_STRLOC);
1292 if (info->assembly.name)
1293 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1297 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1298 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1301 if (!info->assembly.name && !type) /* try mscorlib */
1302 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1304 if (assembly && !type && type_resolve) {
1305 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1306 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1312 return mono_type_get_object (mono_domain_get (), type);
1316 MonoReflectionType *
1317 mono_type_get (const char *str)
1319 char *copy = g_strdup (str);
1320 MonoTypeNameParse info;
1321 MonoReflectionType *type;
1324 parsedOk = mono_reflection_parse_type(copy, &info);
1326 mono_reflection_free_type_info (&info);
1331 type = type_from_parsed_name (&info, FALSE);
1333 mono_reflection_free_type_info (&info);
1340 ICALL_EXPORT MonoReflectionType*
1341 ves_icall_type_from_name (MonoString *name,
1342 MonoBoolean throwOnError,
1343 MonoBoolean ignoreCase)
1345 char *str = mono_string_to_utf8 (name);
1346 MonoTypeNameParse info;
1347 MonoReflectionType *type;
1350 parsedOk = mono_reflection_parse_type (str, &info);
1352 /* mono_reflection_parse_type() mangles the string */
1354 mono_reflection_free_type_info (&info);
1357 mono_set_pending_exception(mono_get_exception_argument("typeName", "failed parse"));
1362 type = type_from_parsed_name (&info, ignoreCase);
1364 mono_reflection_free_type_info (&info);
1368 MonoException *e = NULL;
1371 e = mono_get_exception_type_load (name, NULL);
1373 mono_loader_clear_error ();
1375 mono_set_pending_exception (e);
1384 ICALL_EXPORT MonoReflectionType*
1385 ves_icall_type_from_handle (MonoType *handle)
1387 MonoDomain *domain = mono_domain_get ();
1389 return mono_type_get_object (domain, handle);
1392 /* System.TypeCode */
1411 TYPECODE_STRING = 18
1414 ICALL_EXPORT guint32
1415 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1417 int t = type->type->type;
1419 if (type->type->byref)
1420 return TYPECODE_OBJECT;
1424 case MONO_TYPE_VOID:
1425 return TYPECODE_OBJECT;
1426 case MONO_TYPE_BOOLEAN:
1427 return TYPECODE_BOOLEAN;
1429 return TYPECODE_BYTE;
1431 return TYPECODE_SBYTE;
1433 return TYPECODE_UINT16;
1435 return TYPECODE_INT16;
1436 case MONO_TYPE_CHAR:
1437 return TYPECODE_CHAR;
1441 return TYPECODE_OBJECT;
1443 return TYPECODE_UINT32;
1445 return TYPECODE_INT32;
1447 return TYPECODE_UINT64;
1449 return TYPECODE_INT64;
1451 return TYPECODE_SINGLE;
1453 return TYPECODE_DOUBLE;
1454 case MONO_TYPE_VALUETYPE: {
1455 MonoClass *klass = type->type->data.klass;
1457 if (klass->enumtype) {
1458 t = mono_class_enum_basetype (klass)->type;
1460 } else if (mono_is_corlib_image (klass->image)) {
1461 if (strcmp (klass->name_space, "System") == 0) {
1462 if (strcmp (klass->name, "Decimal") == 0)
1463 return TYPECODE_DECIMAL;
1464 else if (strcmp (klass->name, "DateTime") == 0)
1465 return TYPECODE_DATETIME;
1468 return TYPECODE_OBJECT;
1470 case MONO_TYPE_STRING:
1471 return TYPECODE_STRING;
1472 case MONO_TYPE_SZARRAY:
1473 case MONO_TYPE_ARRAY:
1474 case MONO_TYPE_OBJECT:
1476 case MONO_TYPE_MVAR:
1477 case MONO_TYPE_TYPEDBYREF:
1478 return TYPECODE_OBJECT;
1479 case MONO_TYPE_CLASS:
1481 MonoClass *klass = type->type->data.klass;
1482 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1483 if (strcmp (klass->name, "DBNull") == 0)
1484 return TYPECODE_DBNULL;
1487 return TYPECODE_OBJECT;
1488 case MONO_TYPE_GENERICINST:
1489 return TYPECODE_OBJECT;
1491 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1497 mono_type_is_primitive (MonoType *type)
1499 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1500 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1504 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1506 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1507 return mono_class_enum_basetype (type->data.klass);
1508 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1509 return mono_class_enum_basetype (type->data.generic_class->container_class);
1513 ICALL_EXPORT guint32
1514 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1519 g_assert (type != NULL);
1521 klass = mono_class_from_mono_type (type->type);
1522 klassc = mono_class_from_mono_type (c->type);
1524 if (type->type->byref ^ c->type->byref)
1527 if (type->type->byref) {
1528 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1529 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1531 klass = mono_class_from_mono_type (t);
1532 klassc = mono_class_from_mono_type (ot);
1534 if (mono_type_is_primitive (t)) {
1535 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1536 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1537 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1538 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1539 return t->type == ot->type;
1541 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1544 if (klass->valuetype)
1545 return klass == klassc;
1546 return klass->valuetype == klassc->valuetype;
1549 return mono_class_is_assignable_from (klass, klassc);
1552 ICALL_EXPORT guint32
1553 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1555 MonoClass *klass = mono_class_from_mono_type (type->type);
1556 mono_class_init_or_throw (klass);
1557 return mono_object_isinst (obj, klass) != NULL;
1560 ICALL_EXPORT guint32
1561 ves_icall_get_attributes (MonoReflectionType *type)
1563 MonoClass *klass = mono_class_from_mono_type (type->type);
1564 return klass->flags;
1567 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1568 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1570 MonoClass *klass = field->field->parent;
1571 MonoMarshalType *info;
1575 if (klass->generic_container ||
1576 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1579 ftype = mono_field_get_type (field->field);
1580 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1583 info = mono_marshal_load_type_info (klass);
1585 for (i = 0; i < info->num_fields; ++i) {
1586 if (info->fields [i].field == field->field) {
1587 if (!info->fields [i].mspec)
1590 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1597 ICALL_EXPORT MonoReflectionField*
1598 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1600 gboolean found = FALSE;
1607 klass = handle->parent;
1609 klass = mono_class_from_mono_type (type);
1611 /* Check that the field belongs to the class */
1612 for (k = klass; k; k = k->parent) {
1613 if (k == handle->parent) {
1620 /* The managed code will throw the exception */
1624 return mono_field_get_object (mono_domain_get (), klass, handle);
1627 ICALL_EXPORT MonoArray*
1628 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1631 MonoType *type = mono_field_get_type_checked (field->field, &error);
1632 mono_error_raise_exception (&error);
1634 return type_array_from_modifiers (field->field->parent->image, type, optional);
1638 vell_icall_get_method_attributes (MonoMethod *method)
1640 return method->flags;
1644 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1647 MonoDomain *domain = mono_domain_get ();
1648 MonoMethodSignature* sig;
1650 sig = mono_method_signature_checked (method, &error);
1651 if (!mono_error_ok (&error))
1652 mono_error_raise_exception (&error);
1655 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1656 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1657 info->attrs = method->flags;
1658 info->implattrs = method->iflags;
1659 if (sig->call_convention == MONO_CALL_DEFAULT)
1660 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1662 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1667 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1670 ICALL_EXPORT MonoArray*
1671 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1673 MonoDomain *domain = mono_domain_get ();
1675 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1678 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1679 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1681 MonoDomain *domain = mono_domain_get ();
1682 MonoReflectionMarshalAsAttribute* res = NULL;
1683 MonoMarshalSpec **mspecs;
1686 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1687 mono_method_get_marshal_info (method, mspecs);
1690 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1692 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1694 mono_metadata_free_marshal_spec (mspecs [i]);
1701 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1703 MonoClass *parent = field->field->parent;
1704 if (!parent->size_inited)
1705 mono_class_init (parent);
1706 mono_class_setup_fields_locking (parent);
1708 return field->field->offset - sizeof (MonoObject);
1711 ICALL_EXPORT MonoReflectionType*
1712 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1716 parent = declaring? field->field->parent: field->klass;
1718 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1721 ICALL_EXPORT MonoObject *
1722 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1724 MonoClass *fklass = field->klass;
1725 MonoClassField *cf = field->field;
1726 MonoDomain *domain = mono_object_domain (field);
1728 if (fklass->image->assembly->ref_only) {
1729 mono_set_pending_exception (mono_get_exception_invalid_operation (
1730 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1734 if (mono_security_core_clr_enabled ())
1735 mono_security_core_clr_ensure_reflection_access_field (cf);
1737 return mono_field_get_value_object (domain, cf, obj);
1741 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1744 MonoClassField *cf = field->field;
1748 if (field->klass->image->assembly->ref_only) {
1749 mono_set_pending_exception (mono_get_exception_invalid_operation (
1750 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1754 if (mono_security_core_clr_enabled ())
1755 mono_security_core_clr_ensure_reflection_access_field (cf);
1757 type = mono_field_get_type_checked (cf, &error);
1758 if (!mono_error_ok (&error))
1759 mono_error_raise_exception (&error);
1761 v = (gchar *) value;
1763 switch (type->type) {
1766 case MONO_TYPE_BOOLEAN:
1769 case MONO_TYPE_CHAR:
1778 case MONO_TYPE_VALUETYPE:
1781 v += sizeof (MonoObject);
1783 case MONO_TYPE_STRING:
1784 case MONO_TYPE_OBJECT:
1785 case MONO_TYPE_CLASS:
1786 case MONO_TYPE_ARRAY:
1787 case MONO_TYPE_SZARRAY:
1790 case MONO_TYPE_GENERICINST: {
1791 MonoGenericClass *gclass = type->data.generic_class;
1792 g_assert (!gclass->context.class_inst->is_open);
1794 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1795 MonoClass *nklass = mono_class_from_mono_type (type);
1796 MonoObject *nullable;
1799 * Convert the boxed vtype into a Nullable structure.
1800 * This is complicated by the fact that Nullables have
1801 * a variable structure.
1803 nullable = mono_object_new (mono_domain_get (), nklass);
1805 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1807 v = (gchar *)mono_object_unbox (nullable);
1810 if (gclass->container_class->valuetype && (v != NULL))
1811 v += sizeof (MonoObject);
1815 g_error ("type 0x%x not handled in "
1816 "ves_icall_FieldInfo_SetValueInternal", type->type);
1821 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1822 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1823 if (!vtable->initialized)
1824 mono_runtime_class_init (vtable);
1825 mono_field_static_set_value (vtable, cf, v);
1827 mono_field_set_value (obj, cf, v);
1832 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1841 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1842 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1846 if (MONO_TYPE_IS_REFERENCE (f->type))
1847 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1849 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1852 ICALL_EXPORT MonoObject *
1853 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1855 MonoObject *o = NULL;
1856 MonoClassField *field = rfield->field;
1858 MonoDomain *domain = mono_object_domain (rfield);
1860 MonoTypeEnum def_type;
1861 const char *def_value;
1865 mono_class_init (field->parent);
1867 t = mono_field_get_type_checked (field, &error);
1868 if (!mono_error_ok (&error))
1869 mono_error_raise_exception (&error);
1871 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1872 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1876 if (image_is_dynamic (field->parent->image)) {
1877 MonoClass *klass = field->parent;
1878 int fidx = field - klass->fields;
1880 g_assert (fidx >= 0 && fidx < klass->field.count);
1881 g_assert (klass->ext);
1882 g_assert (klass->ext->field_def_values);
1883 def_type = klass->ext->field_def_values [fidx].def_type;
1884 def_value = klass->ext->field_def_values [fidx].data;
1885 if (def_type == MONO_TYPE_END) {
1886 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1890 def_value = mono_class_get_field_default_value (field, &def_type);
1891 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1893 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1898 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1902 case MONO_TYPE_BOOLEAN:
1905 case MONO_TYPE_CHAR:
1913 case MONO_TYPE_R8: {
1916 /* boxed value type */
1917 t = g_new0 (MonoType, 1);
1919 klass = mono_class_from_mono_type (t);
1921 o = mono_object_new (domain, klass);
1922 v = ((gchar *) o) + sizeof (MonoObject);
1923 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1926 case MONO_TYPE_STRING:
1927 case MONO_TYPE_CLASS:
1928 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1931 g_assert_not_reached ();
1937 ICALL_EXPORT MonoReflectionType*
1938 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1941 MonoClassField *field = ref_field->field;
1942 MonoType *type = mono_field_get_type_checked (field, &error);
1943 if (!mono_error_ok (&error))
1944 mono_error_raise_exception (&error);
1945 return mono_type_get_object (mono_object_domain (ref_field), type);
1948 /* From MonoProperty.cs */
1950 PInfo_Attributes = 1,
1951 PInfo_GetMethod = 1 << 1,
1952 PInfo_SetMethod = 1 << 2,
1953 PInfo_ReflectedType = 1 << 3,
1954 PInfo_DeclaringType = 1 << 4,
1959 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1961 MonoDomain *domain = mono_object_domain (property);
1962 const MonoProperty *pproperty = property->property;
1964 if ((req_info & PInfo_ReflectedType) != 0)
1965 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1966 if ((req_info & PInfo_DeclaringType) != 0)
1967 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &pproperty->parent->byval_arg));
1969 if ((req_info & PInfo_Name) != 0)
1970 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
1972 if ((req_info & PInfo_Attributes) != 0)
1973 info->attrs = pproperty->attrs;
1975 if ((req_info & PInfo_GetMethod) != 0)
1976 MONO_STRUCT_SETREF (info, get, pproperty->get &&
1977 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->get->klass == property->klass) ?
1978 mono_method_get_object (domain, pproperty->get, property->klass): NULL);
1979 if ((req_info & PInfo_SetMethod) != 0)
1980 MONO_STRUCT_SETREF (info, set, pproperty->set &&
1981 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->set->klass == property->klass) ?
1982 mono_method_get_object (domain, pproperty->set, property->klass): NULL);
1984 * There may be other methods defined for properties, though, it seems they are not exposed
1985 * in the reflection API
1990 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1992 MonoDomain *domain = mono_object_domain (event);
1994 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1995 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1997 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1998 info->attrs = event->event->attrs;
1999 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2000 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2001 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2003 #ifndef MONO_SMALL_CONFIG
2004 if (event->event->other) {
2006 while (event->event->other [n])
2008 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2010 for (i = 0; i < n; i++)
2011 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2017 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2022 mono_class_setup_interfaces (klass, error);
2023 if (!mono_error_ok (error))
2026 for (i = 0; i < klass->interface_count; i++) {
2027 ic = klass->interfaces [i];
2028 g_hash_table_insert (ifaces, ic, ic);
2030 collect_interfaces (ic, ifaces, error);
2031 if (!mono_error_ok (error))
2037 MonoArray *iface_array;
2038 MonoGenericContext *context;
2042 } FillIfaceArrayData;
2045 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2047 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2048 MonoClass *ic = (MonoClass *)key;
2049 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2051 if (!mono_error_ok (data->error))
2054 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2055 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2056 if (!mono_error_ok (data->error))
2060 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2063 mono_metadata_free_type (inflated);
2067 get_interfaces_hash (gconstpointer v1)
2069 MonoClass *k = (MonoClass*)v1;
2071 return k->type_token;
2074 ICALL_EXPORT MonoArray*
2075 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2078 MonoClass *klass = mono_class_from_mono_type (type->type);
2080 FillIfaceArrayData data = { 0 };
2083 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2085 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2086 data.context = mono_class_get_context (klass);
2087 klass = klass->generic_class->container_class;
2090 for (parent = klass; parent; parent = parent->parent) {
2091 mono_class_setup_interfaces (parent, &error);
2092 if (!mono_error_ok (&error))
2094 collect_interfaces (parent, iface_hash, &error);
2095 if (!mono_error_ok (&error))
2099 data.error = &error;
2100 data.domain = mono_object_domain (type);
2102 len = g_hash_table_size (iface_hash);
2104 g_hash_table_destroy (iface_hash);
2105 if (!data.domain->empty_types)
2106 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2107 return data.domain->empty_types;
2110 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2111 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2112 if (!mono_error_ok (&error))
2115 g_hash_table_destroy (iface_hash);
2116 return data.iface_array;
2119 g_hash_table_destroy (iface_hash);
2120 mono_error_raise_exception (&error);
2125 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2127 gboolean variance_used;
2128 MonoClass *klass = mono_class_from_mono_type (type->type);
2129 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2130 MonoReflectionMethod *member;
2133 int i = 0, len, ioffset;
2136 mono_class_init_or_throw (klass);
2137 mono_class_init_or_throw (iclass);
2139 mono_class_setup_vtable (klass);
2141 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2145 len = mono_class_num_methods (iclass);
2146 domain = mono_object_domain (type);
2147 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2148 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2150 while ((method = mono_class_get_methods (iclass, &iter))) {
2151 member = mono_method_get_object (domain, method, iclass);
2152 mono_array_setref (*methods, i, member);
2153 member = mono_method_get_object (domain, klass->vtable [i + ioffset], klass);
2154 mono_array_setref (*targets, i, member);
2161 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2163 MonoClass *klass = mono_class_from_mono_type (type->type);
2164 mono_class_init_or_throw (klass);
2166 if (image_is_dynamic (klass->image)) {
2167 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2168 *packing = tb->packing_size;
2169 *size = tb->class_size;
2171 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2175 ICALL_EXPORT MonoReflectionType*
2176 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2180 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2181 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2183 klass = mono_class_from_mono_type (type->type);
2184 mono_class_init_or_throw (klass);
2186 // GetElementType should only return a type for:
2187 // Array Pointer PassedByRef
2188 if (type->type->byref)
2189 return mono_type_get_object (mono_object_domain (type), &klass->byval_arg);
2190 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2191 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2192 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2193 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2198 ICALL_EXPORT MonoReflectionType*
2199 ves_icall_get_type_parent (MonoReflectionType *type)
2201 if (type->type->byref)
2204 MonoClass *klass = mono_class_from_mono_type (type->type);
2205 return klass->parent ? mono_type_get_object (mono_object_domain (type), &klass->parent->byval_arg): NULL;
2208 ICALL_EXPORT MonoBoolean
2209 ves_icall_type_ispointer (MonoReflectionType *type)
2211 return type->type->type == MONO_TYPE_PTR;
2214 ICALL_EXPORT MonoBoolean
2215 ves_icall_type_isprimitive (MonoReflectionType *type)
2217 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)));
2220 ICALL_EXPORT MonoBoolean
2221 ves_icall_type_isbyref (MonoReflectionType *type)
2223 return type->type->byref;
2226 ICALL_EXPORT MonoBoolean
2227 ves_icall_type_iscomobject (MonoReflectionType *type)
2229 MonoClass *klass = mono_class_from_mono_type (type->type);
2230 mono_class_init_or_throw (klass);
2232 return mono_class_is_com_object (klass);
2235 ICALL_EXPORT MonoReflectionModule*
2236 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2238 MonoClass *klass = mono_class_from_mono_type (type->type);
2239 return mono_module_get_object (mono_object_domain (type), klass->image);
2242 ICALL_EXPORT MonoReflectionAssembly*
2243 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2245 MonoDomain *domain = mono_domain_get ();
2246 MonoClass *klass = mono_class_from_mono_type (type->type);
2247 return mono_assembly_get_object (domain, klass->image->assembly);
2250 ICALL_EXPORT MonoReflectionType*
2251 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2253 MonoDomain *domain = mono_domain_get ();
2256 if (type->type->byref)
2258 if (type->type->type == MONO_TYPE_VAR) {
2259 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2260 klass = param ? param->owner.klass : NULL;
2261 } else if (type->type->type == MONO_TYPE_MVAR) {
2262 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2263 klass = param ? param->owner.method->klass : NULL;
2265 klass = mono_class_from_mono_type (type->type)->nested_in;
2268 return klass ? mono_type_get_object (domain, &klass->byval_arg) : NULL;
2271 ICALL_EXPORT MonoString*
2272 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2274 MonoDomain *domain = mono_domain_get ();
2275 MonoClass *klass = mono_class_from_mono_type (type->type);
2277 if (type->type->byref) {
2278 char *n = g_strdup_printf ("%s&", klass->name);
2279 MonoString *res = mono_string_new (domain, n);
2285 return mono_string_new (domain, klass->name);
2289 ICALL_EXPORT MonoString*
2290 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2292 MonoDomain *domain = mono_domain_get ();
2293 MonoClass *klass = mono_class_from_mono_type (type->type);
2295 while (klass->nested_in)
2296 klass = klass->nested_in;
2298 if (klass->name_space [0] == '\0')
2301 return mono_string_new (domain, klass->name_space);
2305 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2309 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2310 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2314 klass = mono_class_from_mono_type (type->type);
2320 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2323 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2327 ICALL_EXPORT MonoArray*
2328 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2331 MonoClass *klass, *pklass;
2332 MonoDomain *domain = mono_object_domain (type);
2335 klass = mono_class_from_mono_type (type->type);
2337 if (klass->generic_container) {
2338 MonoGenericContainer *container = klass->generic_container;
2339 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2340 for (i = 0; i < container->type_argc; ++i) {
2341 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2342 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2344 } else if (klass->generic_class) {
2345 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2346 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2347 for (i = 0; i < inst->type_argc; ++i)
2348 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2355 ICALL_EXPORT gboolean
2356 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2360 if (!IS_MONOTYPE (type))
2363 if (type->type->byref)
2366 klass = mono_class_from_mono_type (type->type);
2367 return klass->generic_container != NULL;
2370 ICALL_EXPORT MonoReflectionType*
2371 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2375 if (type->type->byref)
2378 klass = mono_class_from_mono_type (type->type);
2380 if (klass->generic_container) {
2381 return type; /* check this one */
2383 if (klass->generic_class) {
2384 MonoClass *generic_class = klass->generic_class->container_class;
2387 tb = mono_class_get_ref_info (generic_class);
2389 if (generic_class->wastypebuilder && tb)
2390 return (MonoReflectionType *)tb;
2392 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2397 ICALL_EXPORT MonoReflectionType*
2398 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2401 MonoType *geninst, **types;
2404 g_assert (IS_MONOTYPE (type));
2405 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2407 count = mono_array_length (type_array);
2408 types = g_new0 (MonoType *, count);
2410 for (i = 0; i < count; i++) {
2411 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2412 types [i] = t->type;
2415 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2420 klass = mono_class_from_mono_type (geninst);
2422 /*we might inflate to the GTD*/
2423 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2424 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2428 return mono_type_get_object (mono_object_domain (type), geninst);
2431 ICALL_EXPORT gboolean
2432 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2436 if (!IS_MONOTYPE (type))
2439 if (type->type->byref)
2442 klass = mono_class_from_mono_type (type->type);
2443 return klass->generic_class != NULL || klass->generic_container != NULL;
2447 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2449 if (!IS_MONOTYPE (type))
2452 if (is_generic_parameter (type->type))
2453 return mono_type_get_generic_param_num (type->type);
2457 ICALL_EXPORT GenericParameterAttributes
2458 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2460 g_assert (IS_MONOTYPE (type));
2461 g_assert (is_generic_parameter (type->type));
2462 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2465 ICALL_EXPORT MonoArray *
2466 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2468 MonoGenericParamInfo *param_info;
2474 g_assert (IS_MONOTYPE (type));
2476 domain = mono_object_domain (type);
2477 param_info = mono_generic_param_info (type->type->data.generic_param);
2478 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2481 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2482 for (i = 0; i < count; i++)
2483 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2489 ICALL_EXPORT MonoBoolean
2490 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2492 return is_generic_parameter (type->type);
2495 ICALL_EXPORT MonoBoolean
2496 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2498 return is_generic_parameter (tb->type.type);
2502 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2503 MonoReflectionType *t)
2505 enumtype->type = t->type;
2508 ICALL_EXPORT MonoReflectionMethod*
2509 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2510 MonoReflectionMethod* generic)
2517 domain = ((MonoObject *)type)->vtable->domain;
2519 klass = mono_class_from_mono_type (type->type);
2520 mono_class_init_or_throw (klass);
2523 while ((method = mono_class_get_methods (klass, &iter))) {
2524 if (method->token == generic->method->token)
2525 return mono_method_get_object (domain, method, klass);
2531 ICALL_EXPORT MonoReflectionMethod *
2532 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2535 MonoType *type = ref_type->type;
2537 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2538 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2541 if (type->type == MONO_TYPE_VAR)
2544 method = mono_type_get_generic_param_owner (type)->owner.method;
2546 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2549 ICALL_EXPORT MonoBoolean
2550 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2552 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2556 ICALL_EXPORT MonoBoolean
2557 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2559 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2564 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2566 MonoDomain *domain = mono_domain_get ();
2567 MonoImage *image = method->method->klass->image;
2568 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2569 MonoTableInfo *tables = image->tables;
2570 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2571 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2572 guint32 im_cols [MONO_IMPLMAP_SIZE];
2573 guint32 scope_token;
2574 const char *import = NULL;
2575 const char *scope = NULL;
2577 if (image_is_dynamic (image)) {
2578 MonoReflectionMethodAux *method_aux =
2579 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2581 import = method_aux->dllentry;
2582 scope = method_aux->dll;
2585 if (!import || !scope) {
2586 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2591 if (piinfo->implmap_idx) {
2592 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2594 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2595 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2596 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2597 scope = mono_metadata_string_heap (image, scope_token);
2601 *flags = piinfo->piflags;
2602 *entry_point = mono_string_new (domain, import);
2603 *dll_name = mono_string_new (domain, scope);
2606 ICALL_EXPORT MonoReflectionMethod *
2607 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2609 MonoMethodInflated *imethod;
2612 if (method->method->is_generic)
2615 if (!method->method->is_inflated)
2618 imethod = (MonoMethodInflated *) method->method;
2620 result = imethod->declaring;
2621 /* Not a generic method. */
2622 if (!result->is_generic)
2625 if (image_is_dynamic (method->method->klass->image)) {
2626 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2627 MonoReflectionMethod *res;
2630 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2631 * the dynamic case as well ?
2633 mono_image_lock ((MonoImage*)image);
2634 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2635 mono_image_unlock ((MonoImage*)image);
2641 if (imethod->context.class_inst) {
2642 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2643 /*Generic methods gets the context of the GTD.*/
2644 if (mono_class_get_context (klass)) {
2646 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2647 mono_error_raise_exception (&error);
2651 return mono_method_get_object (mono_object_domain (method), result, NULL);
2654 ICALL_EXPORT gboolean
2655 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2657 return mono_method_signature (method->method)->generic_param_count != 0;
2660 ICALL_EXPORT gboolean
2661 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2663 return method->method->is_generic;
2666 ICALL_EXPORT MonoArray*
2667 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2673 domain = mono_object_domain (method);
2675 if (method->method->is_inflated) {
2676 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2679 count = inst->type_argc;
2680 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2682 for (i = 0; i < count; i++)
2683 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2689 count = mono_method_signature (method->method)->generic_param_count;
2690 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2692 for (i = 0; i < count; i++) {
2693 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2694 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2695 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2696 mono_array_setref (res, i,
2697 mono_type_get_object (domain, &pklass->byval_arg));
2703 ICALL_EXPORT MonoObject *
2704 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2708 * Invoke from reflection is supposed to always be a virtual call (the API
2709 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2710 * greater flexibility.
2712 MonoMethod *m = method->method;
2713 MonoMethodSignature *sig = mono_method_signature (m);
2716 void *obj = this_arg;
2720 if (mono_security_core_clr_enabled ())
2721 mono_security_core_clr_ensure_reflection_access_method (m);
2723 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2724 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2725 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2730 if (!mono_object_isinst (this_arg, m->klass)) {
2731 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2732 char *target_name = mono_type_get_full_name (m->klass);
2733 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2734 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2736 g_free (target_name);
2740 m = mono_object_get_virtual_method (this_arg, m);
2741 /* must pass the pointer to the value for valuetype methods */
2742 if (m->klass->valuetype)
2743 obj = mono_object_unbox (this_arg);
2744 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2745 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2750 if (sig->ret->byref) {
2751 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"));
2755 pcount = params? mono_array_length (params): 0;
2756 if (pcount != sig->param_count) {
2757 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2761 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2762 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."));
2766 image = m->klass->image;
2767 if (image->assembly->ref_only) {
2768 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."));
2772 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2773 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2777 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2781 intptr_t *lower_bounds;
2782 pcount = mono_array_length (params);
2783 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
2784 /* Note: the synthetized array .ctors have int32 as argument type */
2785 for (i = 0; i < pcount; ++i)
2786 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2788 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2789 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2790 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
2791 mono_error_raise_exception (&error);
2793 for (i = 0; i < mono_array_length (arr); ++i) {
2794 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
2795 mono_error_raise_exception (&error);
2797 mono_array_setref_fast (arr, i, subarray);
2799 return (MonoObject*)arr;
2802 if (m->klass->rank == pcount) {
2803 /* Only lengths provided. */
2804 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
2805 mono_error_raise_exception (&error);
2807 return (MonoObject*)arr;
2809 g_assert (pcount == (m->klass->rank * 2));
2810 /* The arguments are lower-bound-length pairs */
2811 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
2813 for (i = 0; i < pcount / 2; ++i) {
2814 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
2815 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
2818 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
2819 mono_error_raise_exception (&error);
2821 return (MonoObject*)arr;
2824 return mono_runtime_invoke_array (m, obj, params, NULL);
2827 #ifndef DISABLE_REMOTING
2828 ICALL_EXPORT MonoObject *
2829 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
2831 MonoDomain *domain = mono_object_domain (method);
2832 MonoMethod *m = method->method;
2833 MonoMethodSignature *sig = mono_method_signature (m);
2834 MonoArray *out_args;
2836 int i, j, outarg_count = 0;
2838 if (m->klass == mono_defaults.object_class) {
2839 if (!strcmp (m->name, "FieldGetter")) {
2840 MonoClass *k = this_arg->vtable->klass;
2844 /* If this is a proxy, then it must be a CBO */
2845 if (k == mono_defaults.transparent_proxy_class) {
2846 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2847 this_arg = tp->rp->unwrapped_server;
2848 g_assert (this_arg);
2849 k = this_arg->vtable->klass;
2852 name = mono_array_get (params, MonoString *, 1);
2853 str = mono_string_to_utf8 (name);
2856 MonoClassField* field = mono_class_get_field_from_name (k, str);
2858 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2859 if (field_klass->valuetype)
2860 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
2862 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
2864 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2865 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2866 mono_array_setref (out_args, 0, result);
2874 g_assert_not_reached ();
2876 } else if (!strcmp (m->name, "FieldSetter")) {
2877 MonoClass *k = this_arg->vtable->klass;
2883 /* If this is a proxy, then it must be a CBO */
2884 if (k == mono_defaults.transparent_proxy_class) {
2885 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2886 this_arg = tp->rp->unwrapped_server;
2887 g_assert (this_arg);
2888 k = this_arg->vtable->klass;
2891 name = mono_array_get (params, MonoString *, 1);
2892 str = mono_string_to_utf8 (name);
2895 MonoClassField* field = mono_class_get_field_from_name (k, str);
2897 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2898 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
2900 if (field_klass->valuetype) {
2901 size = mono_type_size (field->type, &align);
2902 g_assert (size == mono_class_value_size (field_klass, NULL));
2903 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2905 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
2908 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2909 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2919 g_assert_not_reached ();
2924 for (i = 0; i < mono_array_length (params); i++) {
2925 if (sig->params [i]->byref)
2929 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2931 /* handle constructors only for objects already allocated */
2932 if (!strcmp (method->method->name, ".ctor"))
2933 g_assert (this_arg);
2935 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2936 g_assert (!method->method->klass->valuetype);
2937 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
2939 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2940 if (sig->params [i]->byref) {
2942 arg = mono_array_get (params, gpointer, i);
2943 mono_array_setref (out_args, j, arg);
2948 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2955 read_enum_value (const char *mem, int type)
2958 case MONO_TYPE_BOOLEAN:
2960 return *(guint8*)mem;
2962 return *(gint8*)mem;
2963 case MONO_TYPE_CHAR:
2965 return read16 (mem);
2967 return (gint16) read16 (mem);
2969 return read32 (mem);
2971 return (gint32) read32 (mem);
2974 return read64 (mem);
2976 g_assert_not_reached ();
2982 write_enum_value (char *mem, int type, guint64 value)
2986 case MONO_TYPE_I1: {
2987 guint8 *p = (guint8*)mem;
2992 case MONO_TYPE_I2: {
2993 guint16 *p = (guint16 *)mem;
2998 case MONO_TYPE_I4: {
2999 guint32 *p = (guint32 *)mem;
3004 case MONO_TYPE_I8: {
3005 guint64 *p = (guint64 *)mem;
3010 g_assert_not_reached ();
3015 ICALL_EXPORT MonoObject *
3016 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3023 domain = mono_object_domain (enumType);
3024 enumc = mono_class_from_mono_type (enumType->type);
3026 mono_class_init_or_throw (enumc);
3028 etype = mono_class_enum_basetype (enumc);
3030 res = mono_object_new (domain, enumc);
3031 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3036 ICALL_EXPORT MonoBoolean
3037 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3039 int size = mono_class_value_size (a->vtable->klass, NULL);
3040 guint64 a_val = 0, b_val = 0;
3042 memcpy (&a_val, mono_object_unbox (a), size);
3043 memcpy (&b_val, mono_object_unbox (b), size);
3045 return (a_val & b_val) == b_val;
3048 ICALL_EXPORT MonoObject *
3049 ves_icall_System_Enum_get_value (MonoObject *eobj)
3060 g_assert (eobj->vtable->klass->enumtype);
3062 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3063 res = mono_object_new (mono_object_domain (eobj), enumc);
3064 dst = (char *)res + sizeof (MonoObject);
3065 src = (char *)eobj + sizeof (MonoObject);
3066 size = mono_class_value_size (enumc, NULL);
3068 memcpy (dst, src, size);
3073 ICALL_EXPORT MonoReflectionType *
3074 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3079 klass = mono_class_from_mono_type (type->type);
3080 mono_class_init_or_throw (klass);
3082 etype = mono_class_enum_basetype (klass);
3084 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3088 return mono_type_get_object (mono_object_domain (type), etype);
3092 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3094 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3095 gpointer odata = (char *)other + sizeof (MonoObject);
3096 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3097 g_assert (basetype);
3102 if (eobj->vtable->klass != other->vtable->klass)
3105 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3106 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3107 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3110 return me > other ? 1 : -1; \
3113 switch (basetype->type) {
3115 COMPARE_ENUM_VALUES (guint8);
3117 COMPARE_ENUM_VALUES (gint8);
3118 case MONO_TYPE_CHAR:
3120 COMPARE_ENUM_VALUES (guint16);
3122 COMPARE_ENUM_VALUES (gint16);
3124 COMPARE_ENUM_VALUES (guint32);
3126 COMPARE_ENUM_VALUES (gint32);
3128 COMPARE_ENUM_VALUES (guint64);
3130 COMPARE_ENUM_VALUES (gint64);
3134 #undef COMPARE_ENUM_VALUES
3135 /* indicates that the enum was of an unsupported unerlying type */
3140 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3142 gpointer data = (char *)eobj + sizeof (MonoObject);
3143 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3144 g_assert (basetype);
3146 switch (basetype->type) {
3147 case MONO_TYPE_I1: {
3148 gint8 value = *((gint8*)data);
3149 return ((int)value ^ (int)value << 8);
3152 return *((guint8*)data);
3153 case MONO_TYPE_CHAR:
3155 return *((guint16*)data);
3157 case MONO_TYPE_I2: {
3158 gint16 value = *((gint16*)data);
3159 return ((int)(guint16)value | (((int)value) << 16));
3162 return *((guint32*)data);
3164 return *((gint32*)data);
3166 case MONO_TYPE_I8: {
3167 gint64 value = *((gint64*)data);
3168 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3171 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3176 ICALL_EXPORT MonoBoolean
3177 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3179 MonoDomain *domain = mono_object_domain (type);
3180 MonoClass *enumc = mono_class_from_mono_type (type->type);
3181 guint j = 0, nvalues;
3183 MonoClassField *field;
3185 guint64 field_value, previous_value = 0;
3186 gboolean sorted = TRUE;
3188 mono_class_init_or_throw (enumc);
3190 if (!enumc->enumtype) {
3191 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3195 base_type = mono_class_enum_basetype (enumc)->type;
3197 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3198 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3199 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3202 while ((field = mono_class_get_fields (enumc, &iter))) {
3204 MonoTypeEnum def_type;
3206 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3208 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3210 if (mono_field_is_deleted (field))
3212 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3214 p = mono_class_get_field_default_value (field, &def_type);
3215 /* len = */ mono_metadata_decode_blob_size (p, &p);
3217 field_value = read_enum_value (p, base_type);
3218 mono_array_set (*values, guint64, j, field_value);
3220 if (previous_value > field_value)
3223 previous_value = field_value;
3231 BFLAGS_IgnoreCase = 1,
3232 BFLAGS_DeclaredOnly = 2,
3233 BFLAGS_Instance = 4,
3235 BFLAGS_Public = 0x10,
3236 BFLAGS_NonPublic = 0x20,
3237 BFLAGS_FlattenHierarchy = 0x40,
3238 BFLAGS_InvokeMethod = 0x100,
3239 BFLAGS_CreateInstance = 0x200,
3240 BFLAGS_GetField = 0x400,
3241 BFLAGS_SetField = 0x800,
3242 BFLAGS_GetProperty = 0x1000,
3243 BFLAGS_SetProperty = 0x2000,
3244 BFLAGS_ExactBinding = 0x10000,
3245 BFLAGS_SuppressChangeType = 0x20000,
3246 BFLAGS_OptionalParamBinding = 0x40000
3249 ICALL_EXPORT MonoArray*
3250 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3253 MonoClass *startklass, *klass, *refklass;
3258 char *utf8_name = NULL;
3259 int (*compare_func) (const char *s1, const char *s2) = NULL;
3260 MonoClassField *field;
3261 MonoPtrArray tmp_array;
3263 domain = ((MonoObject *)type)->vtable->domain;
3264 if (type->type->byref)
3265 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3267 klass = startklass = mono_class_from_mono_type (type->type);
3268 refklass = mono_class_from_mono_type (reftype->type);
3270 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3273 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3274 mono_ptr_array_destroy (tmp_array);
3275 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3280 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3281 guint32 flags = mono_field_get_flags (field);
3283 if (mono_field_is_deleted_with_flags (field, flags))
3285 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3286 if (bflags & BFLAGS_Public)
3288 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3289 if (bflags & BFLAGS_NonPublic) {
3296 if (flags & FIELD_ATTRIBUTE_STATIC) {
3297 if (bflags & BFLAGS_Static)
3298 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3301 if (bflags & BFLAGS_Instance)
3309 if (utf8_name == NULL) {
3310 utf8_name = mono_string_to_utf8 (name);
3311 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3314 if (compare_func (mono_field_get_name (field), utf8_name))
3318 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3319 mono_ptr_array_append (tmp_array, member);
3321 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3324 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3326 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3327 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3329 mono_ptr_array_destroy (tmp_array);
3331 if (utf8_name != NULL)
3338 method_nonpublic (MonoMethod* method, gboolean start_klass)
3340 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3341 case METHOD_ATTRIBUTE_ASSEM:
3342 return (start_klass || mono_defaults.generic_ilist_class);
3343 case METHOD_ATTRIBUTE_PRIVATE:
3345 case METHOD_ATTRIBUTE_PUBLIC:
3353 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3356 MonoClass *startklass;
3360 /*FIXME, use MonoBitSet*/
3361 guint32 method_slots_default [8];
3362 guint32 *method_slots = NULL;
3363 int (*compare_func) (const char *s1, const char *s2) = NULL;
3365 array = g_ptr_array_new ();
3370 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3372 /* An optimization for calls made from Delegate:CreateDelegate () */
3373 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3374 method = mono_get_delegate_invoke (klass);
3375 if (mono_loader_get_last_error ())
3378 g_ptr_array_add (array, method);
3382 mono_class_setup_methods (klass);
3383 mono_class_setup_vtable (klass);
3384 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3387 if (is_generic_parameter (&klass->byval_arg))
3388 nslots = mono_class_get_vtable_size (klass->parent);
3390 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3391 if (nslots >= sizeof (method_slots_default) * 8) {
3392 method_slots = g_new0 (guint32, nslots / 32 + 1);
3394 method_slots = method_slots_default;
3395 memset (method_slots, 0, sizeof (method_slots_default));
3398 mono_class_setup_methods (klass);
3399 mono_class_setup_vtable (klass);
3400 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3404 while ((method = mono_class_get_methods (klass, &iter))) {
3406 if (method->slot != -1) {
3407 g_assert (method->slot < nslots);
3408 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3410 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3411 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3414 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3416 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3417 if (bflags & BFLAGS_Public)
3419 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3425 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3426 if (bflags & BFLAGS_Static)
3427 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3430 if (bflags & BFLAGS_Instance)
3438 if (compare_func (name, method->name))
3443 g_ptr_array_add (array, method);
3445 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3447 if (method_slots != method_slots_default)
3448 g_free (method_slots);
3453 if (method_slots != method_slots_default)
3454 g_free (method_slots);
3455 g_ptr_array_free (array, TRUE);
3457 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3458 *ex = mono_class_get_exception_for_failure (klass);
3460 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3461 mono_loader_clear_error ();
3466 ICALL_EXPORT MonoArray*
3467 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3469 static MonoClass *MethodInfo_array;
3472 MonoVTable *array_vtable;
3473 MonoException *ex = NULL;
3474 const char *mname = NULL;
3475 GPtrArray *method_array;
3476 MonoClass *klass, *refklass;
3479 if (!MethodInfo_array) {
3480 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3481 mono_memory_barrier ();
3482 MethodInfo_array = klass;
3485 klass = mono_class_from_mono_type (type->type);
3486 refklass = mono_class_from_mono_type (reftype->type);
3487 domain = ((MonoObject *)type)->vtable->domain;
3488 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3489 if (type->type->byref)
3490 return mono_array_new_specific (array_vtable, 0);
3493 mname = mono_string_to_utf8 (name);
3495 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3496 g_free ((char*)mname);
3498 mono_set_pending_exception (ex);
3502 res = mono_array_new_specific (array_vtable, method_array->len);
3504 for (i = 0; i < method_array->len; ++i) {
3505 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3506 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3509 g_ptr_array_free (method_array, TRUE);
3513 ICALL_EXPORT MonoArray*
3514 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3517 static MonoClass *System_Reflection_ConstructorInfo;
3518 MonoClass *startklass, *klass, *refklass;
3523 gpointer iter = NULL;
3524 MonoPtrArray tmp_array;
3526 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3528 domain = ((MonoObject *)type)->vtable->domain;
3529 if (type->type->byref)
3530 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3531 klass = startklass = mono_class_from_mono_type (type->type);
3532 refklass = mono_class_from_mono_type (reftype->type);
3534 if (!System_Reflection_ConstructorInfo)
3535 System_Reflection_ConstructorInfo = mono_class_from_name (
3536 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3538 mono_class_setup_methods (klass);
3539 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3540 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3545 while ((method = mono_class_get_methods (klass, &iter))) {
3547 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3549 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3550 if (bflags & BFLAGS_Public)
3553 if (bflags & BFLAGS_NonPublic)
3559 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3560 if (bflags & BFLAGS_Static)
3561 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3564 if (bflags & BFLAGS_Instance)
3570 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3572 mono_ptr_array_append (tmp_array, member);
3575 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3577 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3578 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3580 mono_ptr_array_destroy (tmp_array);
3586 property_hash (gconstpointer data)
3588 MonoProperty *prop = (MonoProperty*)data;
3590 return g_str_hash (prop->name);
3594 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3596 if (method1->is_inflated)
3597 method1 = ((MonoMethodInflated*) method1)->declaring;
3598 if (method2->is_inflated)
3599 method2 = ((MonoMethodInflated*) method2)->declaring;
3601 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3605 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3607 // Properties are hide-by-name-and-signature
3608 if (!g_str_equal (prop1->name, prop2->name))
3611 /* If we see a property in a generic method, we want to
3612 compare the generic signatures, not the inflated signatures
3613 because we might conflate two properties that were
3617 public T this[T t] { getter { return t; } } // method 1
3618 public U this[U u] { getter { return u; } } // method 2
3621 If we see int Foo<int,int>::Item[int] we need to know if
3622 the indexer came from method 1 or from method 2, and we
3623 shouldn't conflate them. (Bugzilla 36283)
3625 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3628 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3635 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3640 return method_nonpublic (accessor, start_klass);
3643 ICALL_EXPORT MonoArray*
3644 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3648 static MonoClass *System_Reflection_PropertyInfo;
3649 MonoClass *startklass, *klass;
3655 gchar *propname = NULL;
3656 int (*compare_func) (const char *s1, const char *s2) = NULL;
3658 GHashTable *properties = NULL;
3659 MonoPtrArray tmp_array;
3661 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3663 if (!System_Reflection_PropertyInfo)
3664 System_Reflection_PropertyInfo = mono_class_from_name (
3665 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3667 domain = ((MonoObject *)type)->vtable->domain;
3668 if (type->type->byref)
3669 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3670 klass = startklass = mono_class_from_mono_type (type->type);
3673 propname = mono_string_to_utf8 (name);
3674 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3677 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3679 mono_class_setup_methods (klass);
3680 mono_class_setup_vtable (klass);
3681 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3685 while ((prop = mono_class_get_properties (klass, &iter))) {
3691 flags = method->flags;
3694 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3695 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3696 if (bflags & BFLAGS_Public)
3698 } else if (bflags & BFLAGS_NonPublic) {
3699 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3700 property_accessor_nonpublic(prop->set, startklass == klass)) {
3707 if (flags & METHOD_ATTRIBUTE_STATIC) {
3708 if (bflags & BFLAGS_Static)
3709 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3712 if (bflags & BFLAGS_Instance)
3721 if (compare_func (propname, prop->name))
3725 if (g_hash_table_lookup (properties, prop))
3728 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3730 g_hash_table_insert (properties, prop, prop);
3732 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3735 g_hash_table_destroy (properties);
3738 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3739 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3740 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3742 mono_ptr_array_destroy (tmp_array);
3748 g_hash_table_destroy (properties);
3751 mono_ptr_array_destroy (tmp_array);
3753 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3754 ex = mono_class_get_exception_for_failure (klass);
3756 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3757 mono_loader_clear_error ();
3759 mono_set_pending_exception (ex);
3764 event_hash (gconstpointer data)
3766 MonoEvent *event = (MonoEvent*)data;
3768 return g_str_hash (event->name);
3772 event_equal (MonoEvent *event1, MonoEvent *event2)
3774 // Events are hide-by-name
3775 return g_str_equal (event1->name, event2->name);
3778 ICALL_EXPORT MonoArray*
3779 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3783 static MonoClass *System_Reflection_EventInfo;
3784 MonoClass *startklass, *klass;
3790 char *utf8_name = NULL;
3791 int (*compare_func) (const char *s1, const char *s2) = NULL;
3792 GHashTable *events = NULL;
3793 MonoPtrArray tmp_array;
3795 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
3797 if (!System_Reflection_EventInfo)
3798 System_Reflection_EventInfo = mono_class_from_name (
3799 mono_defaults.corlib, "System.Reflection", "EventInfo");
3801 domain = mono_object_domain (type);
3802 if (type->type->byref)
3803 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3804 klass = startklass = mono_class_from_mono_type (type->type);
3806 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3808 mono_class_setup_methods (klass);
3809 mono_class_setup_vtable (klass);
3810 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3814 while ((event = mono_class_get_events (klass, &iter))) {
3816 method = event->add;
3818 method = event->remove;
3820 method = event->raise;
3822 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3823 if (bflags & BFLAGS_Public)
3825 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3826 if (bflags & BFLAGS_NonPublic)
3831 if (bflags & BFLAGS_NonPublic)
3837 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3838 if (bflags & BFLAGS_Static)
3839 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3842 if (bflags & BFLAGS_Instance)
3847 if (bflags & BFLAGS_Instance)
3853 if (utf8_name == NULL) {
3854 utf8_name = mono_string_to_utf8 (name);
3855 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3858 if (compare_func (event->name, utf8_name))
3862 if (g_hash_table_lookup (events, event))
3865 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3867 g_hash_table_insert (events, event, event);
3869 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3872 g_hash_table_destroy (events);
3874 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3876 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3877 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3879 mono_ptr_array_destroy (tmp_array);
3881 if (utf8_name != NULL)
3887 mono_ptr_array_destroy (tmp_array);
3888 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3889 ex = mono_class_get_exception_for_failure (klass);
3891 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3892 mono_loader_clear_error ();
3894 mono_set_pending_exception (ex);
3898 ICALL_EXPORT MonoArray*
3899 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
3909 MonoPtrArray tmp_array;
3911 domain = ((MonoObject *)type)->vtable->domain;
3912 if (type->type->byref)
3913 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3914 klass = mono_class_from_mono_type (type->type);
3917 * If a nested type is generic, return its generic type definition.
3918 * Note that this means that the return value is essentially the set
3919 * of nested types of the generic type definition of @klass.
3921 * A note in MSDN claims that a generic type definition can have
3922 * nested types that aren't generic. In any case, the container of that
3923 * nested type would be the generic type definition.
3925 if (klass->generic_class)
3926 klass = klass->generic_class->container_class;
3928 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
3930 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3932 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3933 if (bflags & BFLAGS_Public)
3936 if (bflags & BFLAGS_NonPublic)
3944 str = mono_string_to_utf8 (name);
3945 mono_identifier_unescape_type_name_chars (str);
3948 if (strcmp (nested->name, str))
3952 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3953 mono_ptr_array_append (tmp_array, member);
3956 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
3958 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3959 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3961 mono_ptr_array_destroy (tmp_array);
3969 ICALL_EXPORT MonoReflectionType*
3970 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3973 MonoType *type = NULL;
3974 MonoTypeNameParse info;
3975 gboolean type_resolve;
3977 /* On MS.NET, this does not fire a TypeResolve event */
3978 type_resolve = TRUE;
3979 str = mono_string_to_utf8 (name);
3980 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3981 if (!mono_reflection_parse_type (str, &info)) {
3983 mono_reflection_free_type_info (&info);
3985 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
3988 /*g_print ("failed parse\n");*/
3992 if (info.assembly.name) {
3994 mono_reflection_free_type_info (&info);
3996 /* 1.0 and 2.0 throw different exceptions */
3997 if (mono_defaults.generic_ilist_class)
3998 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4000 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4006 if (module != NULL) {
4008 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4013 if (assembly_is_dynamic (assembly->assembly)) {
4014 /* Enumerate all modules */
4015 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4019 if (abuilder->modules) {
4020 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4021 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4022 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4028 if (!type && abuilder->loaded_modules) {
4029 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4030 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4031 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4038 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4040 mono_reflection_free_type_info (&info);
4042 MonoException *e = NULL;
4045 e = mono_get_exception_type_load (name, NULL);
4047 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4048 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4050 mono_loader_clear_error ();
4053 mono_set_pending_exception (e);
4055 } else if (mono_loader_get_last_error ()) {
4057 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4060 mono_loader_clear_error ();
4063 if (type->type == MONO_TYPE_CLASS) {
4064 MonoClass *klass = mono_type_get_class (type);
4066 /* need to report exceptions ? */
4067 if (throwOnError && klass->exception_type) {
4068 /* report SecurityException (or others) that occured when loading the assembly */
4069 MonoException *exc = mono_class_get_exception_for_failure (klass);
4070 mono_loader_clear_error ();
4071 mono_set_pending_exception (exc);
4076 /* g_print ("got it\n"); */
4077 return mono_type_get_object (mono_object_domain (assembly), type);
4081 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4084 gchar *shadow_ini_file;
4087 /* Check for shadow-copied assembly */
4088 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4089 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4091 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4092 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4098 g_free (shadow_ini_file);
4099 if (content != NULL) {
4102 *filename = content;
4109 ICALL_EXPORT MonoString *
4110 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4112 MonoDomain *domain = mono_object_domain (assembly);
4113 MonoAssembly *mass = assembly->assembly;
4114 MonoString *res = NULL;
4119 if (g_path_is_absolute (mass->image->name)) {
4120 absolute = g_strdup (mass->image->name);
4121 dirname = g_path_get_dirname (absolute);
4123 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4124 dirname = g_strdup (mass->basedir);
4127 replace_shadow_path (domain, dirname, &absolute);
4132 for (i = strlen (absolute) - 1; i >= 0; i--)
4133 if (absolute [i] == '\\')
4138 uri = g_filename_to_uri (absolute, NULL, NULL);
4140 const char *prepend = "file://";
4142 if (*absolute == '/' && *(absolute + 1) == '/') {
4145 prepend = "file:///";
4148 uri = g_strconcat (prepend, absolute, NULL);
4152 res = mono_string_new (domain, uri);
4159 ICALL_EXPORT MonoBoolean
4160 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4162 MonoAssembly *mass = assembly->assembly;
4164 return mass->in_gac;
4167 ICALL_EXPORT MonoReflectionAssembly*
4168 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4172 MonoImageOpenStatus status;
4174 name = mono_string_to_utf8 (mname);
4175 res = mono_assembly_load_with_partial_name (name, &status);
4181 return mono_assembly_get_object (mono_domain_get (), res);
4184 ICALL_EXPORT MonoString *
4185 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4187 MonoDomain *domain = mono_object_domain (assembly);
4190 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4195 ICALL_EXPORT MonoBoolean
4196 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4198 return assembly->assembly->ref_only;
4201 ICALL_EXPORT MonoString *
4202 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4204 MonoDomain *domain = mono_object_domain (assembly);
4206 return mono_string_new (domain, assembly->assembly->image->version);
4209 ICALL_EXPORT MonoReflectionMethod*
4210 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4214 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4218 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4219 mono_error_raise_exception (&error);
4221 return mono_method_get_object (mono_object_domain (assembly), method, NULL);
4224 ICALL_EXPORT MonoReflectionModule*
4225 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4227 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4230 ICALL_EXPORT MonoArray*
4231 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4233 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4234 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4238 for (i = 0; i < table->rows; ++i) {
4239 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4240 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4246 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4248 static MonoClass *System_Version = NULL;
4249 static MonoMethod *create_version = NULL;
4253 if (!System_Version) {
4254 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4255 g_assert (System_Version);
4258 if (!create_version) {
4259 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4260 create_version = mono_method_desc_search_in_class (desc, System_Version);
4261 g_assert (create_version);
4262 mono_method_desc_free (desc);
4268 args [3] = &revision;
4269 result = mono_object_new (domain, System_Version);
4270 mono_runtime_invoke (create_version, result, args, NULL);
4275 ICALL_EXPORT MonoArray*
4276 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4278 static MonoClass *System_Reflection_AssemblyName;
4280 MonoDomain *domain = mono_object_domain (assembly);
4282 static MonoMethod *create_culture = NULL;
4283 MonoImage *image = assembly->assembly->image;
4286 if (!System_Reflection_AssemblyName)
4287 System_Reflection_AssemblyName = mono_class_from_name (
4288 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4290 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4293 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4295 if (count > 0 && !create_culture) {
4296 MonoMethodDesc *desc = mono_method_desc_new (
4297 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4298 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4299 g_assert (create_culture);
4300 mono_method_desc_free (desc);
4303 for (i = 0; i < count; i++) {
4304 MonoReflectionAssemblyName *aname;
4305 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4307 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4309 aname = (MonoReflectionAssemblyName *) mono_object_new (
4310 domain, System_Reflection_AssemblyName);
4312 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4314 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4315 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4316 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4317 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4318 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4319 aname->versioncompat = 1; /* SameMachine (default) */
4320 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4321 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4323 if (create_culture) {
4325 MonoBoolean assembly_ref = 1;
4326 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4327 args [1] = &assembly_ref;
4328 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4331 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4332 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4333 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4335 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4336 /* public key token isn't copied - the class library will
4337 automatically generate it from the public key if required */
4338 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4339 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4341 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4342 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4345 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4348 /* note: this function doesn't return the codebase on purpose (i.e. it can
4349 be used under partial trust as path information isn't present). */
4351 mono_array_setref (result, i, aname);
4356 /* move this in some file in mono/util/ */
4358 g_concat_dir_and_file (const char *dir, const char *file)
4360 g_return_val_if_fail (dir != NULL, NULL);
4361 g_return_val_if_fail (file != NULL, NULL);
4364 * If the directory name doesn't have a / on the end, we need
4365 * to add one so we get a proper path to the file
4367 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4368 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4370 return g_strconcat (dir, file, NULL);
4374 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4376 char *n = mono_string_to_utf8 (name);
4377 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4379 guint32 cols [MONO_MANIFEST_SIZE];
4380 guint32 impl, file_idx;
4384 for (i = 0; i < table->rows; ++i) {
4385 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4386 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4387 if (strcmp (val, n) == 0)
4391 if (i == table->rows)
4394 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4397 * this code should only be called after obtaining the
4398 * ResourceInfo and handling the other cases.
4400 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4401 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4403 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4408 module = assembly->assembly->image;
4410 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4412 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4415 ICALL_EXPORT gboolean
4416 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4418 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4420 guint32 cols [MONO_MANIFEST_SIZE];
4421 guint32 file_cols [MONO_FILE_SIZE];
4425 n = mono_string_to_utf8 (name);
4426 for (i = 0; i < table->rows; ++i) {
4427 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4428 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4429 if (strcmp (val, n) == 0)
4433 if (i == table->rows)
4436 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4437 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4440 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4441 case MONO_IMPLEMENTATION_FILE:
4442 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4443 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4444 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4445 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4446 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4447 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4450 info->location = RESOURCE_LOCATION_EMBEDDED;
4453 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4454 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4455 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4456 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4457 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4458 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4460 mono_set_pending_exception (ex);
4463 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4465 /* Obtain info recursively */
4466 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4467 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4470 case MONO_IMPLEMENTATION_EXP_TYPE:
4471 g_assert_not_reached ();
4479 ICALL_EXPORT MonoObject*
4480 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4482 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4483 MonoArray *result = NULL;
4488 /* check hash if needed */
4490 n = mono_string_to_utf8 (name);
4491 for (i = 0; i < table->rows; ++i) {
4492 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4493 if (strcmp (val, n) == 0) {
4496 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4497 fn = mono_string_new (mono_object_domain (assembly), n);
4499 return (MonoObject*)fn;
4507 for (i = 0; i < table->rows; ++i) {
4508 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4512 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4515 for (i = 0; i < table->rows; ++i) {
4516 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4517 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4518 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4519 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4524 return (MonoObject*)result;
4527 ICALL_EXPORT MonoArray*
4528 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4530 MonoDomain *domain = mono_domain_get();
4533 int i, j, file_count = 0;
4534 MonoImage **modules;
4535 guint32 module_count, real_module_count;
4536 MonoTableInfo *table;
4537 guint32 cols [MONO_FILE_SIZE];
4538 MonoImage *image = assembly->assembly->image;
4540 g_assert (image != NULL);
4541 g_assert (!assembly_is_dynamic (assembly->assembly));
4543 table = &image->tables [MONO_TABLE_FILE];
4544 file_count = table->rows;
4546 modules = image->modules;
4547 module_count = image->module_count;
4549 real_module_count = 0;
4550 for (i = 0; i < module_count; ++i)
4552 real_module_count ++;
4554 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4555 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4557 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4559 for (i = 0; i < module_count; ++i)
4561 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4565 for (i = 0; i < file_count; ++i, ++j) {
4566 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4567 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4568 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4570 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4572 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4573 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4576 mono_array_setref (res, j, mono_module_get_object (domain, m));
4583 ICALL_EXPORT MonoReflectionMethod*
4584 ves_icall_GetCurrentMethod (void)
4586 MonoMethod *m = mono_method_get_last_managed ();
4589 mono_raise_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4591 while (m->is_inflated)
4592 m = ((MonoMethodInflated*)m)->declaring;
4594 return mono_method_get_object (mono_domain_get (), m, NULL);
4599 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4602 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4605 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4606 //method is inflated, we should inflate it on the other class
4607 MonoGenericContext ctx;
4608 ctx.method_inst = inflated->context.method_inst;
4609 ctx.class_inst = inflated->context.class_inst;
4610 if (klass->generic_class)
4611 ctx.class_inst = klass->generic_class->context.class_inst;
4612 else if (klass->generic_container)
4613 ctx.class_inst = klass->generic_container->context.class_inst;
4614 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4615 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4619 mono_class_setup_methods (method->klass);
4620 if (method->klass->exception_type)
4622 for (i = 0; i < method->klass->method.count; ++i) {
4623 if (method->klass->methods [i] == method) {
4628 mono_class_setup_methods (klass);
4629 if (klass->exception_type)
4631 g_assert (offset >= 0 && offset < klass->method.count);
4632 return klass->methods [offset];
4635 ICALL_EXPORT MonoReflectionMethod*
4636 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4640 klass = mono_class_from_mono_type (type);
4641 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4643 if (method->klass != klass) {
4644 method = mono_method_get_equivalent_method (method, klass);
4649 klass = method->klass;
4650 return mono_method_get_object (mono_domain_get (), method, klass);
4653 ICALL_EXPORT MonoReflectionMethodBody*
4654 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4656 return mono_method_body_get_object (mono_domain_get (), method);
4659 ICALL_EXPORT MonoReflectionAssembly*
4660 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4662 MonoMethod *dest = NULL;
4664 mono_stack_walk_no_il (get_executing, &dest);
4666 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4670 ICALL_EXPORT MonoReflectionAssembly*
4671 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4673 MonoDomain* domain = mono_domain_get ();
4675 if (!domain->entry_assembly)
4678 return mono_assembly_get_object (domain, domain->entry_assembly);
4681 ICALL_EXPORT MonoReflectionAssembly*
4682 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4688 mono_stack_walk_no_il (get_executing, &dest);
4690 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
4694 mono_raise_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4695 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4698 ICALL_EXPORT MonoString *
4699 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4700 gboolean assembly_qualified)
4702 MonoDomain *domain = mono_object_domain (object);
4703 MonoTypeNameFormat format;
4708 format = assembly_qualified ?
4709 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4710 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4712 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4714 name = mono_type_get_name_full (object->type, format);
4718 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4723 res = mono_string_new (domain, name);
4730 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
4732 MonoClass *klass = mono_class_from_mono_type (rfield->type);
4733 mono_class_init_or_throw (klass);
4734 return mono_security_core_clr_class_level (klass);
4738 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
4740 MonoClassField *field = rfield->field;
4741 return mono_security_core_clr_field_level (field, TRUE);
4745 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
4747 MonoMethod *method = rfield->method;
4748 return mono_security_core_clr_method_level (method, TRUE);
4752 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4754 static MonoMethod *create_culture = NULL;
4757 const char *pkey_ptr;
4759 MonoBoolean assembly_ref = 0;
4761 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4762 aname->major = name->major;
4763 aname->minor = name->minor;
4764 aname->build = name->build;
4765 aname->flags = name->flags;
4766 aname->revision = name->revision;
4767 aname->hashalg = name->hash_alg;
4768 aname->versioncompat = 1; /* SameMachine (default) */
4769 aname->processor_architecture = name->arch;
4771 if (by_default_version)
4772 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4775 if (absolute != NULL && *absolute != '\0') {
4776 const gchar *prepend = "file://";
4779 codebase = g_strdup (absolute);
4784 for (i = strlen (codebase) - 1; i >= 0; i--)
4785 if (codebase [i] == '\\')
4788 if (*codebase == '/' && *(codebase + 1) == '/') {
4791 prepend = "file:///";
4795 result = g_strconcat (prepend, codebase, NULL);
4801 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4805 if (!create_culture) {
4806 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4807 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4808 g_assert (create_culture);
4809 mono_method_desc_free (desc);
4812 if (name->culture) {
4813 args [0] = mono_string_new (domain, name->culture);
4814 args [1] = &assembly_ref;
4815 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4818 if (name->public_key) {
4819 pkey_ptr = (char*)name->public_key;
4820 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4822 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4823 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4824 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4825 } else if (default_publickey) {
4826 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4827 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4830 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4831 if (name->public_key_token [0]) {
4835 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4836 p = mono_array_addr (aname->keyToken, char, 0);
4838 for (i = 0, j = 0; i < 8; i++) {
4839 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4840 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4843 } else if (default_token) {
4844 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4848 ICALL_EXPORT MonoString *
4849 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4851 MonoDomain *domain = mono_object_domain (assembly);
4852 MonoAssembly *mass = assembly->assembly;
4856 name = mono_stringify_assembly_name (&mass->aname);
4857 res = mono_string_new (domain, name);
4864 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4867 MonoAssembly *mass = assembly->assembly;
4869 if (g_path_is_absolute (mass->image->name)) {
4870 fill_reflection_assembly_name (mono_object_domain (assembly),
4871 aname, &mass->aname, mass->image->name, TRUE,
4875 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4877 fill_reflection_assembly_name (mono_object_domain (assembly),
4878 aname, &mass->aname, absolute, TRUE, TRUE,
4885 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4888 MonoImageOpenStatus status = MONO_IMAGE_OK;
4891 MonoAssemblyName name;
4894 filename = mono_string_to_utf8 (fname);
4896 dirname = g_path_get_dirname (filename);
4897 replace_shadow_path (mono_domain_get (), dirname, &filename);
4900 image = mono_image_open (filename, &status);
4906 if (status == MONO_IMAGE_IMAGE_INVALID)
4907 exc = mono_get_exception_bad_image_format2 (NULL, fname);
4909 exc = mono_get_exception_file_not_found2 (NULL, fname);
4910 mono_set_pending_exception (exc);
4914 res = mono_assembly_fill_assembly_name (image, &name);
4916 mono_image_close (image);
4918 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4922 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
4926 mono_image_close (image);
4929 ICALL_EXPORT MonoBoolean
4930 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4931 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4933 MonoBoolean result = FALSE;
4934 MonoDeclSecurityEntry entry;
4936 /* SecurityAction.RequestMinimum */
4937 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4938 *minimum = entry.blob;
4939 *minLength = entry.size;
4942 /* SecurityAction.RequestOptional */
4943 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4944 *optional = entry.blob;
4945 *optLength = entry.size;
4948 /* SecurityAction.RequestRefuse */
4949 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4950 *refused = entry.blob;
4951 *refLength = entry.size;
4959 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
4961 guint32 attrs, visibility;
4963 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
4964 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4965 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
4968 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
4974 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
4978 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4981 /* we start the count from 1 because we skip the special type <Module> */
4984 for (i = 1; i < tdef->rows; ++i) {
4985 if (mono_module_type_is_visible (tdef, image, i + 1))
4989 count = tdef->rows - 1;
4991 res = mono_array_new (domain, mono_defaults.monotype_class, count);
4992 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
4994 for (i = 1; i < tdef->rows; ++i) {
4995 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
4997 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
4998 mono_loader_assert_no_error (); /* Plug any leaks */
5001 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5003 MonoException *ex = mono_error_convert_to_exception (&error);
5004 mono_array_setref (*exceptions, count, ex);
5013 ICALL_EXPORT MonoArray*
5014 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5016 MonoArray *res = NULL;
5017 MonoArray *exceptions = NULL;
5018 MonoImage *image = NULL;
5019 MonoTableInfo *table = NULL;
5022 int i, len, ex_count;
5024 domain = mono_object_domain (assembly);
5026 g_assert (!assembly_is_dynamic (assembly->assembly));
5027 image = assembly->assembly->image;
5028 table = &image->tables [MONO_TABLE_FILE];
5029 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5031 /* Append data from all modules in the assembly */
5032 for (i = 0; i < table->rows; ++i) {
5033 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5034 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5037 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5038 /* Append the new types to the end of the array */
5039 if (mono_array_length (res2) > 0) {
5041 MonoArray *res3, *ex3;
5043 len1 = mono_array_length (res);
5044 len2 = mono_array_length (res2);
5046 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5047 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5048 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5051 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5052 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5053 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5060 /* the ReflectionTypeLoadException must have all the types (Types property),
5061 * NULL replacing types which throws an exception. The LoaderException must
5062 * contain all exceptions for NULL items.
5065 len = mono_array_length (res);
5068 for (i = 0; i < len; i++) {
5069 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5073 klass = mono_type_get_class (t->type);
5074 if ((klass != NULL) && klass->exception_type) {
5075 /* keep the class in the list */
5076 list = g_list_append (list, klass);
5077 /* and replace Type with NULL */
5078 mono_array_setref (res, i, NULL);
5085 if (list || ex_count) {
5087 MonoException *exc = NULL;
5088 MonoArray *exl = NULL;
5089 int j, length = g_list_length (list) + ex_count;
5091 mono_loader_clear_error ();
5093 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5094 /* Types for which mono_class_get_checked () succeeded */
5095 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5096 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5097 mono_array_setref (exl, i, exc);
5099 /* Types for which it don't */
5100 for (j = 0; j < mono_array_length (exceptions); ++j) {
5101 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5103 g_assert (i < length);
5104 mono_array_setref (exl, i, exc);
5111 exc = mono_get_exception_reflection_type_load (res, exl);
5112 mono_loader_clear_error ();
5113 mono_set_pending_exception (exc);
5120 ICALL_EXPORT gboolean
5121 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5123 MonoAssemblyName aname;
5124 MonoDomain *domain = mono_object_domain (name);
5126 gboolean is_version_defined;
5127 gboolean is_token_defined;
5129 aname.public_key = NULL;
5130 val = mono_string_to_utf8 (assname);
5131 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5132 g_free ((guint8*) aname.public_key);
5137 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5138 FALSE, is_token_defined);
5140 mono_assembly_name_free (&aname);
5141 g_free ((guint8*) aname.public_key);
5147 ICALL_EXPORT MonoReflectionType*
5148 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5151 MonoDomain *domain = mono_object_domain (module);
5154 g_assert (module->image);
5156 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5157 /* These images do not have a global type */
5160 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5161 mono_error_raise_exception (&error);
5162 return mono_type_get_object (domain, &klass->byval_arg);
5166 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5168 /*if (module->image)
5169 mono_image_close (module->image);*/
5172 ICALL_EXPORT MonoString*
5173 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5175 MonoDomain *domain = mono_object_domain (module);
5177 g_assert (module->image);
5178 return mono_string_new (domain, module->image->guid);
5181 ICALL_EXPORT gpointer
5182 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5185 if (module->image && module->image->is_module_handle)
5186 return module->image->raw_data;
5189 return (gpointer) (-1);
5193 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5195 if (image_is_dynamic (image)) {
5196 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5197 *pe_kind = dyn->pe_kind;
5198 *machine = dyn->machine;
5201 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5202 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5207 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5209 return (image->md_version_major << 16) | (image->md_version_minor);
5212 ICALL_EXPORT MonoArray*
5213 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5215 MonoArray *exceptions;
5219 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5221 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5222 for (i = 0; i < mono_array_length (exceptions); ++i) {
5223 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5225 mono_set_pending_exception (ex);
5234 mono_memberref_is_method (MonoImage *image, guint32 token)
5236 if (!image_is_dynamic (image)) {
5237 guint32 cols [MONO_MEMBERREF_SIZE];
5239 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5240 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5241 mono_metadata_decode_blob_size (sig, &sig);
5242 return (*sig != 0x6);
5244 MonoClass *handle_class;
5246 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5249 return mono_defaults.methodhandle_class == handle_class;
5254 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5257 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5258 mono_array_addr (type_args, MonoType*, 0));
5260 context->class_inst = NULL;
5262 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5263 mono_array_addr (method_args, MonoType*, 0));
5265 context->method_inst = NULL;
5268 ICALL_EXPORT MonoType*
5269 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5272 int table = mono_metadata_token_table (token);
5273 int index = mono_metadata_token_index (token);
5274 MonoGenericContext context;
5277 *resolve_error = ResolveTokenError_Other;
5279 /* Validate token */
5280 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5281 (table != MONO_TABLE_TYPESPEC)) {
5282 *resolve_error = ResolveTokenError_BadTable;
5286 if (image_is_dynamic (image)) {
5287 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5288 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5289 return klass ? &klass->byval_arg : NULL;
5292 init_generic_context_from_args (&context, type_args, method_args);
5293 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5294 return klass ? &klass->byval_arg : NULL;
5297 if ((index <= 0) || (index > image->tables [table].rows)) {
5298 *resolve_error = ResolveTokenError_OutOfRange;
5302 init_generic_context_from_args (&context, type_args, method_args);
5303 klass = mono_class_get_checked (image, token, &error);
5305 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5306 mono_error_raise_exception (&error);
5309 return &klass->byval_arg;
5314 ICALL_EXPORT MonoMethod*
5315 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5318 int table = mono_metadata_token_table (token);
5319 int index = mono_metadata_token_index (token);
5320 MonoGenericContext context;
5323 *resolve_error = ResolveTokenError_Other;
5325 /* Validate token */
5326 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5327 (table != MONO_TABLE_MEMBERREF)) {
5328 *resolve_error = ResolveTokenError_BadTable;
5332 if (image_is_dynamic (image)) {
5333 if (table == MONO_TABLE_METHOD)
5334 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5336 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5337 *resolve_error = ResolveTokenError_BadTable;
5341 init_generic_context_from_args (&context, type_args, method_args);
5342 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5345 if ((index <= 0) || (index > image->tables [table].rows)) {
5346 *resolve_error = ResolveTokenError_OutOfRange;
5349 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5350 *resolve_error = ResolveTokenError_BadTable;
5354 init_generic_context_from_args (&context, type_args, method_args);
5355 method = mono_get_method_checked (image, token, NULL, &context, &error);
5356 mono_error_raise_exception (&error);
5361 ICALL_EXPORT MonoString*
5362 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5364 int index = mono_metadata_token_index (token);
5366 *error = ResolveTokenError_Other;
5368 /* Validate token */
5369 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5370 *error = ResolveTokenError_BadTable;
5374 if (image_is_dynamic (image))
5375 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5377 if ((index <= 0) || (index >= image->heap_us.size)) {
5378 *error = ResolveTokenError_OutOfRange;
5382 /* FIXME: What to do if the index points into the middle of a string ? */
5384 return mono_ldstr (mono_domain_get (), image, index);
5387 ICALL_EXPORT MonoClassField*
5388 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5392 int table = mono_metadata_token_table (token);
5393 int index = mono_metadata_token_index (token);
5394 MonoGenericContext context;
5395 MonoClassField *field;
5397 *resolve_error = ResolveTokenError_Other;
5399 /* Validate token */
5400 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5401 *resolve_error = ResolveTokenError_BadTable;
5405 if (image_is_dynamic (image)) {
5406 if (table == MONO_TABLE_FIELD)
5407 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5409 if (mono_memberref_is_method (image, token)) {
5410 *resolve_error = ResolveTokenError_BadTable;
5414 init_generic_context_from_args (&context, type_args, method_args);
5415 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5418 if ((index <= 0) || (index > image->tables [table].rows)) {
5419 *resolve_error = ResolveTokenError_OutOfRange;
5422 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5423 *resolve_error = ResolveTokenError_BadTable;
5427 init_generic_context_from_args (&context, type_args, method_args);
5428 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5429 mono_error_raise_exception (&error);
5435 ICALL_EXPORT MonoObject*
5436 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5438 int table = mono_metadata_token_table (token);
5440 *error = ResolveTokenError_Other;
5443 case MONO_TABLE_TYPEDEF:
5444 case MONO_TABLE_TYPEREF:
5445 case MONO_TABLE_TYPESPEC: {
5446 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5448 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5452 case MONO_TABLE_METHOD:
5453 case MONO_TABLE_METHODSPEC: {
5454 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5456 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5460 case MONO_TABLE_FIELD: {
5461 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5463 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5467 case MONO_TABLE_MEMBERREF:
5468 if (mono_memberref_is_method (image, token)) {
5469 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5471 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5476 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5478 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5485 *error = ResolveTokenError_BadTable;
5491 ICALL_EXPORT MonoArray*
5492 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5494 int table = mono_metadata_token_table (token);
5495 int idx = mono_metadata_token_index (token);
5496 MonoTableInfo *tables = image->tables;
5501 *error = ResolveTokenError_OutOfRange;
5503 /* FIXME: Support other tables ? */
5504 if (table != MONO_TABLE_STANDALONESIG)
5507 if (image_is_dynamic (image))
5510 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5513 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5515 ptr = mono_metadata_blob_heap (image, sig);
5516 len = mono_metadata_decode_blob_size (ptr, &ptr);
5518 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5519 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5523 ICALL_EXPORT MonoReflectionType*
5524 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5527 int isbyref = 0, rank;
5528 char *str = mono_string_to_utf8 (smodifiers);
5531 klass = mono_class_from_mono_type (tb->type.type);
5533 /* logic taken from mono_reflection_parse_type(): keep in sync */
5537 if (isbyref) { /* only one level allowed by the spec */
5544 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5547 klass = mono_ptr_class_get (&klass->byval_arg);
5548 mono_class_init (klass);
5559 else if (*p != '*') { /* '*' means unknown lower bound */
5570 klass = mono_array_class_get (klass, rank);
5571 mono_class_init (klass);
5578 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5581 ICALL_EXPORT MonoBoolean
5582 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5588 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5594 check_for_invalid_type (MonoClass *klass)
5598 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5601 name = mono_type_get_full_name (klass);
5602 str = mono_string_new (mono_domain_get (), name);
5604 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5607 ICALL_EXPORT MonoReflectionType *
5608 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5610 MonoClass *klass, *aklass;
5612 klass = mono_class_from_mono_type (type->type);
5613 check_for_invalid_type (klass);
5615 if (rank == 0) //single dimentional array
5616 aklass = mono_array_class_get (klass, 1);
5618 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5620 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5623 ICALL_EXPORT MonoReflectionType *
5624 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5628 klass = mono_class_from_mono_type (type->type);
5629 mono_class_init_or_throw (klass);
5630 check_for_invalid_type (klass);
5632 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5635 ICALL_EXPORT MonoReflectionType *
5636 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5638 MonoClass *klass, *pklass;
5640 klass = mono_class_from_mono_type (type->type);
5641 mono_class_init_or_throw (klass);
5642 check_for_invalid_type (klass);
5644 pklass = mono_ptr_class_get (type->type);
5646 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5649 ICALL_EXPORT MonoObject *
5650 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5651 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5653 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5654 MonoObject *delegate;
5656 MonoMethod *method = info->method;
5658 mono_class_init_or_throw (delegate_class);
5660 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5662 if (mono_security_core_clr_enabled ()) {
5663 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5667 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5669 if (method_is_dynamic (method)) {
5670 /* Creating a trampoline would leak memory */
5671 func = mono_compile_method (method);
5673 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5674 method = mono_object_get_virtual_method (target, method);
5675 func = mono_create_ftnptr (mono_domain_get (),
5676 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5679 mono_delegate_ctor_with_method (delegate, target, func, method);
5684 ICALL_EXPORT MonoMulticastDelegate *
5685 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
5687 MonoMulticastDelegate *ret;
5689 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
5691 ret = (MonoMulticastDelegate*) mono_object_new (mono_object_domain (delegate), mono_object_class (delegate));
5692 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
5697 ICALL_EXPORT MonoReflectionMethod*
5698 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
5700 return mono_method_get_object (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target));
5705 static inline gint32
5706 mono_array_get_byte_length (MonoArray *array)
5712 klass = array->obj.vtable->klass;
5714 if (array->bounds == NULL)
5715 length = array->max_length;
5718 for (i = 0; i < klass->rank; ++ i)
5719 length *= array->bounds [i].length;
5722 switch (klass->element_class->byval_arg.type) {
5725 case MONO_TYPE_BOOLEAN:
5729 case MONO_TYPE_CHAR:
5737 return length * sizeof (gpointer);
5748 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
5750 return mono_array_get_byte_length (array);
5754 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
5756 return mono_array_get (array, gint8, idx);
5760 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
5762 mono_array_set (array, gint8, idx, value);
5765 ICALL_EXPORT MonoBoolean
5766 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
5768 guint8 *src_buf, *dest_buf;
5771 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
5775 g_assert (count >= 0);
5777 /* This is called directly from the class libraries without going through the managed wrapper */
5778 MONO_CHECK_ARG_NULL (src, FALSE);
5779 MONO_CHECK_ARG_NULL (dest, FALSE);
5781 /* watch out for integer overflow */
5782 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5785 src_buf = (guint8 *)src->vector + src_offset;
5786 dest_buf = (guint8 *)dest->vector + dest_offset;
5789 memcpy (dest_buf, src_buf, count);
5791 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5796 #ifndef DISABLE_REMOTING
5797 ICALL_EXPORT MonoObject *
5798 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
5800 MonoDomain *domain = mono_object_domain (this_obj);
5802 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
5803 MonoTransparentProxy *tp;
5807 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5808 tp = (MonoTransparentProxy*) res;
5810 MONO_OBJECT_SETREF (tp, rp, rp);
5811 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5812 klass = mono_class_from_mono_type (type);
5814 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
5815 mono_class_setup_vtable (klass);
5816 if (klass->exception_type)
5817 mono_raise_exception (mono_class_get_exception_for_failure (klass));
5819 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
5820 tp->remote_class = mono_remote_class (domain, class_name, klass);
5822 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
5826 ICALL_EXPORT MonoReflectionType *
5827 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5829 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5833 /* System.Environment */
5836 ves_icall_System_Environment_get_UserName (void)
5838 /* using glib is more portable */
5839 return mono_string_new (mono_domain_get (), g_get_user_name ());
5843 ICALL_EXPORT MonoString *
5844 ves_icall_System_Environment_get_MachineName (void)
5846 #if defined (HOST_WIN32)
5851 len = MAX_COMPUTERNAME_LENGTH + 1;
5852 buf = g_new (gunichar2, len);
5855 if (GetComputerName (buf, (PDWORD) &len))
5856 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5860 #elif !defined(DISABLE_SOCKETS)
5864 #if defined _SC_HOST_NAME_MAX
5865 n = sysconf (_SC_HOST_NAME_MAX);
5869 buf = g_malloc (n+1);
5871 if (gethostname (buf, n) == 0){
5873 result = mono_string_new (mono_domain_get (), buf);
5880 return mono_string_new (mono_domain_get (), "mono");
5885 ves_icall_System_Environment_get_Platform (void)
5887 #if defined (TARGET_WIN32)
5890 #elif defined(__MACH__)
5893 // Notice that the value is hidden from user code, and only exposed
5894 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
5895 // define and making assumptions based on Unix/128/4 values before there
5896 // was a MacOS define. Lots of code would assume that not-Unix meant
5897 // Windows, but in this case, it would be OSX.
5906 ICALL_EXPORT MonoString *
5907 ves_icall_System_Environment_get_NewLine (void)
5909 #if defined (HOST_WIN32)
5910 return mono_string_new (mono_domain_get (), "\r\n");
5912 return mono_string_new (mono_domain_get (), "\n");
5916 ICALL_EXPORT MonoBoolean
5917 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
5919 #if SIZEOF_VOID_P == 8
5923 gboolean isWow64Process = FALSE;
5924 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
5925 return (MonoBoolean)isWow64Process;
5927 #elif defined(HAVE_SYS_UTSNAME_H)
5928 struct utsname name;
5930 if (uname (&name) >= 0) {
5931 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
5938 ICALL_EXPORT MonoString *
5939 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5947 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5948 value = g_getenv (utf8_name);
5955 return mono_string_new (mono_domain_get (), value);
5959 * There is no standard way to get at environ.
5962 #ifndef __MINGW32_VERSION
5963 #if defined(__APPLE__)
5964 #if defined (TARGET_OSX)
5965 /* Apple defines this in crt_externs.h but doesn't provide that header for
5966 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
5967 * in fact exist on all implementations (so far)
5969 gchar ***_NSGetEnviron(void);
5970 #define environ (*_NSGetEnviron())
5972 static char *mono_environ[1] = { NULL };
5973 #define environ mono_environ
5974 #endif /* defined (TARGET_OSX) */
5982 ICALL_EXPORT MonoArray *
5983 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
5994 env_strings = GetEnvironmentStrings();
5997 env_string = env_strings;
5998 while (*env_string != '\0') {
5999 /* weird case that MS seems to skip */
6000 if (*env_string != '=')
6002 while (*env_string != '\0')
6008 domain = mono_domain_get ();
6009 names = mono_array_new (domain, mono_defaults.string_class, n);
6013 env_string = env_strings;
6014 while (*env_string != '\0') {
6015 /* weird case that MS seems to skip */
6016 if (*env_string != '=') {
6017 equal_str = wcschr(env_string, '=');
6018 g_assert(equal_str);
6019 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6020 mono_array_setref (names, n, str);
6023 while (*env_string != '\0')
6028 FreeEnvironmentStrings (env_strings);
6041 for (e = environ; *e != 0; ++ e)
6044 domain = mono_domain_get ();
6045 names = mono_array_new (domain, mono_defaults.string_class, n);
6048 for (e = environ; *e != 0; ++ e) {
6049 parts = g_strsplit (*e, "=", 2);
6051 str = mono_string_new (domain, *parts);
6052 mono_array_setref (names, n, str);
6065 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6067 #if !GLIB_CHECK_VERSION(2,4,0)
6068 #define g_setenv(a,b,c) setenv(a,b,c)
6069 #define g_unsetenv(a) unsetenv(a)
6073 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6076 gunichar2 *utf16_name, *utf16_value;
6078 gchar *utf8_name, *utf8_value;
6083 utf16_name = mono_string_to_utf16 (name);
6084 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6085 SetEnvironmentVariable (utf16_name, NULL);
6086 g_free (utf16_name);
6090 utf16_value = mono_string_to_utf16 (value);
6092 SetEnvironmentVariable (utf16_name, utf16_value);
6094 g_free (utf16_name);
6095 g_free (utf16_value);
6097 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6099 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6100 g_unsetenv (utf8_name);
6105 utf8_value = mono_string_to_utf8_checked (value, &error);
6106 if (!mono_error_ok (&error)) {
6108 mono_error_raise_exception (&error);
6110 g_setenv (utf8_name, utf8_value, TRUE);
6113 g_free (utf8_value);
6118 ves_icall_System_Environment_Exit (int result)
6120 mono_environment_exitcode_set (result);
6122 /* FIXME: There are some cleanup hangs that should be worked out, but
6123 * if the program is going to exit, everything will be cleaned up when
6124 * NaCl exits anyway.
6126 #ifndef __native_client__
6127 if (!mono_runtime_try_shutdown ())
6128 mono_thread_exit ();
6130 /* Suspend all managed threads since the runtime is going away */
6131 mono_thread_suspend_all_other_threads ();
6133 mono_runtime_quit ();
6136 /* we may need to do some cleanup here... */
6140 ICALL_EXPORT MonoString*
6141 ves_icall_System_Environment_GetGacPath (void)
6143 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6146 ICALL_EXPORT MonoString*
6147 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6149 #if defined (HOST_WIN32)
6150 #ifndef CSIDL_FLAG_CREATE
6151 #define CSIDL_FLAG_CREATE 0x8000
6154 WCHAR path [MAX_PATH];
6155 /* Create directory if no existing */
6156 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6160 return mono_string_new_utf16 (mono_domain_get (), path, len);
6163 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6165 return mono_string_new (mono_domain_get (), "");
6168 ICALL_EXPORT MonoArray *
6169 ves_icall_System_Environment_GetLogicalDrives (void)
6171 gunichar2 buf [256], *ptr, *dname;
6173 guint initial_size = 127, size = 128;
6176 MonoString *drivestr;
6177 MonoDomain *domain = mono_domain_get ();
6183 while (size > initial_size) {
6184 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6185 if (size > initial_size) {
6188 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6189 initial_size = size;
6203 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6208 while (*u16) { u16++; len ++; }
6209 drivestr = mono_string_new_utf16 (domain, dname, len);
6210 mono_array_setref (result, ndrives++, drivestr);
6220 ICALL_EXPORT MonoString *
6221 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6223 gunichar2 volume_name [MAX_PATH + 1];
6225 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6227 return mono_string_from_utf16 (volume_name);
6230 ICALL_EXPORT MonoString *
6231 ves_icall_System_Environment_InternalGetHome (void)
6233 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6236 static const char *encodings [] = {
6238 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6239 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6240 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6242 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6243 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6244 "x_unicode_2_0_utf_7",
6246 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6247 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6249 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6252 "unicodefffe", "utf_16be",
6259 * Returns the internal codepage, if the value of "int_code_page" is
6260 * 1 at entry, and we can not compute a suitable code page number,
6261 * returns the code page as a string
6263 ICALL_EXPORT MonoString*
6264 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6269 char *codepage = NULL;
6271 int want_name = *int_code_page;
6274 *int_code_page = -1;
6276 g_get_charset (&cset);
6277 c = codepage = strdup (cset);
6278 for (c = codepage; *c; c++){
6279 if (isascii (*c) && isalpha (*c))
6284 /* g_print ("charset: %s\n", cset); */
6286 /* handle some common aliases */
6289 for (i = 0; p != 0; ){
6292 p = encodings [++i];
6295 if (strcmp (p, codepage) == 0){
6296 *int_code_page = code;
6299 p = encodings [++i];
6302 if (strstr (codepage, "utf_8") != NULL)
6303 *int_code_page |= 0x10000000;
6306 if (want_name && *int_code_page == -1)
6307 return mono_string_new (mono_domain_get (), cset);
6312 ICALL_EXPORT MonoBoolean
6313 ves_icall_System_Environment_get_HasShutdownStarted (void)
6315 if (mono_runtime_is_shutting_down ())
6318 if (mono_domain_is_unloading (mono_domain_get ()))
6325 ves_icall_System_Environment_BroadcastSettingChange (void)
6328 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6333 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6339 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6340 MonoReflectionMethod *method,
6341 MonoArray *out_args)
6343 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6346 #ifndef DISABLE_REMOTING
6347 ICALL_EXPORT MonoBoolean
6348 ves_icall_IsTransparentProxy (MonoObject *proxy)
6353 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6359 ICALL_EXPORT MonoReflectionMethod *
6360 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6361 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6365 MonoMethod **vtable;
6366 MonoMethod *res = NULL;
6368 MONO_CHECK_ARG_NULL (rtype, NULL);
6369 MONO_CHECK_ARG_NULL (rmethod, NULL);
6371 method = rmethod->method;
6372 klass = mono_class_from_mono_type (rtype->type);
6373 mono_class_init_or_throw (klass);
6375 if (MONO_CLASS_IS_INTERFACE (klass))
6378 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6381 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6382 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6388 mono_class_setup_vtable (klass);
6389 vtable = klass->vtable;
6391 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6392 gboolean variance_used = FALSE;
6393 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6394 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6396 res = vtable [offs + method->slot];
6398 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6401 if (method->slot != -1)
6402 res = vtable [method->slot];
6408 return mono_method_get_object (mono_domain_get (), res, NULL);
6412 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6417 klass = mono_class_from_mono_type (type->type);
6418 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6420 mono_vtable_set_is_remote (vtable, enable);
6423 #else /* DISABLE_REMOTING */
6426 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6428 g_assert_not_reached ();
6433 ICALL_EXPORT MonoObject *
6434 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6441 domain = mono_object_domain (type);
6442 klass = mono_class_from_mono_type (type->type);
6443 mono_class_init_or_throw (klass);
6445 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6446 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6450 if (klass->rank >= 1) {
6451 g_assert (klass->rank == 1);
6452 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6454 /* Bypass remoting object creation check */
6455 ret = mono_object_new_alloc_specific_checked (mono_class_vtable_full (domain, klass, TRUE), &error);
6456 mono_error_raise_exception (&error);
6462 ICALL_EXPORT MonoString *
6463 ves_icall_System_IO_get_temp_path (void)
6465 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6468 #ifndef PLATFORM_NO_DRIVEINFO
6469 ICALL_EXPORT MonoBoolean
6470 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6471 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6475 ULARGE_INTEGER wapi_free_bytes_avail;
6476 ULARGE_INTEGER wapi_total_number_of_bytes;
6477 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6479 *error = ERROR_SUCCESS;
6480 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6481 &wapi_total_number_of_free_bytes);
6484 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6485 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6486 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6488 *free_bytes_avail = 0;
6489 *total_number_of_bytes = 0;
6490 *total_number_of_free_bytes = 0;
6491 *error = GetLastError ();
6497 ICALL_EXPORT guint32
6498 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6500 return GetDriveType (mono_string_chars (root_path_name));
6504 ICALL_EXPORT gpointer
6505 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6507 return mono_compile_method (method);
6510 ICALL_EXPORT MonoString *
6511 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6516 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6518 #if defined (HOST_WIN32)
6519 /* Avoid mixing '/' and '\\' */
6522 for (i = strlen (path) - 1; i >= 0; i--)
6523 if (path [i] == '/')
6527 mcpath = mono_string_new (mono_domain_get (), path);
6534 get_bundled_app_config (void)
6536 const gchar *app_config;
6539 gchar *config_file_name, *config_file_path;
6540 gsize len, config_file_path_length, config_ext_length;
6543 domain = mono_domain_get ();
6544 file = domain->setup->configuration_file;
6545 if (!file || file->length == 0)
6548 // Retrieve config file and remove the extension
6549 config_file_name = mono_string_to_utf8 (file);
6550 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6551 if (!config_file_path)
6552 config_file_path = config_file_name;
6554 config_file_path_length = strlen (config_file_path);
6555 config_ext_length = strlen (".config");
6556 if (config_file_path_length <= config_ext_length)
6559 len = config_file_path_length - config_ext_length;
6560 module = (gchar *)g_malloc0 (len + 1);
6561 memcpy (module, config_file_path, len);
6562 // Get the config file from the module name
6563 app_config = mono_config_string_for_assembly_file (module);
6566 if (config_file_name != config_file_path)
6567 g_free (config_file_name);
6568 g_free (config_file_path);
6573 return mono_string_new (mono_domain_get (), app_config);
6577 get_bundled_machine_config (void)
6579 const gchar *machine_config;
6581 machine_config = mono_get_machine_config ();
6583 if (!machine_config)
6586 return mono_string_new (mono_domain_get (), machine_config);
6589 ICALL_EXPORT MonoString *
6590 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6595 path = g_path_get_dirname (mono_get_config_dir ());
6597 #if defined (HOST_WIN32)
6598 /* Avoid mixing '/' and '\\' */
6601 for (i = strlen (path) - 1; i >= 0; i--)
6602 if (path [i] == '/')
6606 ipath = mono_string_new (mono_domain_get (), path);
6612 ICALL_EXPORT gboolean
6613 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6615 MonoPEResourceDataEntry *entry;
6618 if (!assembly || !result || !size)
6623 image = assembly->assembly->image;
6624 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6628 *result = mono_image_rva_map (image, entry->rde_data_offset);
6633 *size = entry->rde_size;
6638 ICALL_EXPORT MonoBoolean
6639 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6641 return mono_is_debugger_attached ();
6644 ICALL_EXPORT MonoBoolean
6645 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
6647 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
6648 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
6654 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
6656 if (mono_get_runtime_callbacks ()->debug_log)
6657 mono_get_runtime_callbacks ()->debug_log (level, category, message);
6661 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6663 #if defined (HOST_WIN32)
6664 OutputDebugString (mono_string_chars (message));
6666 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6670 /* Only used for value types */
6671 ICALL_EXPORT MonoObject *
6672 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6677 domain = mono_object_domain (type);
6678 klass = mono_class_from_mono_type (type->type);
6679 mono_class_init_or_throw (klass);
6681 if (mono_class_is_nullable (klass))
6682 /* No arguments -> null */
6685 return mono_object_new (domain, klass);
6688 ICALL_EXPORT MonoReflectionMethod *
6689 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6691 MonoClass *klass, *parent;
6692 MonoGenericContext *generic_inst = NULL;
6693 MonoMethod *method = m->method;
6694 MonoMethod *result = NULL;
6697 if (method->klass == NULL)
6700 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6701 MONO_CLASS_IS_INTERFACE (method->klass) ||
6702 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6705 slot = mono_method_get_vtable_slot (method);
6709 klass = method->klass;
6710 if (klass->generic_class) {
6711 generic_inst = mono_class_get_context (klass);
6712 klass = klass->generic_class->container_class;
6716 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6717 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6718 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6719 or klass is the generic container class and generic_inst is the instantiation.
6721 when we go to the parent, if the parent is an open constructed type, we need to
6722 replace the type parameters by the definitions from the generic_inst, and then take it
6723 apart again into the klass and the generic_inst.
6725 For cases like this:
6726 class C<T> : B<T, int> {
6727 public override void Foo () { ... }
6729 class B<U,V> : A<HashMap<U,V>> {
6730 public override void Foo () { ... }
6733 public virtual void Foo () { ... }
6736 if at each iteration the parent isn't open, we can skip inflating it. if at some
6737 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6740 MonoGenericContext *parent_inst = NULL;
6741 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
6743 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
6744 mono_error_raise_exception(&error);
6746 if (parent->generic_class) {
6747 parent_inst = mono_class_get_context (parent);
6748 parent = parent->generic_class->container_class;
6751 mono_class_setup_vtable (parent);
6752 if (parent->vtable_size <= slot)
6755 generic_inst = parent_inst;
6758 klass = klass->parent;
6761 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
6763 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6764 mono_error_raise_exception(&error);
6766 generic_inst = NULL;
6768 if (klass->generic_class) {
6769 generic_inst = mono_class_get_context (klass);
6770 klass = klass->generic_class->container_class;
6777 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6778 mono_error_raise_exception(&error);
6781 if (klass == method->klass)
6784 /*This is possible if definition == FALSE.
6785 * Do it here to be really sure we don't read invalid memory.
6787 if (slot >= klass->vtable_size)
6790 mono_class_setup_vtable (klass);
6792 result = klass->vtable [slot];
6793 if (result == NULL) {
6794 /* It is an abstract method */
6795 gpointer iter = NULL;
6796 while ((result = mono_class_get_methods (klass, &iter)))
6797 if (result->slot == slot)
6804 return mono_method_get_object (mono_domain_get (), result, NULL);
6807 ICALL_EXPORT MonoString*
6808 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6810 MonoMethod *method = m->method;
6812 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6817 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6819 iter->sig = *(MonoMethodSignature**)argsp;
6821 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6822 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6825 /* FIXME: it's not documented what start is exactly... */
6829 iter->args = argsp + sizeof (gpointer);
6831 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6833 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6836 ICALL_EXPORT MonoTypedRef
6837 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6839 guint32 i, arg_size;
6843 i = iter->sig->sentinelpos + iter->next_arg;
6845 g_assert (i < iter->sig->param_count);
6847 res.type = iter->sig->params [i];
6848 res.klass = mono_class_from_mono_type (res.type);
6849 arg_size = mono_type_stack_size (res.type, &align);
6850 #if defined(__arm__) || defined(__mips__)
6851 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6853 res.value = iter->args;
6854 #if defined(__native_client__) && SIZEOF_REGISTER == 8
6855 /* Values are stored as 8 byte register sized objects, but 'value'
6856 * is dereferenced as a pointer in other routines.
6858 res.value = (char*)res.value + 4;
6860 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6861 if (arg_size <= sizeof (gpointer)) {
6863 int padding = arg_size - mono_type_size (res.type, &dummy);
6864 res.value = (guint8*)res.value + padding;
6867 iter->args = (char*)iter->args + arg_size;
6870 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6875 ICALL_EXPORT MonoTypedRef
6876 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6878 guint32 i, arg_size;
6882 i = iter->sig->sentinelpos + iter->next_arg;
6884 g_assert (i < iter->sig->param_count);
6886 while (i < iter->sig->param_count) {
6887 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6889 res.type = iter->sig->params [i];
6890 res.klass = mono_class_from_mono_type (res.type);
6891 /* FIXME: endianess issue... */
6892 arg_size = mono_type_stack_size (res.type, &align);
6893 #if defined(__arm__) || defined(__mips__)
6894 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6896 res.value = iter->args;
6897 iter->args = (char*)iter->args + arg_size;
6899 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6902 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6910 ICALL_EXPORT MonoType*
6911 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6915 i = iter->sig->sentinelpos + iter->next_arg;
6917 g_assert (i < iter->sig->param_count);
6919 return iter->sig->params [i];
6922 ICALL_EXPORT MonoObject*
6923 mono_TypedReference_ToObject (MonoTypedRef* tref)
6925 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
6926 MonoObject** objp = (MonoObject **)tref->value;
6930 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
6933 ICALL_EXPORT MonoTypedRef
6934 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
6937 MonoReflectionField *f;
6939 MonoType *ftype = NULL;
6943 memset (&res, 0, sizeof (res));
6946 g_assert (mono_array_length (fields) > 0);
6948 klass = target->vtable->klass;
6950 for (i = 0; i < mono_array_length (fields); ++i) {
6951 f = mono_array_get (fields, MonoReflectionField*, i);
6953 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
6956 if (f->field->parent != klass) {
6957 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
6961 p = (guint8*)target + f->field->offset;
6963 p += f->field->offset - sizeof (MonoObject);
6964 klass = mono_class_from_mono_type (f->field->type);
6965 ftype = f->field->type;
6969 res.klass = mono_class_from_mono_type (ftype);
6976 prelink_method (MonoMethod *method)
6978 const char *exc_class, *exc_arg;
6979 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6981 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6983 mono_raise_exception(
6984 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6986 /* create the wrapper, too? */
6990 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6992 prelink_method (method->method);
6996 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6998 MonoClass *klass = mono_class_from_mono_type (type->type);
7000 gpointer iter = NULL;
7002 mono_class_init_or_throw (klass);
7004 while ((m = mono_class_get_methods (klass, &iter)))
7008 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7010 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7011 gint32 const **exponents,
7012 gunichar2 const **digitLowerTable,
7013 gunichar2 const **digitUpperTable,
7014 gint64 const **tenPowersList,
7015 gint32 const **decHexDigits)
7017 *mantissas = Formatter_MantissaBitsTable;
7018 *exponents = Formatter_TensExponentTable;
7019 *digitLowerTable = Formatter_DigitLowerTable;
7020 *digitUpperTable = Formatter_DigitUpperTable;
7021 *tenPowersList = Formatter_TenPowersList;
7022 *decHexDigits = Formatter_DecHexDigits;
7026 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7027 * and avoid useless allocations.
7032 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7036 for (i = 0; i < type->num_mods; ++i) {
7037 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7042 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7044 for (i = 0; i < type->num_mods; ++i) {
7045 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7047 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7048 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7049 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7056 ICALL_EXPORT MonoArray*
7057 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7059 MonoType *type = param->ClassImpl->type;
7060 MonoClass *member_class = mono_object_class (param->MemberImpl);
7061 MonoMethod *method = NULL;
7064 MonoMethodSignature *sig;
7066 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7067 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7068 method = rmethod->method;
7069 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7070 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7071 if (!(method = prop->property->get))
7072 method = prop->property->set;
7075 char *type_name = mono_type_get_full_name (member_class);
7076 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7077 MonoException *ex = mono_get_exception_not_supported (msg);
7080 mono_set_pending_exception (ex);
7084 image = method->klass->image;
7085 pos = param->PositionImpl;
7086 sig = mono_method_signature (method);
7090 type = sig->params [pos];
7092 return type_array_from_modifiers (image, type, optional);
7096 get_property_type (MonoProperty *prop)
7098 MonoMethodSignature *sig;
7100 sig = mono_method_signature (prop->get);
7102 } else if (prop->set) {
7103 sig = mono_method_signature (prop->set);
7104 return sig->params [sig->param_count - 1];
7109 ICALL_EXPORT MonoArray*
7110 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7112 MonoType *type = get_property_type (property->property);
7113 MonoImage *image = property->klass->image;
7117 return type_array_from_modifiers (image, type, optional);
7121 *Construct a MonoType suited to be used to decode a constant blob object.
7123 * @type is the target type which will be constructed
7124 * @blob_type is the blob type, for example, that comes from the constant table
7125 * @real_type is the expected constructed type.
7128 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7130 type->type = blob_type;
7131 type->data.klass = NULL;
7132 if (blob_type == MONO_TYPE_CLASS)
7133 type->data.klass = mono_defaults.object_class;
7134 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7135 /* For enums, we need to use the base type */
7136 type->type = MONO_TYPE_VALUETYPE;
7137 type->data.klass = mono_class_from_mono_type (real_type);
7139 type->data.klass = mono_class_from_mono_type (real_type);
7142 ICALL_EXPORT MonoObject*
7143 property_info_get_default_value (MonoReflectionProperty *property)
7146 MonoProperty *prop = property->property;
7147 MonoType *type = get_property_type (prop);
7148 MonoDomain *domain = mono_object_domain (property);
7149 MonoTypeEnum def_type;
7150 const char *def_value;
7153 mono_class_init (prop->parent);
7155 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7156 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7160 def_value = mono_class_get_property_default_value (prop, &def_type);
7162 mono_type_from_blob_type (&blob_type, def_type, type);
7163 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7168 ICALL_EXPORT MonoBoolean
7169 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7171 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7172 MonoCustomAttrInfo *cinfo;
7175 mono_class_init_or_throw (attr_class);
7177 cinfo = mono_reflection_get_custom_attrs_info (obj);
7180 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7182 mono_custom_attrs_free (cinfo);
7186 ICALL_EXPORT MonoArray*
7187 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7189 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7194 mono_class_init_or_throw (attr_class);
7196 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7197 mono_error_raise_exception (&error);
7199 if (mono_loader_get_last_error ()) {
7200 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7207 ICALL_EXPORT MonoString*
7208 ves_icall_Mono_Runtime_GetDisplayName (void)
7211 MonoString *display_name;
7213 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7214 display_name = mono_string_new (mono_domain_get (), info);
7216 return display_name;
7219 ICALL_EXPORT MonoString*
7220 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7222 MonoString *message;
7226 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7227 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7230 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7232 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7239 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7242 char *path_str = mono_string_to_utf8 (path);
7244 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7252 #ifndef DISABLE_ICALL_TABLES
7254 #define ICALL_TYPE(id,name,first)
7255 #define ICALL(id,name,func) Icall_ ## id,
7258 #include "metadata/icall-def.h"
7264 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7265 #define ICALL(id,name,func)
7267 #include "metadata/icall-def.h"
7273 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7274 #define ICALL(id,name,func)
7276 guint16 first_icall;
7279 static const IcallTypeDesc
7280 icall_type_descs [] = {
7281 #include "metadata/icall-def.h"
7285 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7288 #define ICALL_TYPE(id,name,first)
7291 #ifdef HAVE_ARRAY_ELEM_INIT
7292 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7293 #define MSGSTRFIELD1(line) str##line
7295 static const struct msgstrtn_t {
7296 #define ICALL(id,name,func)
7298 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7299 #include "metadata/icall-def.h"
7301 } icall_type_names_str = {
7302 #define ICALL_TYPE(id,name,first) (name),
7303 #include "metadata/icall-def.h"
7306 static const guint16 icall_type_names_idx [] = {
7307 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7308 #include "metadata/icall-def.h"
7311 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7313 static const struct msgstr_t {
7315 #define ICALL_TYPE(id,name,first)
7316 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7317 #include "metadata/icall-def.h"
7319 } icall_names_str = {
7320 #define ICALL(id,name,func) (name),
7321 #include "metadata/icall-def.h"
7324 static const guint16 icall_names_idx [] = {
7325 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7326 #include "metadata/icall-def.h"
7329 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7335 #define ICALL_TYPE(id,name,first) name,
7336 #define ICALL(id,name,func)
7337 static const char* const
7338 icall_type_names [] = {
7339 #include "metadata/icall-def.h"
7343 #define icall_type_name_get(id) (icall_type_names [(id)])
7347 #define ICALL_TYPE(id,name,first)
7348 #define ICALL(id,name,func) name,
7349 static const char* const
7351 #include "metadata/icall-def.h"
7354 #define icall_name_get(id) icall_names [(id)]
7356 #endif /* !HAVE_ARRAY_ELEM_INIT */
7360 #define ICALL_TYPE(id,name,first)
7361 #define ICALL(id,name,func) func,
7362 static const gconstpointer
7363 icall_functions [] = {
7364 #include "metadata/icall-def.h"
7368 #ifdef ENABLE_ICALL_SYMBOL_MAP
7371 #define ICALL_TYPE(id,name,first)
7372 #define ICALL(id,name,func) #func,
7373 static const gconstpointer
7374 icall_symbols [] = {
7375 #include "metadata/icall-def.h"
7380 #endif /* DISABLE_ICALL_TABLES */
7382 static mono_mutex_t icall_mutex;
7383 static GHashTable *icall_hash = NULL;
7384 static GHashTable *jit_icall_hash_name = NULL;
7385 static GHashTable *jit_icall_hash_addr = NULL;
7388 mono_icall_init (void)
7390 #ifndef DISABLE_ICALL_TABLES
7393 /* check that tables are sorted: disable in release */
7396 const char *prev_class = NULL;
7397 const char *prev_method;
7399 for (i = 0; i < Icall_type_num; ++i) {
7400 const IcallTypeDesc *desc;
7403 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7404 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7405 prev_class = icall_type_name_get (i);
7406 desc = &icall_type_descs [i];
7407 num_icalls = icall_desc_num_icalls (desc);
7408 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7409 for (j = 0; j < num_icalls; ++j) {
7410 const char *methodn = icall_name_get (desc->first_icall + j);
7411 if (prev_method && strcmp (prev_method, methodn) >= 0)
7412 g_print ("method %s should come before method %s\n", methodn, prev_method);
7413 prev_method = methodn;
7419 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7420 mono_os_mutex_init (&icall_mutex);
7424 mono_icall_lock (void)
7426 mono_locks_os_acquire (&icall_mutex, IcallLock);
7430 mono_icall_unlock (void)
7432 mono_locks_os_release (&icall_mutex, IcallLock);
7436 mono_icall_cleanup (void)
7438 g_hash_table_destroy (icall_hash);
7439 g_hash_table_destroy (jit_icall_hash_name);
7440 g_hash_table_destroy (jit_icall_hash_addr);
7441 mono_os_mutex_destroy (&icall_mutex);
7445 mono_add_internal_call (const char *name, gconstpointer method)
7449 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7451 mono_icall_unlock ();
7454 #ifndef DISABLE_ICALL_TABLES
7456 #ifdef HAVE_ARRAY_ELEM_INIT
7458 compare_method_imap (const void *key, const void *elem)
7460 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7461 return strcmp (key, method_name);
7465 find_method_icall (const IcallTypeDesc *imap, const char *name)
7467 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);
7470 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7474 compare_class_imap (const void *key, const void *elem)
7476 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7477 return strcmp (key, class_name);
7480 static const IcallTypeDesc*
7481 find_class_icalls (const char *name)
7483 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);
7486 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7489 #else /* HAVE_ARRAY_ELEM_INIT */
7492 compare_method_imap (const void *key, const void *elem)
7494 const char** method_name = (const char**)elem;
7495 return strcmp (key, *method_name);
7499 find_method_icall (const IcallTypeDesc *imap, const char *name)
7501 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7504 return (gpointer)icall_functions [(nameslot - icall_names)];
7508 compare_class_imap (const void *key, const void *elem)
7510 const char** class_name = (const char**)elem;
7511 return strcmp (key, *class_name);
7514 static const IcallTypeDesc*
7515 find_class_icalls (const char *name)
7517 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7520 return &icall_type_descs [nameslot - icall_type_names];
7523 #endif /* HAVE_ARRAY_ELEM_INIT */
7525 #endif /* DISABLE_ICALL_TABLES */
7528 * we should probably export this as an helper (handle nested types).
7529 * Returns the number of chars written in buf.
7532 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7534 int nspacelen, cnamelen;
7535 nspacelen = strlen (klass->name_space);
7536 cnamelen = strlen (klass->name);
7537 if (nspacelen + cnamelen + 2 > bufsize)
7540 memcpy (buf, klass->name_space, nspacelen);
7541 buf [nspacelen ++] = '.';
7543 memcpy (buf + nspacelen, klass->name, cnamelen);
7544 buf [nspacelen + cnamelen] = 0;
7545 return nspacelen + cnamelen;
7548 #ifdef DISABLE_ICALL_TABLES
7550 no_icall_table (void)
7552 g_assert_not_reached ();
7557 mono_lookup_internal_call (MonoMethod *method)
7562 int typelen = 0, mlen, siglen;
7564 #ifndef DISABLE_ICALL_TABLES
7565 const IcallTypeDesc *imap = NULL;
7568 g_assert (method != NULL);
7570 if (method->is_inflated)
7571 method = ((MonoMethodInflated *) method)->declaring;
7573 if (method->klass->nested_in) {
7574 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7578 mname [pos++] = '/';
7581 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7587 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7592 #ifndef DISABLE_ICALL_TABLES
7593 imap = find_class_icalls (mname);
7596 mname [typelen] = ':';
7597 mname [typelen + 1] = ':';
7599 mlen = strlen (method->name);
7600 memcpy (mname + typelen + 2, method->name, mlen);
7601 sigstart = mname + typelen + 2 + mlen;
7604 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7605 siglen = strlen (tmpsig);
7606 if (typelen + mlen + siglen + 6 > sizeof (mname))
7609 memcpy (sigstart + 1, tmpsig, siglen);
7610 sigstart [siglen + 1] = ')';
7611 sigstart [siglen + 2] = 0;
7616 res = g_hash_table_lookup (icall_hash, mname);
7618 mono_icall_unlock ();;
7621 /* try without signature */
7623 res = g_hash_table_lookup (icall_hash, mname);
7625 mono_icall_unlock ();
7629 #ifdef DISABLE_ICALL_TABLES
7630 mono_icall_unlock ();
7631 /* Fail only when the result is actually used */
7632 /* mono_marshal_get_native_wrapper () depends on this */
7633 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
7634 return ves_icall_System_String_ctor_RedirectToCreateString;
7636 return no_icall_table;
7638 /* it wasn't found in the static call tables */
7640 mono_icall_unlock ();
7643 res = find_method_icall (imap, sigstart - mlen);
7645 mono_icall_unlock ();
7648 /* try _with_ signature */
7650 res = find_method_icall (imap, sigstart - mlen);
7652 mono_icall_unlock ();
7656 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7657 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7658 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7659 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
7660 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");
7661 g_print ("If you see other errors or faults after this message they are probably related\n");
7662 g_print ("and you need to fix your mono install first.\n");
7664 mono_icall_unlock ();
7670 #ifdef ENABLE_ICALL_SYMBOL_MAP
7672 func_cmp (gconstpointer key, gconstpointer p)
7674 return (gsize)key - (gsize)*(gsize*)p;
7679 * mono_lookup_icall_symbol:
7681 * Given the icall METHOD, returns its C symbol.
7684 mono_lookup_icall_symbol (MonoMethod *m)
7686 #ifdef DISABLE_ICALL_TABLES
7687 g_assert_not_reached ();
7690 #ifdef ENABLE_ICALL_SYMBOL_MAP
7694 static gconstpointer *functions_sorted;
7695 static const char**symbols_sorted;
7696 static gboolean inited;
7701 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7702 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7703 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7704 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7705 /* Bubble sort the two arrays */
7709 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
7710 if (functions_sorted [i] > functions_sorted [i + 1]) {
7713 tmp = functions_sorted [i];
7714 functions_sorted [i] = functions_sorted [i + 1];
7715 functions_sorted [i + 1] = tmp;
7716 tmp = symbols_sorted [i];
7717 symbols_sorted [i] = symbols_sorted [i + 1];
7718 symbols_sorted [i + 1] = tmp;
7725 func = mono_lookup_internal_call (m);
7728 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
7732 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
7734 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
7735 g_assert_not_reached ();
7742 type_from_typename (char *type_name)
7744 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7746 if (!strcmp (type_name, "int"))
7747 klass = mono_defaults.int_class;
7748 else if (!strcmp (type_name, "ptr"))
7749 klass = mono_defaults.int_class;
7750 else if (!strcmp (type_name, "void"))
7751 klass = mono_defaults.void_class;
7752 else if (!strcmp (type_name, "int32"))
7753 klass = mono_defaults.int32_class;
7754 else if (!strcmp (type_name, "uint32"))
7755 klass = mono_defaults.uint32_class;
7756 else if (!strcmp (type_name, "int8"))
7757 klass = mono_defaults.sbyte_class;
7758 else if (!strcmp (type_name, "uint8"))
7759 klass = mono_defaults.byte_class;
7760 else if (!strcmp (type_name, "int16"))
7761 klass = mono_defaults.int16_class;
7762 else if (!strcmp (type_name, "uint16"))
7763 klass = mono_defaults.uint16_class;
7764 else if (!strcmp (type_name, "long"))
7765 klass = mono_defaults.int64_class;
7766 else if (!strcmp (type_name, "ulong"))
7767 klass = mono_defaults.uint64_class;
7768 else if (!strcmp (type_name, "float"))
7769 klass = mono_defaults.single_class;
7770 else if (!strcmp (type_name, "double"))
7771 klass = mono_defaults.double_class;
7772 else if (!strcmp (type_name, "object"))
7773 klass = mono_defaults.object_class;
7774 else if (!strcmp (type_name, "obj"))
7775 klass = mono_defaults.object_class;
7776 else if (!strcmp (type_name, "string"))
7777 klass = mono_defaults.string_class;
7778 else if (!strcmp (type_name, "bool"))
7779 klass = mono_defaults.boolean_class;
7780 else if (!strcmp (type_name, "boolean"))
7781 klass = mono_defaults.boolean_class;
7783 g_error ("%s", type_name);
7784 g_assert_not_reached ();
7786 return &klass->byval_arg;
7790 * LOCKING: Take the corlib image lock.
7792 MonoMethodSignature*
7793 mono_create_icall_signature (const char *sigstr)
7798 MonoMethodSignature *res, *res2;
7799 MonoImage *corlib = mono_defaults.corlib;
7801 mono_image_lock (corlib);
7802 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7803 mono_image_unlock (corlib);
7808 parts = g_strsplit (sigstr, " ", 256);
7817 res = mono_metadata_signature_alloc (corlib, len - 1);
7822 * Under windows, the default pinvoke calling convention is STDCALL but
7825 res->call_convention = MONO_CALL_C;
7828 res->ret = type_from_typename (parts [0]);
7829 for (i = 1; i < len; ++i) {
7830 res->params [i - 1] = type_from_typename (parts [i]);
7835 mono_image_lock (corlib);
7836 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7838 res = res2; /*Value is allocated in the image pool*/
7840 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
7841 mono_image_unlock (corlib);
7847 mono_find_jit_icall_by_name (const char *name)
7849 MonoJitICallInfo *info;
7850 g_assert (jit_icall_hash_name);
7853 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7854 mono_icall_unlock ();
7859 mono_find_jit_icall_by_addr (gconstpointer addr)
7861 MonoJitICallInfo *info;
7862 g_assert (jit_icall_hash_addr);
7865 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7866 mono_icall_unlock ();
7872 * mono_get_jit_icall_info:
7874 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7875 * caller should access it while holding the icall lock.
7878 mono_get_jit_icall_info (void)
7880 return jit_icall_hash_name;
7884 * mono_lookup_jit_icall_symbol:
7886 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
7889 mono_lookup_jit_icall_symbol (const char *name)
7891 MonoJitICallInfo *info;
7892 const char *res = NULL;
7895 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7897 res = info->c_symbol;
7898 mono_icall_unlock ();
7903 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7906 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7907 mono_icall_unlock ();
7911 * 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
7912 * icalls without wrappers in some cases.
7915 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
7917 MonoJitICallInfo *info;
7924 if (!jit_icall_hash_name) {
7925 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7926 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7929 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7930 g_warning ("jit icall already defined \"%s\"\n", name);
7931 g_assert_not_reached ();
7934 info = g_new0 (MonoJitICallInfo, 1);
7939 info->c_symbol = c_symbol;
7940 info->no_raise = no_raise;
7943 info->wrapper = func;
7945 info->wrapper = NULL;
7948 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7949 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7951 mono_icall_unlock ();
7956 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7958 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);