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)
522 MonoClass *aklass, *klass;
525 gboolean bounded = FALSE;
527 MONO_CHECK_ARG_NULL (type, NULL);
528 MONO_CHECK_ARG_NULL (lengths, NULL);
530 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
532 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
534 for (i = 0; i < mono_array_length (lengths); i++) {
535 if (mono_array_get (lengths, gint32, i) < 0) {
536 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
541 klass = mono_class_from_mono_type (type->type);
542 mono_class_init_or_throw (klass);
544 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
545 /* vectors are not the same as one dimensional arrays with no-zero bounds */
550 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
552 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
553 for (i = 0; i < aklass->rank; ++i) {
554 sizes [i] = mono_array_get (lengths, guint32, i);
556 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
558 sizes [i + aklass->rank] = 0;
561 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
566 ICALL_EXPORT MonoArray *
567 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
569 MonoClass *aklass, *klass;
572 gboolean bounded = FALSE;
574 MONO_CHECK_ARG_NULL (type, NULL);
575 MONO_CHECK_ARG_NULL (lengths, NULL);
577 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
579 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
581 for (i = 0; i < mono_array_length (lengths); i++) {
582 if ((mono_array_get (lengths, gint64, i) < 0) ||
583 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
584 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
589 klass = mono_class_from_mono_type (type->type);
590 mono_class_init_or_throw (klass);
592 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
593 /* vectors are not the same as one dimensional arrays with no-zero bounds */
598 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
600 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
601 for (i = 0; i < aklass->rank; ++i) {
602 sizes [i] = mono_array_get (lengths, guint64, i);
604 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
606 sizes [i + aklass->rank] = 0;
609 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
615 ves_icall_System_Array_GetRank (MonoObject *arr)
617 return arr->vtable->klass->rank;
621 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
623 gint32 rank = arr->obj.vtable->klass->rank;
626 if ((dimension < 0) || (dimension >= rank)) {
627 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
631 if (arr->bounds == NULL)
632 length = arr->max_length;
634 length = arr->bounds [dimension].length;
636 #ifdef MONO_BIG_ARRAYS
637 if (length > G_MAXINT32) {
638 mono_set_pending_exception (mono_get_exception_overflow ());
646 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
648 gint32 rank = arr->obj.vtable->klass->rank;
650 if ((dimension < 0) || (dimension >= rank)) {
651 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
655 if (arr->bounds == NULL)
656 return arr->max_length;
658 return arr->bounds [dimension].length;
662 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
664 gint32 rank = arr->obj.vtable->klass->rank;
666 if ((dimension < 0) || (dimension >= rank)) {
667 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
671 if (arr->bounds == NULL)
674 return arr->bounds [dimension].lower_bound;
678 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
680 int sz = mono_array_element_size (mono_object_class (arr));
681 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
684 ICALL_EXPORT gboolean
685 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
690 MonoVTable *src_vtable;
691 MonoVTable *dest_vtable;
692 MonoClass *src_class;
693 MonoClass *dest_class;
695 src_vtable = source->obj.vtable;
696 dest_vtable = dest->obj.vtable;
698 if (src_vtable->rank != dest_vtable->rank)
701 if (source->bounds || dest->bounds)
704 /* there's no integer overflow since mono_array_length returns an unsigned integer */
705 if ((dest_idx + length > mono_array_length_fast (dest)) ||
706 (source_idx + length > mono_array_length_fast (source)))
709 src_class = src_vtable->klass->element_class;
710 dest_class = dest_vtable->klass->element_class;
713 * Handle common cases.
716 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
717 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
719 if (src_class == mono_defaults.object_class && dest_class->valuetype)
722 /* Check if we're copying a char[] <==> (u)short[] */
723 if (src_class != dest_class) {
724 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
727 /* 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. */
728 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
732 if (dest_class->valuetype) {
733 element_size = mono_array_element_size (source->obj.vtable->klass);
734 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
735 if (dest_class->has_references) {
736 mono_value_copy_array (dest, dest_idx, source_addr, length);
738 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
739 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
742 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
749 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
755 ac = (MonoClass *)arr->obj.vtable->klass;
757 esize = mono_array_element_size (ac);
758 ea = (gpointer*)((char*)arr->vector + (pos * esize));
760 mono_gc_memmove_atomic (value, ea, esize);
764 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
770 ac = (MonoClass *)arr->obj.vtable->klass;
771 ec = ac->element_class;
773 esize = mono_array_element_size (ac);
774 ea = (gpointer*)((char*)arr->vector + (pos * esize));
776 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
777 g_assert (esize == sizeof (gpointer));
778 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
780 g_assert (ec->inited);
781 g_assert (esize == mono_class_value_size (ec, NULL));
782 if (ec->has_references)
783 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
785 mono_gc_memmove_atomic (ea, value, esize);
790 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
792 MonoClass *klass = array->obj.vtable->klass;
793 guint32 size = mono_array_element_size (klass);
794 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
796 const char *field_data;
798 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
799 MonoException *exc = mono_get_exception_argument("array",
800 "Cannot initialize array of non-primitive type.");
801 mono_set_pending_exception (exc);
805 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
806 MonoException *exc = mono_get_exception_argument("field_handle",
807 "Field doesn't have an RVA");
808 mono_set_pending_exception (exc);
812 size *= array->max_length;
813 field_data = mono_field_get_data (field_handle);
815 if (size > mono_type_size (field_handle->type, &align)) {
816 MonoException *exc = mono_get_exception_argument("field_handle",
817 "Field not large enough to fill array");
818 mono_set_pending_exception (exc);
822 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
824 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
825 guint ## n *src = (guint ## n *) field_data; \
827 nEnt = (size / sizeof(guint ## n)); \
829 for (i = 0; i < nEnt; i++) { \
830 data[i] = read ## n (&src[i]); \
834 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
836 switch (type->type) {
853 memcpy (mono_array_addr (array, char, 0), field_data, size);
857 memcpy (mono_array_addr (array, char, 0), field_data, size);
862 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
864 return offsetof (MonoString, chars);
867 ICALL_EXPORT MonoObject *
868 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
870 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
873 return mono_object_clone (obj);
877 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
882 MONO_CHECK_ARG_NULL (handle,);
884 klass = mono_class_from_mono_type (handle);
885 MONO_CHECK_ARG (handle, klass,);
887 if (klass->generic_container)
890 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
892 /* This will call the type constructor */
893 mono_runtime_class_init (vtable);
897 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
901 mono_image_check_for_module_cctor (image);
902 if (image->has_module_cctor) {
903 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
904 mono_error_raise_exception (&error);
905 /*It's fine to raise the exception here*/
906 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
910 ICALL_EXPORT MonoBoolean
911 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
916 /* later make this configurable and per-arch */
917 int min_size = 4096 * 4 * sizeof (void*);
918 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
919 /* if we have no info we are optimistic and assume there is enough room */
923 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
927 current = (guint8 *)&stack_addr;
928 if (current > stack_addr) {
929 if ((current - stack_addr) < min_size)
932 if (current - (stack_addr - stack_size) < min_size)
938 ICALL_EXPORT MonoObject *
939 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
941 return mono_object_clone (this_obj);
945 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
948 MonoObject **values = NULL;
951 gint32 result = (int)(gsize)mono_defaults.int32_class;
952 MonoClassField* field;
955 klass = mono_object_class (this_obj);
957 if (mono_class_num_fields (klass) == 0)
961 * Compute the starting value of the hashcode for fields of primitive
962 * types, and return the remaining fields in an array to the managed side.
963 * This way, we can avoid costly reflection operations in managed code.
966 while ((field = mono_class_get_fields (klass, &iter))) {
967 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
969 if (mono_field_is_deleted (field))
971 /* FIXME: Add more types */
972 switch (field->type->type) {
974 result ^= *(gint32*)((guint8*)this_obj + field->offset);
976 case MONO_TYPE_STRING: {
978 s = *(MonoString**)((guint8*)this_obj + field->offset);
980 result ^= mono_string_hash (s);
985 values = g_newa (MonoObject*, mono_class_num_fields (klass));
986 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
987 values [count++] = o;
993 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
994 for (i = 0; i < count; ++i)
995 mono_array_setref (*fields, i, values [i]);
1002 ICALL_EXPORT MonoBoolean
1003 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1006 MonoObject **values = NULL;
1008 MonoClassField* field;
1012 MONO_CHECK_ARG_NULL (that, FALSE);
1014 if (this_obj->vtable != that->vtable)
1017 klass = mono_object_class (this_obj);
1019 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1020 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1023 * Do the comparison for fields of primitive type and return a result if
1024 * possible. Otherwise, return the remaining fields in an array to the
1025 * managed side. This way, we can avoid costly reflection operations in
1030 while ((field = mono_class_get_fields (klass, &iter))) {
1031 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1033 if (mono_field_is_deleted (field))
1035 /* FIXME: Add more types */
1036 switch (field->type->type) {
1039 case MONO_TYPE_BOOLEAN:
1040 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1045 case MONO_TYPE_CHAR:
1046 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1051 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1056 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1060 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1064 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1069 case MONO_TYPE_STRING: {
1070 MonoString *s1, *s2;
1071 guint32 s1len, s2len;
1072 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1073 s2 = *(MonoString**)((guint8*)that + field->offset);
1076 if ((s1 == NULL) || (s2 == NULL))
1078 s1len = mono_string_length (s1);
1079 s2len = mono_string_length (s2);
1083 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1089 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1090 o = mono_field_get_value_object (mono_object_domain (this_obj), field, this_obj);
1091 values [count++] = o;
1092 o = mono_field_get_value_object (mono_object_domain (this_obj), field, that);
1093 values [count++] = o;
1096 if (klass->enumtype)
1097 /* enums only have one non-static field */
1103 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1104 for (i = 0; i < count; ++i)
1105 mono_array_setref_fast (*fields, i, values [i]);
1112 ICALL_EXPORT MonoReflectionType *
1113 ves_icall_System_Object_GetType (MonoObject *obj)
1115 #ifndef DISABLE_REMOTING
1116 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1117 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1120 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1124 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1126 mtype->type = &obj->vtable->klass->byval_arg;
1127 g_assert (mtype->type->type);
1131 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1133 MONO_CHECK_ARG_NULL (obj, 0);
1135 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1139 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1140 MonoReflectionMethod *method,
1141 MonoArray *opt_param_types)
1143 MONO_CHECK_ARG_NULL (method, 0);
1145 return mono_image_create_method_token (
1146 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1150 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1152 mono_image_create_pefile (mb, file);
1156 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1158 mono_image_build_metadata (mb);
1162 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1164 mono_image_register_token (mb->dynamic_image, token, obj);
1167 ICALL_EXPORT MonoObject*
1168 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1172 mono_loader_lock ();
1173 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1174 mono_loader_unlock ();
1180 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1182 MonoMethod **dest = (MonoMethod **)data;
1184 /* skip unmanaged frames */
1200 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1202 MonoMethod **dest = (MonoMethod **)data;
1204 /* skip unmanaged frames */
1209 if (!strcmp (m->klass->name_space, "System.Reflection"))
1218 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1220 MonoMethod **dest = (MonoMethod **)data;
1222 /* skip unmanaged frames */
1226 if (m->wrapper_type != MONO_WRAPPER_NONE)
1229 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1243 static MonoReflectionType *
1244 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase)
1246 MonoMethod *m, *dest;
1248 MonoType *type = NULL;
1249 MonoAssembly *assembly = NULL;
1250 gboolean type_resolve = FALSE;
1253 * We must compute the calling assembly as type loading must happen under a metadata context.
1254 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1255 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1257 m = mono_method_get_last_managed ();
1260 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1265 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1266 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1267 * to crash. This only seems to happen in some strange remoting
1268 * scenarios and I was unable to figure out what's happening there.
1269 * Dec 10, 2005 - Martin.
1273 assembly = dest->klass->image->assembly;
1274 type_resolve = TRUE;
1276 g_warning (G_STRLOC);
1279 if (info->assembly.name)
1280 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1284 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1285 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1288 if (!info->assembly.name && !type) /* try mscorlib */
1289 type = mono_reflection_get_type (NULL, info, ignoreCase, &type_resolve);
1291 if (assembly && !type && type_resolve) {
1292 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1293 type = mono_reflection_get_type (assembly->image, info, ignoreCase, &type_resolve);
1299 return mono_type_get_object (mono_domain_get (), type);
1303 MonoReflectionType *
1304 mono_type_get (const char *str)
1306 char *copy = g_strdup (str);
1307 MonoTypeNameParse info;
1308 MonoReflectionType *type;
1311 parsedOk = mono_reflection_parse_type(copy, &info);
1313 mono_reflection_free_type_info (&info);
1318 type = type_from_parsed_name (&info, FALSE);
1320 mono_reflection_free_type_info (&info);
1327 ICALL_EXPORT MonoReflectionType*
1328 ves_icall_type_from_name (MonoString *name,
1329 MonoBoolean throwOnError,
1330 MonoBoolean ignoreCase)
1332 char *str = mono_string_to_utf8 (name);
1333 MonoTypeNameParse info;
1334 MonoReflectionType *type;
1337 parsedOk = mono_reflection_parse_type (str, &info);
1339 /* mono_reflection_parse_type() mangles the string */
1341 mono_reflection_free_type_info (&info);
1344 mono_set_pending_exception(mono_get_exception_argument("typeName", "failed parse"));
1349 type = type_from_parsed_name (&info, ignoreCase);
1351 mono_reflection_free_type_info (&info);
1355 MonoException *e = NULL;
1358 e = mono_get_exception_type_load (name, NULL);
1360 mono_loader_clear_error ();
1362 mono_set_pending_exception (e);
1371 ICALL_EXPORT MonoReflectionType*
1372 ves_icall_type_from_handle (MonoType *handle)
1374 MonoDomain *domain = mono_domain_get ();
1376 return mono_type_get_object (domain, handle);
1379 /* System.TypeCode */
1398 TYPECODE_STRING = 18
1401 ICALL_EXPORT guint32
1402 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1404 int t = type->type->type;
1406 if (type->type->byref)
1407 return TYPECODE_OBJECT;
1411 case MONO_TYPE_VOID:
1412 return TYPECODE_OBJECT;
1413 case MONO_TYPE_BOOLEAN:
1414 return TYPECODE_BOOLEAN;
1416 return TYPECODE_BYTE;
1418 return TYPECODE_SBYTE;
1420 return TYPECODE_UINT16;
1422 return TYPECODE_INT16;
1423 case MONO_TYPE_CHAR:
1424 return TYPECODE_CHAR;
1428 return TYPECODE_OBJECT;
1430 return TYPECODE_UINT32;
1432 return TYPECODE_INT32;
1434 return TYPECODE_UINT64;
1436 return TYPECODE_INT64;
1438 return TYPECODE_SINGLE;
1440 return TYPECODE_DOUBLE;
1441 case MONO_TYPE_VALUETYPE: {
1442 MonoClass *klass = type->type->data.klass;
1444 if (klass->enumtype) {
1445 t = mono_class_enum_basetype (klass)->type;
1447 } else if (mono_is_corlib_image (klass->image)) {
1448 if (strcmp (klass->name_space, "System") == 0) {
1449 if (strcmp (klass->name, "Decimal") == 0)
1450 return TYPECODE_DECIMAL;
1451 else if (strcmp (klass->name, "DateTime") == 0)
1452 return TYPECODE_DATETIME;
1455 return TYPECODE_OBJECT;
1457 case MONO_TYPE_STRING:
1458 return TYPECODE_STRING;
1459 case MONO_TYPE_SZARRAY:
1460 case MONO_TYPE_ARRAY:
1461 case MONO_TYPE_OBJECT:
1463 case MONO_TYPE_MVAR:
1464 case MONO_TYPE_TYPEDBYREF:
1465 return TYPECODE_OBJECT;
1466 case MONO_TYPE_CLASS:
1468 MonoClass *klass = type->type->data.klass;
1469 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1470 if (strcmp (klass->name, "DBNull") == 0)
1471 return TYPECODE_DBNULL;
1474 return TYPECODE_OBJECT;
1475 case MONO_TYPE_GENERICINST:
1476 return TYPECODE_OBJECT;
1478 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1484 mono_type_is_primitive (MonoType *type)
1486 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1487 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1491 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1493 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1494 return mono_class_enum_basetype (type->data.klass);
1495 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1496 return mono_class_enum_basetype (type->data.generic_class->container_class);
1500 ICALL_EXPORT guint32
1501 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1506 g_assert (type != NULL);
1508 klass = mono_class_from_mono_type (type->type);
1509 klassc = mono_class_from_mono_type (c->type);
1511 if (type->type->byref ^ c->type->byref)
1514 if (type->type->byref) {
1515 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1516 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1518 klass = mono_class_from_mono_type (t);
1519 klassc = mono_class_from_mono_type (ot);
1521 if (mono_type_is_primitive (t)) {
1522 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1523 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1524 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1525 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1526 return t->type == ot->type;
1528 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1531 if (klass->valuetype)
1532 return klass == klassc;
1533 return klass->valuetype == klassc->valuetype;
1536 return mono_class_is_assignable_from (klass, klassc);
1539 ICALL_EXPORT guint32
1540 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1542 MonoClass *klass = mono_class_from_mono_type (type->type);
1543 mono_class_init_or_throw (klass);
1544 return mono_object_isinst (obj, klass) != NULL;
1547 ICALL_EXPORT guint32
1548 ves_icall_get_attributes (MonoReflectionType *type)
1550 MonoClass *klass = mono_class_from_mono_type (type->type);
1551 return klass->flags;
1554 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1555 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1557 MonoClass *klass = field->field->parent;
1558 MonoMarshalType *info;
1562 if (klass->generic_container ||
1563 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1566 ftype = mono_field_get_type (field->field);
1567 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1570 info = mono_marshal_load_type_info (klass);
1572 for (i = 0; i < info->num_fields; ++i) {
1573 if (info->fields [i].field == field->field) {
1574 if (!info->fields [i].mspec)
1577 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1584 ICALL_EXPORT MonoReflectionField*
1585 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1587 gboolean found = FALSE;
1594 klass = handle->parent;
1596 klass = mono_class_from_mono_type (type);
1598 /* Check that the field belongs to the class */
1599 for (k = klass; k; k = k->parent) {
1600 if (k == handle->parent) {
1607 /* The managed code will throw the exception */
1611 return mono_field_get_object (mono_domain_get (), klass, handle);
1614 ICALL_EXPORT MonoArray*
1615 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1618 MonoType *type = mono_field_get_type_checked (field->field, &error);
1619 mono_error_raise_exception (&error);
1621 return type_array_from_modifiers (field->field->parent->image, type, optional);
1625 vell_icall_get_method_attributes (MonoMethod *method)
1627 return method->flags;
1631 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1634 MonoDomain *domain = mono_domain_get ();
1635 MonoMethodSignature* sig;
1637 sig = mono_method_signature_checked (method, &error);
1638 if (!mono_error_ok (&error))
1639 mono_error_raise_exception (&error);
1642 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1643 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1644 info->attrs = method->flags;
1645 info->implattrs = method->iflags;
1646 if (sig->call_convention == MONO_CALL_DEFAULT)
1647 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1649 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1654 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1657 ICALL_EXPORT MonoArray*
1658 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1660 MonoDomain *domain = mono_domain_get ();
1662 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1665 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1666 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1668 MonoDomain *domain = mono_domain_get ();
1669 MonoReflectionMarshalAsAttribute* res = NULL;
1670 MonoMarshalSpec **mspecs;
1673 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1674 mono_method_get_marshal_info (method, mspecs);
1677 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1679 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1681 mono_metadata_free_marshal_spec (mspecs [i]);
1688 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1690 MonoClass *parent = field->field->parent;
1691 if (!parent->size_inited)
1692 mono_class_init (parent);
1693 mono_class_setup_fields_locking (parent);
1695 return field->field->offset - sizeof (MonoObject);
1698 ICALL_EXPORT MonoReflectionType*
1699 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1703 parent = declaring? field->field->parent: field->klass;
1705 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1708 ICALL_EXPORT MonoObject *
1709 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1711 MonoClass *fklass = field->klass;
1712 MonoClassField *cf = field->field;
1713 MonoDomain *domain = mono_object_domain (field);
1715 if (fklass->image->assembly->ref_only) {
1716 mono_set_pending_exception (mono_get_exception_invalid_operation (
1717 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1721 if (mono_security_core_clr_enabled ())
1722 mono_security_core_clr_ensure_reflection_access_field (cf);
1724 return mono_field_get_value_object (domain, cf, obj);
1728 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1731 MonoClassField *cf = field->field;
1735 if (field->klass->image->assembly->ref_only) {
1736 mono_set_pending_exception (mono_get_exception_invalid_operation (
1737 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1741 if (mono_security_core_clr_enabled ())
1742 mono_security_core_clr_ensure_reflection_access_field (cf);
1744 type = mono_field_get_type_checked (cf, &error);
1745 if (!mono_error_ok (&error))
1746 mono_error_raise_exception (&error);
1748 v = (gchar *) value;
1750 switch (type->type) {
1753 case MONO_TYPE_BOOLEAN:
1756 case MONO_TYPE_CHAR:
1765 case MONO_TYPE_VALUETYPE:
1768 v += sizeof (MonoObject);
1770 case MONO_TYPE_STRING:
1771 case MONO_TYPE_OBJECT:
1772 case MONO_TYPE_CLASS:
1773 case MONO_TYPE_ARRAY:
1774 case MONO_TYPE_SZARRAY:
1777 case MONO_TYPE_GENERICINST: {
1778 MonoGenericClass *gclass = type->data.generic_class;
1779 g_assert (!gclass->context.class_inst->is_open);
1781 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1782 MonoClass *nklass = mono_class_from_mono_type (type);
1783 MonoObject *nullable;
1786 * Convert the boxed vtype into a Nullable structure.
1787 * This is complicated by the fact that Nullables have
1788 * a variable structure.
1790 nullable = mono_object_new (mono_domain_get (), nklass);
1792 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1794 v = (gchar *)mono_object_unbox (nullable);
1797 if (gclass->container_class->valuetype && (v != NULL))
1798 v += sizeof (MonoObject);
1802 g_error ("type 0x%x not handled in "
1803 "ves_icall_FieldInfo_SetValueInternal", type->type);
1808 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1809 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1810 if (!vtable->initialized)
1811 mono_runtime_class_init (vtable);
1812 mono_field_static_set_value (vtable, cf, v);
1814 mono_field_set_value (obj, cf, v);
1819 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1828 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1829 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1833 if (MONO_TYPE_IS_REFERENCE (f->type))
1834 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1836 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1839 ICALL_EXPORT MonoObject *
1840 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1842 MonoObject *o = NULL;
1843 MonoClassField *field = rfield->field;
1845 MonoDomain *domain = mono_object_domain (rfield);
1847 MonoTypeEnum def_type;
1848 const char *def_value;
1852 mono_class_init (field->parent);
1854 t = mono_field_get_type_checked (field, &error);
1855 if (!mono_error_ok (&error))
1856 mono_error_raise_exception (&error);
1858 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
1859 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1863 if (image_is_dynamic (field->parent->image)) {
1864 MonoClass *klass = field->parent;
1865 int fidx = field - klass->fields;
1867 g_assert (fidx >= 0 && fidx < klass->field.count);
1868 g_assert (klass->ext);
1869 g_assert (klass->ext->field_def_values);
1870 def_type = klass->ext->field_def_values [fidx].def_type;
1871 def_value = klass->ext->field_def_values [fidx].data;
1872 if (def_type == MONO_TYPE_END) {
1873 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1877 def_value = mono_class_get_field_default_value (field, &def_type);
1878 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1880 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
1885 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1889 case MONO_TYPE_BOOLEAN:
1892 case MONO_TYPE_CHAR:
1900 case MONO_TYPE_R8: {
1903 /* boxed value type */
1904 t = g_new0 (MonoType, 1);
1906 klass = mono_class_from_mono_type (t);
1908 o = mono_object_new (domain, klass);
1909 v = ((gchar *) o) + sizeof (MonoObject);
1910 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1913 case MONO_TYPE_STRING:
1914 case MONO_TYPE_CLASS:
1915 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1918 g_assert_not_reached ();
1924 ICALL_EXPORT MonoReflectionType*
1925 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1928 MonoClassField *field = ref_field->field;
1929 MonoType *type = mono_field_get_type_checked (field, &error);
1930 if (!mono_error_ok (&error))
1931 mono_error_raise_exception (&error);
1932 return mono_type_get_object (mono_object_domain (ref_field), type);
1935 /* From MonoProperty.cs */
1937 PInfo_Attributes = 1,
1938 PInfo_GetMethod = 1 << 1,
1939 PInfo_SetMethod = 1 << 2,
1940 PInfo_ReflectedType = 1 << 3,
1941 PInfo_DeclaringType = 1 << 4,
1946 ves_icall_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1948 MonoDomain *domain = mono_object_domain (property);
1949 const MonoProperty *pproperty = property->property;
1951 if ((req_info & PInfo_ReflectedType) != 0)
1952 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1953 if ((req_info & PInfo_DeclaringType) != 0)
1954 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &pproperty->parent->byval_arg));
1956 if ((req_info & PInfo_Name) != 0)
1957 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
1959 if ((req_info & PInfo_Attributes) != 0)
1960 info->attrs = pproperty->attrs;
1962 if ((req_info & PInfo_GetMethod) != 0)
1963 MONO_STRUCT_SETREF (info, get, pproperty->get &&
1964 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->get->klass == property->klass) ?
1965 mono_method_get_object (domain, pproperty->get, property->klass): NULL);
1966 if ((req_info & PInfo_SetMethod) != 0)
1967 MONO_STRUCT_SETREF (info, set, pproperty->set &&
1968 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) || pproperty->set->klass == property->klass) ?
1969 mono_method_get_object (domain, pproperty->set, property->klass): NULL);
1971 * There may be other methods defined for properties, though, it seems they are not exposed
1972 * in the reflection API
1977 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1979 MonoDomain *domain = mono_object_domain (event);
1981 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1982 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1984 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1985 info->attrs = event->event->attrs;
1986 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
1987 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
1988 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
1990 #ifndef MONO_SMALL_CONFIG
1991 if (event->event->other) {
1993 while (event->event->other [n])
1995 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
1997 for (i = 0; i < n; i++)
1998 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2004 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2009 mono_class_setup_interfaces (klass, error);
2010 if (!mono_error_ok (error))
2013 for (i = 0; i < klass->interface_count; i++) {
2014 ic = klass->interfaces [i];
2015 g_hash_table_insert (ifaces, ic, ic);
2017 collect_interfaces (ic, ifaces, error);
2018 if (!mono_error_ok (error))
2024 MonoArray *iface_array;
2025 MonoGenericContext *context;
2029 } FillIfaceArrayData;
2032 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2034 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2035 MonoClass *ic = (MonoClass *)key;
2036 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2038 if (!mono_error_ok (data->error))
2041 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2042 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2043 if (!mono_error_ok (data->error))
2047 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2050 mono_metadata_free_type (inflated);
2054 get_interfaces_hash (gconstpointer v1)
2056 MonoClass *k = (MonoClass*)v1;
2058 return k->type_token;
2061 ICALL_EXPORT MonoArray*
2062 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2065 MonoClass *klass = mono_class_from_mono_type (type->type);
2067 FillIfaceArrayData data = { 0 };
2070 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2072 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2073 data.context = mono_class_get_context (klass);
2074 klass = klass->generic_class->container_class;
2077 for (parent = klass; parent; parent = parent->parent) {
2078 mono_class_setup_interfaces (parent, &error);
2079 if (!mono_error_ok (&error))
2081 collect_interfaces (parent, iface_hash, &error);
2082 if (!mono_error_ok (&error))
2086 data.error = &error;
2087 data.domain = mono_object_domain (type);
2089 len = g_hash_table_size (iface_hash);
2091 g_hash_table_destroy (iface_hash);
2092 if (!data.domain->empty_types)
2093 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2094 return data.domain->empty_types;
2097 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2098 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2099 if (!mono_error_ok (&error))
2102 g_hash_table_destroy (iface_hash);
2103 return data.iface_array;
2106 g_hash_table_destroy (iface_hash);
2107 mono_error_raise_exception (&error);
2112 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2114 gboolean variance_used;
2115 MonoClass *klass = mono_class_from_mono_type (type->type);
2116 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2117 MonoReflectionMethod *member;
2120 int i = 0, len, ioffset;
2123 mono_class_init_or_throw (klass);
2124 mono_class_init_or_throw (iclass);
2126 mono_class_setup_vtable (klass);
2128 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2132 len = mono_class_num_methods (iclass);
2133 domain = mono_object_domain (type);
2134 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2135 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2137 while ((method = mono_class_get_methods (iclass, &iter))) {
2138 member = mono_method_get_object (domain, method, iclass);
2139 mono_array_setref (*methods, i, member);
2140 member = mono_method_get_object (domain, klass->vtable [i + ioffset], klass);
2141 mono_array_setref (*targets, i, member);
2148 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2150 MonoClass *klass = mono_class_from_mono_type (type->type);
2151 mono_class_init_or_throw (klass);
2153 if (image_is_dynamic (klass->image)) {
2154 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2155 *packing = tb->packing_size;
2156 *size = tb->class_size;
2158 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2162 ICALL_EXPORT MonoReflectionType*
2163 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2167 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2168 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2170 klass = mono_class_from_mono_type (type->type);
2171 mono_class_init_or_throw (klass);
2173 // GetElementType should only return a type for:
2174 // Array Pointer PassedByRef
2175 if (type->type->byref)
2176 return mono_type_get_object (mono_object_domain (type), &klass->byval_arg);
2177 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2178 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2179 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2180 return mono_type_get_object (mono_object_domain (type), &klass->element_class->byval_arg);
2185 ICALL_EXPORT MonoReflectionType*
2186 ves_icall_get_type_parent (MonoReflectionType *type)
2188 if (type->type->byref)
2191 MonoClass *klass = mono_class_from_mono_type (type->type);
2192 return klass->parent ? mono_type_get_object (mono_object_domain (type), &klass->parent->byval_arg): NULL;
2195 ICALL_EXPORT MonoBoolean
2196 ves_icall_type_ispointer (MonoReflectionType *type)
2198 return type->type->type == MONO_TYPE_PTR;
2201 ICALL_EXPORT MonoBoolean
2202 ves_icall_type_isprimitive (MonoReflectionType *type)
2204 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2207 ICALL_EXPORT MonoBoolean
2208 ves_icall_type_isbyref (MonoReflectionType *type)
2210 return type->type->byref;
2213 ICALL_EXPORT MonoBoolean
2214 ves_icall_type_iscomobject (MonoReflectionType *type)
2216 MonoClass *klass = mono_class_from_mono_type (type->type);
2217 mono_class_init_or_throw (klass);
2219 return mono_class_is_com_object (klass);
2222 ICALL_EXPORT MonoReflectionModule*
2223 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2225 MonoClass *klass = mono_class_from_mono_type (type->type);
2226 return mono_module_get_object (mono_object_domain (type), klass->image);
2229 ICALL_EXPORT MonoReflectionAssembly*
2230 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2232 MonoDomain *domain = mono_domain_get ();
2233 MonoClass *klass = mono_class_from_mono_type (type->type);
2234 return mono_assembly_get_object (domain, klass->image->assembly);
2237 ICALL_EXPORT MonoReflectionType*
2238 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2240 MonoDomain *domain = mono_domain_get ();
2243 if (type->type->byref)
2245 if (type->type->type == MONO_TYPE_VAR) {
2246 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2247 klass = param ? param->owner.klass : NULL;
2248 } else if (type->type->type == MONO_TYPE_MVAR) {
2249 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2250 klass = param ? param->owner.method->klass : NULL;
2252 klass = mono_class_from_mono_type (type->type)->nested_in;
2255 return klass ? mono_type_get_object (domain, &klass->byval_arg) : NULL;
2258 ICALL_EXPORT MonoString*
2259 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2261 MonoDomain *domain = mono_domain_get ();
2262 MonoClass *klass = mono_class_from_mono_type (type->type);
2264 if (type->type->byref) {
2265 char *n = g_strdup_printf ("%s&", klass->name);
2266 MonoString *res = mono_string_new (domain, n);
2272 return mono_string_new (domain, klass->name);
2276 ICALL_EXPORT MonoString*
2277 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2279 MonoDomain *domain = mono_domain_get ();
2280 MonoClass *klass = mono_class_from_mono_type (type->type);
2282 while (klass->nested_in)
2283 klass = klass->nested_in;
2285 if (klass->name_space [0] == '\0')
2288 return mono_string_new (domain, klass->name_space);
2292 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2296 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2297 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2301 klass = mono_class_from_mono_type (type->type);
2307 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2310 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2314 ICALL_EXPORT MonoArray*
2315 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2318 MonoClass *klass, *pklass;
2319 MonoDomain *domain = mono_object_domain (type);
2322 klass = mono_class_from_mono_type (type->type);
2324 if (klass->generic_container) {
2325 MonoGenericContainer *container = klass->generic_container;
2326 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2327 for (i = 0; i < container->type_argc; ++i) {
2328 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2329 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2331 } else if (klass->generic_class) {
2332 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2333 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2334 for (i = 0; i < inst->type_argc; ++i)
2335 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2342 ICALL_EXPORT gboolean
2343 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2347 if (!IS_MONOTYPE (type))
2350 if (type->type->byref)
2353 klass = mono_class_from_mono_type (type->type);
2354 return klass->generic_container != NULL;
2357 ICALL_EXPORT MonoReflectionType*
2358 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2362 if (type->type->byref)
2365 klass = mono_class_from_mono_type (type->type);
2367 if (klass->generic_container) {
2368 return type; /* check this one */
2370 if (klass->generic_class) {
2371 MonoClass *generic_class = klass->generic_class->container_class;
2374 tb = mono_class_get_ref_info (generic_class);
2376 if (generic_class->wastypebuilder && tb)
2377 return (MonoReflectionType *)tb;
2379 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2384 ICALL_EXPORT MonoReflectionType*
2385 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2388 MonoType *geninst, **types;
2391 g_assert (IS_MONOTYPE (type));
2392 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2394 count = mono_array_length (type_array);
2395 types = g_new0 (MonoType *, count);
2397 for (i = 0; i < count; i++) {
2398 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2399 types [i] = t->type;
2402 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2407 klass = mono_class_from_mono_type (geninst);
2409 /*we might inflate to the GTD*/
2410 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2411 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2415 return mono_type_get_object (mono_object_domain (type), geninst);
2418 ICALL_EXPORT gboolean
2419 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2423 if (!IS_MONOTYPE (type))
2426 if (type->type->byref)
2429 klass = mono_class_from_mono_type (type->type);
2430 return klass->generic_class != NULL || klass->generic_container != NULL;
2434 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2436 if (!IS_MONOTYPE (type))
2439 if (is_generic_parameter (type->type))
2440 return mono_type_get_generic_param_num (type->type);
2444 ICALL_EXPORT GenericParameterAttributes
2445 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2447 g_assert (IS_MONOTYPE (type));
2448 g_assert (is_generic_parameter (type->type));
2449 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2452 ICALL_EXPORT MonoArray *
2453 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2455 MonoGenericParamInfo *param_info;
2461 g_assert (IS_MONOTYPE (type));
2463 domain = mono_object_domain (type);
2464 param_info = mono_generic_param_info (type->type->data.generic_param);
2465 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2468 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2469 for (i = 0; i < count; i++)
2470 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2476 ICALL_EXPORT MonoBoolean
2477 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2479 return is_generic_parameter (type->type);
2482 ICALL_EXPORT MonoBoolean
2483 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2485 return is_generic_parameter (tb->type.type);
2489 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2490 MonoReflectionType *t)
2492 enumtype->type = t->type;
2495 ICALL_EXPORT MonoReflectionMethod*
2496 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2497 MonoReflectionMethod* generic)
2504 domain = ((MonoObject *)type)->vtable->domain;
2506 klass = mono_class_from_mono_type (type->type);
2507 mono_class_init_or_throw (klass);
2510 while ((method = mono_class_get_methods (klass, &iter))) {
2511 if (method->token == generic->method->token)
2512 return mono_method_get_object (domain, method, klass);
2518 ICALL_EXPORT MonoReflectionMethod *
2519 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2522 MonoType *type = ref_type->type;
2524 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2525 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2528 if (type->type == MONO_TYPE_VAR)
2531 method = mono_type_get_generic_param_owner (type)->owner.method;
2533 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2536 ICALL_EXPORT MonoBoolean
2537 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2539 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2543 ICALL_EXPORT MonoBoolean
2544 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2546 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2551 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2553 MonoDomain *domain = mono_domain_get ();
2554 MonoImage *image = method->method->klass->image;
2555 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2556 MonoTableInfo *tables = image->tables;
2557 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2558 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2559 guint32 im_cols [MONO_IMPLMAP_SIZE];
2560 guint32 scope_token;
2561 const char *import = NULL;
2562 const char *scope = NULL;
2564 if (image_is_dynamic (image)) {
2565 MonoReflectionMethodAux *method_aux =
2566 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2568 import = method_aux->dllentry;
2569 scope = method_aux->dll;
2572 if (!import || !scope) {
2573 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2578 if (piinfo->implmap_idx) {
2579 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2581 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2582 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2583 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2584 scope = mono_metadata_string_heap (image, scope_token);
2588 *flags = piinfo->piflags;
2589 *entry_point = mono_string_new (domain, import);
2590 *dll_name = mono_string_new (domain, scope);
2593 ICALL_EXPORT MonoReflectionMethod *
2594 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2596 MonoMethodInflated *imethod;
2599 if (method->method->is_generic)
2602 if (!method->method->is_inflated)
2605 imethod = (MonoMethodInflated *) method->method;
2607 result = imethod->declaring;
2608 /* Not a generic method. */
2609 if (!result->is_generic)
2612 if (image_is_dynamic (method->method->klass->image)) {
2613 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2614 MonoReflectionMethod *res;
2617 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2618 * the dynamic case as well ?
2620 mono_image_lock ((MonoImage*)image);
2621 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2622 mono_image_unlock ((MonoImage*)image);
2628 if (imethod->context.class_inst) {
2629 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2630 /*Generic methods gets the context of the GTD.*/
2631 if (mono_class_get_context (klass)) {
2633 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2634 mono_error_raise_exception (&error);
2638 return mono_method_get_object (mono_object_domain (method), result, NULL);
2641 ICALL_EXPORT gboolean
2642 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2644 return mono_method_signature (method->method)->generic_param_count != 0;
2647 ICALL_EXPORT gboolean
2648 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2650 return method->method->is_generic;
2653 ICALL_EXPORT MonoArray*
2654 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2660 domain = mono_object_domain (method);
2662 if (method->method->is_inflated) {
2663 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2666 count = inst->type_argc;
2667 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2669 for (i = 0; i < count; i++)
2670 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2676 count = mono_method_signature (method->method)->generic_param_count;
2677 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2679 for (i = 0; i < count; i++) {
2680 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2681 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2682 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
2683 mono_array_setref (res, i,
2684 mono_type_get_object (domain, &pklass->byval_arg));
2690 ICALL_EXPORT MonoObject *
2691 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
2694 * Invoke from reflection is supposed to always be a virtual call (the API
2695 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2696 * greater flexibility.
2698 MonoMethod *m = method->method;
2699 MonoMethodSignature *sig = mono_method_signature (m);
2702 void *obj = this_arg;
2706 if (mono_security_core_clr_enabled ())
2707 mono_security_core_clr_ensure_reflection_access_method (m);
2709 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2710 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2711 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2716 if (!mono_object_isinst (this_arg, m->klass)) {
2717 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
2718 char *target_name = mono_type_get_full_name (m->klass);
2719 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2720 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2722 g_free (target_name);
2726 m = mono_object_get_virtual_method (this_arg, m);
2727 /* must pass the pointer to the value for valuetype methods */
2728 if (m->klass->valuetype)
2729 obj = mono_object_unbox (this_arg);
2730 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2731 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2736 if (sig->ret->byref) {
2737 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
2741 pcount = params? mono_array_length (params): 0;
2742 if (pcount != sig->param_count) {
2743 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2747 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
2748 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2752 image = m->klass->image;
2753 if (image->assembly->ref_only) {
2754 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2758 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2759 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2763 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2766 intptr_t *lower_bounds;
2767 pcount = mono_array_length (params);
2768 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
2769 /* Note: the synthetized array .ctors have int32 as argument type */
2770 for (i = 0; i < pcount; ++i)
2771 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2773 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2774 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2775 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2777 for (i = 0; i < mono_array_length (arr); ++i) {
2778 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2780 mono_array_setref_fast (arr, i, subarray);
2782 return (MonoObject*)arr;
2785 if (m->klass->rank == pcount) {
2786 /* Only lengths provided. */
2787 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2789 g_assert (pcount == (m->klass->rank * 2));
2790 /* The arguments are lower-bound-length pairs */
2791 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
2793 for (i = 0; i < pcount / 2; ++i) {
2794 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
2795 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
2798 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2801 return mono_runtime_invoke_array (m, obj, params, NULL);
2804 #ifndef DISABLE_REMOTING
2805 ICALL_EXPORT MonoObject *
2806 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
2808 MonoDomain *domain = mono_object_domain (method);
2809 MonoMethod *m = method->method;
2810 MonoMethodSignature *sig = mono_method_signature (m);
2811 MonoArray *out_args;
2813 int i, j, outarg_count = 0;
2815 if (m->klass == mono_defaults.object_class) {
2816 if (!strcmp (m->name, "FieldGetter")) {
2817 MonoClass *k = this_arg->vtable->klass;
2821 /* If this is a proxy, then it must be a CBO */
2822 if (k == mono_defaults.transparent_proxy_class) {
2823 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2824 this_arg = tp->rp->unwrapped_server;
2825 g_assert (this_arg);
2826 k = this_arg->vtable->klass;
2829 name = mono_array_get (params, MonoString *, 1);
2830 str = mono_string_to_utf8 (name);
2833 MonoClassField* field = mono_class_get_field_from_name (k, str);
2835 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2836 if (field_klass->valuetype)
2837 result = mono_value_box (domain, field_klass, (char *)this_arg + field->offset);
2839 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
2841 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2842 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2843 mono_array_setref (out_args, 0, result);
2851 g_assert_not_reached ();
2853 } else if (!strcmp (m->name, "FieldSetter")) {
2854 MonoClass *k = this_arg->vtable->klass;
2860 /* If this is a proxy, then it must be a CBO */
2861 if (k == mono_defaults.transparent_proxy_class) {
2862 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
2863 this_arg = tp->rp->unwrapped_server;
2864 g_assert (this_arg);
2865 k = this_arg->vtable->klass;
2868 name = mono_array_get (params, MonoString *, 1);
2869 str = mono_string_to_utf8 (name);
2872 MonoClassField* field = mono_class_get_field_from_name (k, str);
2874 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2875 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
2877 if (field_klass->valuetype) {
2878 size = mono_type_size (field->type, &align);
2879 g_assert (size == mono_class_value_size (field_klass, NULL));
2880 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2882 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
2885 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2886 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2896 g_assert_not_reached ();
2901 for (i = 0; i < mono_array_length (params); i++) {
2902 if (sig->params [i]->byref)
2906 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2908 /* handle constructors only for objects already allocated */
2909 if (!strcmp (method->method->name, ".ctor"))
2910 g_assert (this_arg);
2912 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2913 g_assert (!method->method->klass->valuetype);
2914 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
2916 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2917 if (sig->params [i]->byref) {
2919 arg = mono_array_get (params, gpointer, i);
2920 mono_array_setref (out_args, j, arg);
2925 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2932 read_enum_value (const char *mem, int type)
2935 case MONO_TYPE_BOOLEAN:
2937 return *(guint8*)mem;
2939 return *(gint8*)mem;
2940 case MONO_TYPE_CHAR:
2942 return read16 (mem);
2944 return (gint16) read16 (mem);
2946 return read32 (mem);
2948 return (gint32) read32 (mem);
2951 return read64 (mem);
2953 g_assert_not_reached ();
2959 write_enum_value (char *mem, int type, guint64 value)
2963 case MONO_TYPE_I1: {
2964 guint8 *p = (guint8*)mem;
2969 case MONO_TYPE_I2: {
2970 guint16 *p = (guint16 *)mem;
2975 case MONO_TYPE_I4: {
2976 guint32 *p = (guint32 *)mem;
2981 case MONO_TYPE_I8: {
2982 guint64 *p = (guint64 *)mem;
2987 g_assert_not_reached ();
2992 ICALL_EXPORT MonoObject *
2993 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3000 domain = mono_object_domain (enumType);
3001 enumc = mono_class_from_mono_type (enumType->type);
3003 mono_class_init_or_throw (enumc);
3005 etype = mono_class_enum_basetype (enumc);
3007 res = mono_object_new (domain, enumc);
3008 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3013 ICALL_EXPORT MonoBoolean
3014 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3016 int size = mono_class_value_size (a->vtable->klass, NULL);
3017 guint64 a_val = 0, b_val = 0;
3019 memcpy (&a_val, mono_object_unbox (a), size);
3020 memcpy (&b_val, mono_object_unbox (b), size);
3022 return (a_val & b_val) == b_val;
3025 ICALL_EXPORT MonoObject *
3026 ves_icall_System_Enum_get_value (MonoObject *eobj)
3037 g_assert (eobj->vtable->klass->enumtype);
3039 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3040 res = mono_object_new (mono_object_domain (eobj), enumc);
3041 dst = (char *)res + sizeof (MonoObject);
3042 src = (char *)eobj + sizeof (MonoObject);
3043 size = mono_class_value_size (enumc, NULL);
3045 memcpy (dst, src, size);
3050 ICALL_EXPORT MonoReflectionType *
3051 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3056 klass = mono_class_from_mono_type (type->type);
3057 mono_class_init_or_throw (klass);
3059 etype = mono_class_enum_basetype (klass);
3061 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3065 return mono_type_get_object (mono_object_domain (type), etype);
3069 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3071 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3072 gpointer odata = (char *)other + sizeof (MonoObject);
3073 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3074 g_assert (basetype);
3079 if (eobj->vtable->klass != other->vtable->klass)
3082 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3083 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3084 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3087 return me > other ? 1 : -1; \
3090 switch (basetype->type) {
3092 COMPARE_ENUM_VALUES (guint8);
3094 COMPARE_ENUM_VALUES (gint8);
3095 case MONO_TYPE_CHAR:
3097 COMPARE_ENUM_VALUES (guint16);
3099 COMPARE_ENUM_VALUES (gint16);
3101 COMPARE_ENUM_VALUES (guint32);
3103 COMPARE_ENUM_VALUES (gint32);
3105 COMPARE_ENUM_VALUES (guint64);
3107 COMPARE_ENUM_VALUES (gint64);
3111 #undef COMPARE_ENUM_VALUES
3112 /* indicates that the enum was of an unsupported unerlying type */
3117 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3119 gpointer data = (char *)eobj + sizeof (MonoObject);
3120 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3121 g_assert (basetype);
3123 switch (basetype->type) {
3124 case MONO_TYPE_I1: {
3125 gint8 value = *((gint8*)data);
3126 return ((int)value ^ (int)value << 8);
3129 return *((guint8*)data);
3130 case MONO_TYPE_CHAR:
3132 return *((guint16*)data);
3134 case MONO_TYPE_I2: {
3135 gint16 value = *((gint16*)data);
3136 return ((int)(guint16)value | (((int)value) << 16));
3139 return *((guint32*)data);
3141 return *((gint32*)data);
3143 case MONO_TYPE_I8: {
3144 gint64 value = *((gint64*)data);
3145 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3148 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3153 ICALL_EXPORT MonoBoolean
3154 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3156 MonoDomain *domain = mono_object_domain (type);
3157 MonoClass *enumc = mono_class_from_mono_type (type->type);
3158 guint j = 0, nvalues;
3160 MonoClassField *field;
3162 guint64 field_value, previous_value = 0;
3163 gboolean sorted = TRUE;
3165 mono_class_init_or_throw (enumc);
3167 if (!enumc->enumtype) {
3168 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3172 base_type = mono_class_enum_basetype (enumc)->type;
3174 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3175 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3176 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3179 while ((field = mono_class_get_fields (enumc, &iter))) {
3181 MonoTypeEnum def_type;
3183 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3185 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3187 if (mono_field_is_deleted (field))
3189 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3191 p = mono_class_get_field_default_value (field, &def_type);
3192 /* len = */ mono_metadata_decode_blob_size (p, &p);
3194 field_value = read_enum_value (p, base_type);
3195 mono_array_set (*values, guint64, j, field_value);
3197 if (previous_value > field_value)
3200 previous_value = field_value;
3208 BFLAGS_IgnoreCase = 1,
3209 BFLAGS_DeclaredOnly = 2,
3210 BFLAGS_Instance = 4,
3212 BFLAGS_Public = 0x10,
3213 BFLAGS_NonPublic = 0x20,
3214 BFLAGS_FlattenHierarchy = 0x40,
3215 BFLAGS_InvokeMethod = 0x100,
3216 BFLAGS_CreateInstance = 0x200,
3217 BFLAGS_GetField = 0x400,
3218 BFLAGS_SetField = 0x800,
3219 BFLAGS_GetProperty = 0x1000,
3220 BFLAGS_SetProperty = 0x2000,
3221 BFLAGS_ExactBinding = 0x10000,
3222 BFLAGS_SuppressChangeType = 0x20000,
3223 BFLAGS_OptionalParamBinding = 0x40000
3226 ICALL_EXPORT MonoArray*
3227 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3230 MonoClass *startklass, *klass, *refklass;
3235 char *utf8_name = NULL;
3236 int (*compare_func) (const char *s1, const char *s2) = NULL;
3237 MonoClassField *field;
3238 MonoPtrArray tmp_array;
3240 domain = ((MonoObject *)type)->vtable->domain;
3241 if (type->type->byref)
3242 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3244 klass = startklass = mono_class_from_mono_type (type->type);
3245 refklass = mono_class_from_mono_type (reftype->type);
3247 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3250 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3251 mono_ptr_array_destroy (tmp_array);
3252 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3257 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3258 guint32 flags = mono_field_get_flags (field);
3260 if (mono_field_is_deleted_with_flags (field, flags))
3262 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3263 if (bflags & BFLAGS_Public)
3265 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3266 if (bflags & BFLAGS_NonPublic) {
3273 if (flags & FIELD_ATTRIBUTE_STATIC) {
3274 if (bflags & BFLAGS_Static)
3275 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3278 if (bflags & BFLAGS_Instance)
3286 if (utf8_name == NULL) {
3287 utf8_name = mono_string_to_utf8 (name);
3288 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3291 if (compare_func (mono_field_get_name (field), utf8_name))
3295 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3296 mono_ptr_array_append (tmp_array, member);
3298 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3301 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3303 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3304 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3306 mono_ptr_array_destroy (tmp_array);
3308 if (utf8_name != NULL)
3315 method_nonpublic (MonoMethod* method, gboolean start_klass)
3317 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3318 case METHOD_ATTRIBUTE_ASSEM:
3319 return (start_klass || mono_defaults.generic_ilist_class);
3320 case METHOD_ATTRIBUTE_PRIVATE:
3322 case METHOD_ATTRIBUTE_PUBLIC:
3330 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3333 MonoClass *startklass;
3337 /*FIXME, use MonoBitSet*/
3338 guint32 method_slots_default [8];
3339 guint32 *method_slots = NULL;
3340 int (*compare_func) (const char *s1, const char *s2) = NULL;
3342 array = g_ptr_array_new ();
3347 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3349 /* An optimization for calls made from Delegate:CreateDelegate () */
3350 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3351 method = mono_get_delegate_invoke (klass);
3352 if (mono_loader_get_last_error ())
3355 g_ptr_array_add (array, method);
3359 mono_class_setup_methods (klass);
3360 mono_class_setup_vtable (klass);
3361 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3364 if (is_generic_parameter (&klass->byval_arg))
3365 nslots = mono_class_get_vtable_size (klass->parent);
3367 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3368 if (nslots >= sizeof (method_slots_default) * 8) {
3369 method_slots = g_new0 (guint32, nslots / 32 + 1);
3371 method_slots = method_slots_default;
3372 memset (method_slots, 0, sizeof (method_slots_default));
3375 mono_class_setup_methods (klass);
3376 mono_class_setup_vtable (klass);
3377 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3381 while ((method = mono_class_get_methods (klass, &iter))) {
3383 if (method->slot != -1) {
3384 g_assert (method->slot < nslots);
3385 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3387 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3388 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3391 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3393 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3394 if (bflags & BFLAGS_Public)
3396 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3402 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3403 if (bflags & BFLAGS_Static)
3404 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3407 if (bflags & BFLAGS_Instance)
3415 if (compare_func (name, method->name))
3420 g_ptr_array_add (array, method);
3422 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3424 if (method_slots != method_slots_default)
3425 g_free (method_slots);
3430 if (method_slots != method_slots_default)
3431 g_free (method_slots);
3432 g_ptr_array_free (array, TRUE);
3434 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3435 *ex = mono_class_get_exception_for_failure (klass);
3437 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3438 mono_loader_clear_error ();
3443 ICALL_EXPORT MonoArray*
3444 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3446 static MonoClass *MethodInfo_array;
3449 MonoVTable *array_vtable;
3450 MonoException *ex = NULL;
3451 const char *mname = NULL;
3452 GPtrArray *method_array;
3453 MonoClass *klass, *refklass;
3456 if (!MethodInfo_array) {
3457 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3458 mono_memory_barrier ();
3459 MethodInfo_array = klass;
3462 klass = mono_class_from_mono_type (type->type);
3463 refklass = mono_class_from_mono_type (reftype->type);
3464 domain = ((MonoObject *)type)->vtable->domain;
3465 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3466 if (type->type->byref)
3467 return mono_array_new_specific (array_vtable, 0);
3470 mname = mono_string_to_utf8 (name);
3472 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3473 g_free ((char*)mname);
3475 mono_set_pending_exception (ex);
3479 res = mono_array_new_specific (array_vtable, method_array->len);
3481 for (i = 0; i < method_array->len; ++i) {
3482 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3483 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3486 g_ptr_array_free (method_array, TRUE);
3490 ICALL_EXPORT MonoArray*
3491 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3494 static MonoClass *System_Reflection_ConstructorInfo;
3495 MonoClass *startklass, *klass, *refklass;
3500 gpointer iter = NULL;
3501 MonoPtrArray tmp_array;
3503 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3505 domain = ((MonoObject *)type)->vtable->domain;
3506 if (type->type->byref)
3507 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3508 klass = startklass = mono_class_from_mono_type (type->type);
3509 refklass = mono_class_from_mono_type (reftype->type);
3511 if (!System_Reflection_ConstructorInfo)
3512 System_Reflection_ConstructorInfo = mono_class_from_name (
3513 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3515 mono_class_setup_methods (klass);
3516 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3517 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3522 while ((method = mono_class_get_methods (klass, &iter))) {
3524 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3526 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3527 if (bflags & BFLAGS_Public)
3530 if (bflags & BFLAGS_NonPublic)
3536 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3537 if (bflags & BFLAGS_Static)
3538 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3541 if (bflags & BFLAGS_Instance)
3547 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3549 mono_ptr_array_append (tmp_array, member);
3552 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3554 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3555 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3557 mono_ptr_array_destroy (tmp_array);
3563 property_hash (gconstpointer data)
3565 MonoProperty *prop = (MonoProperty*)data;
3567 return g_str_hash (prop->name);
3571 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3573 if (method1->is_inflated)
3574 method1 = ((MonoMethodInflated*) method1)->declaring;
3575 if (method2->is_inflated)
3576 method2 = ((MonoMethodInflated*) method2)->declaring;
3578 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
3582 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3584 // Properties are hide-by-name-and-signature
3585 if (!g_str_equal (prop1->name, prop2->name))
3588 /* If we see a property in a generic method, we want to
3589 compare the generic signatures, not the inflated signatures
3590 because we might conflate two properties that were
3594 public T this[T t] { getter { return t; } } // method 1
3595 public U this[U u] { getter { return u; } } // method 2
3598 If we see int Foo<int,int>::Item[int] we need to know if
3599 the indexer came from method 1 or from method 2, and we
3600 shouldn't conflate them. (Bugzilla 36283)
3602 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
3605 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
3612 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3617 return method_nonpublic (accessor, start_klass);
3620 ICALL_EXPORT MonoArray*
3621 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3625 static MonoClass *System_Reflection_PropertyInfo;
3626 MonoClass *startklass, *klass;
3632 gchar *propname = NULL;
3633 int (*compare_func) (const char *s1, const char *s2) = NULL;
3635 GHashTable *properties = NULL;
3636 MonoPtrArray tmp_array;
3638 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
3640 if (!System_Reflection_PropertyInfo)
3641 System_Reflection_PropertyInfo = mono_class_from_name (
3642 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3644 domain = ((MonoObject *)type)->vtable->domain;
3645 if (type->type->byref)
3646 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3647 klass = startklass = mono_class_from_mono_type (type->type);
3650 propname = mono_string_to_utf8 (name);
3651 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3654 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3656 mono_class_setup_methods (klass);
3657 mono_class_setup_vtable (klass);
3658 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3662 while ((prop = mono_class_get_properties (klass, &iter))) {
3668 flags = method->flags;
3671 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3672 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3673 if (bflags & BFLAGS_Public)
3675 } else if (bflags & BFLAGS_NonPublic) {
3676 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3677 property_accessor_nonpublic(prop->set, startklass == klass)) {
3684 if (flags & METHOD_ATTRIBUTE_STATIC) {
3685 if (bflags & BFLAGS_Static)
3686 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3689 if (bflags & BFLAGS_Instance)
3698 if (compare_func (propname, prop->name))
3702 if (g_hash_table_lookup (properties, prop))
3705 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3707 g_hash_table_insert (properties, prop, prop);
3709 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3712 g_hash_table_destroy (properties);
3715 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3716 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3717 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3719 mono_ptr_array_destroy (tmp_array);
3725 g_hash_table_destroy (properties);
3728 mono_ptr_array_destroy (tmp_array);
3730 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3731 ex = mono_class_get_exception_for_failure (klass);
3733 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3734 mono_loader_clear_error ();
3736 mono_set_pending_exception (ex);
3741 event_hash (gconstpointer data)
3743 MonoEvent *event = (MonoEvent*)data;
3745 return g_str_hash (event->name);
3749 event_equal (MonoEvent *event1, MonoEvent *event2)
3751 // Events are hide-by-name
3752 return g_str_equal (event1->name, event2->name);
3755 ICALL_EXPORT MonoArray*
3756 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3760 static MonoClass *System_Reflection_EventInfo;
3761 MonoClass *startklass, *klass;
3767 char *utf8_name = NULL;
3768 int (*compare_func) (const char *s1, const char *s2) = NULL;
3769 GHashTable *events = NULL;
3770 MonoPtrArray tmp_array;
3772 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
3774 if (!System_Reflection_EventInfo)
3775 System_Reflection_EventInfo = mono_class_from_name (
3776 mono_defaults.corlib, "System.Reflection", "EventInfo");
3778 domain = mono_object_domain (type);
3779 if (type->type->byref)
3780 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3781 klass = startklass = mono_class_from_mono_type (type->type);
3783 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3785 mono_class_setup_methods (klass);
3786 mono_class_setup_vtable (klass);
3787 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3791 while ((event = mono_class_get_events (klass, &iter))) {
3793 method = event->add;
3795 method = event->remove;
3797 method = event->raise;
3799 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3800 if (bflags & BFLAGS_Public)
3802 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3803 if (bflags & BFLAGS_NonPublic)
3808 if (bflags & BFLAGS_NonPublic)
3814 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3815 if (bflags & BFLAGS_Static)
3816 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3819 if (bflags & BFLAGS_Instance)
3824 if (bflags & BFLAGS_Instance)
3830 if (utf8_name == NULL) {
3831 utf8_name = mono_string_to_utf8 (name);
3832 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3835 if (compare_func (event->name, utf8_name))
3839 if (g_hash_table_lookup (events, event))
3842 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3844 g_hash_table_insert (events, event, event);
3846 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3849 g_hash_table_destroy (events);
3851 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3853 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3854 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3856 mono_ptr_array_destroy (tmp_array);
3858 if (utf8_name != NULL)
3864 mono_ptr_array_destroy (tmp_array);
3865 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3866 ex = mono_class_get_exception_for_failure (klass);
3868 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3869 mono_loader_clear_error ();
3871 mono_set_pending_exception (ex);
3875 ICALL_EXPORT MonoArray*
3876 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
3886 MonoPtrArray tmp_array;
3888 domain = ((MonoObject *)type)->vtable->domain;
3889 if (type->type->byref)
3890 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3891 klass = mono_class_from_mono_type (type->type);
3894 * If a nested type is generic, return its generic type definition.
3895 * Note that this means that the return value is essentially the set
3896 * of nested types of the generic type definition of @klass.
3898 * A note in MSDN claims that a generic type definition can have
3899 * nested types that aren't generic. In any case, the container of that
3900 * nested type would be the generic type definition.
3902 if (klass->generic_class)
3903 klass = klass->generic_class->container_class;
3905 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
3907 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3909 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3910 if (bflags & BFLAGS_Public)
3913 if (bflags & BFLAGS_NonPublic)
3921 str = mono_string_to_utf8 (name);
3922 mono_identifier_unescape_type_name_chars (str);
3925 if (strcmp (nested->name, str))
3929 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
3930 mono_ptr_array_append (tmp_array, member);
3933 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
3935 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3936 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3938 mono_ptr_array_destroy (tmp_array);
3946 ICALL_EXPORT MonoReflectionType*
3947 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
3950 MonoType *type = NULL;
3951 MonoTypeNameParse info;
3952 gboolean type_resolve;
3954 /* On MS.NET, this does not fire a TypeResolve event */
3955 type_resolve = TRUE;
3956 str = mono_string_to_utf8 (name);
3957 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
3958 if (!mono_reflection_parse_type (str, &info)) {
3960 mono_reflection_free_type_info (&info);
3962 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
3965 /*g_print ("failed parse\n");*/
3969 if (info.assembly.name) {
3971 mono_reflection_free_type_info (&info);
3973 /* 1.0 and 2.0 throw different exceptions */
3974 if (mono_defaults.generic_ilist_class)
3975 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
3977 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
3983 if (module != NULL) {
3985 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
3990 if (assembly_is_dynamic (assembly->assembly)) {
3991 /* Enumerate all modules */
3992 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
3996 if (abuilder->modules) {
3997 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
3998 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
3999 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4005 if (!type && abuilder->loaded_modules) {
4006 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4007 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4008 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4015 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4017 mono_reflection_free_type_info (&info);
4019 MonoException *e = NULL;
4022 e = mono_get_exception_type_load (name, NULL);
4024 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4025 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4027 mono_loader_clear_error ();
4030 mono_set_pending_exception (e);
4032 } else if (mono_loader_get_last_error ()) {
4034 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4037 mono_loader_clear_error ();
4040 if (type->type == MONO_TYPE_CLASS) {
4041 MonoClass *klass = mono_type_get_class (type);
4043 /* need to report exceptions ? */
4044 if (throwOnError && klass->exception_type) {
4045 /* report SecurityException (or others) that occured when loading the assembly */
4046 MonoException *exc = mono_class_get_exception_for_failure (klass);
4047 mono_loader_clear_error ();
4048 mono_set_pending_exception (exc);
4053 /* g_print ("got it\n"); */
4054 return mono_type_get_object (mono_object_domain (assembly), type);
4058 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4061 gchar *shadow_ini_file;
4064 /* Check for shadow-copied assembly */
4065 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4066 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4068 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4069 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4075 g_free (shadow_ini_file);
4076 if (content != NULL) {
4079 *filename = content;
4086 ICALL_EXPORT MonoString *
4087 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4089 MonoDomain *domain = mono_object_domain (assembly);
4090 MonoAssembly *mass = assembly->assembly;
4091 MonoString *res = NULL;
4096 if (g_path_is_absolute (mass->image->name)) {
4097 absolute = g_strdup (mass->image->name);
4098 dirname = g_path_get_dirname (absolute);
4100 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4101 dirname = g_strdup (mass->basedir);
4104 replace_shadow_path (domain, dirname, &absolute);
4109 for (i = strlen (absolute) - 1; i >= 0; i--)
4110 if (absolute [i] == '\\')
4115 uri = g_filename_to_uri (absolute, NULL, NULL);
4117 const char *prepend = "file://";
4119 if (*absolute == '/' && *(absolute + 1) == '/') {
4122 prepend = "file:///";
4125 uri = g_strconcat (prepend, absolute, NULL);
4129 res = mono_string_new (domain, uri);
4136 ICALL_EXPORT MonoBoolean
4137 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4139 MonoAssembly *mass = assembly->assembly;
4141 return mass->in_gac;
4144 ICALL_EXPORT MonoReflectionAssembly*
4145 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4149 MonoImageOpenStatus status;
4151 name = mono_string_to_utf8 (mname);
4152 res = mono_assembly_load_with_partial_name (name, &status);
4158 return mono_assembly_get_object (mono_domain_get (), res);
4161 ICALL_EXPORT MonoString *
4162 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4164 MonoDomain *domain = mono_object_domain (assembly);
4167 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4172 ICALL_EXPORT MonoBoolean
4173 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4175 return assembly->assembly->ref_only;
4178 ICALL_EXPORT MonoString *
4179 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4181 MonoDomain *domain = mono_object_domain (assembly);
4183 return mono_string_new (domain, assembly->assembly->image->version);
4186 ICALL_EXPORT MonoReflectionMethod*
4187 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4191 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4195 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4196 mono_error_raise_exception (&error);
4198 return mono_method_get_object (mono_object_domain (assembly), method, NULL);
4201 ICALL_EXPORT MonoReflectionModule*
4202 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4204 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4207 ICALL_EXPORT MonoArray*
4208 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4210 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4211 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4215 for (i = 0; i < table->rows; ++i) {
4216 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4217 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4223 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4225 static MonoClass *System_Version = NULL;
4226 static MonoMethod *create_version = NULL;
4230 if (!System_Version) {
4231 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4232 g_assert (System_Version);
4235 if (!create_version) {
4236 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4237 create_version = mono_method_desc_search_in_class (desc, System_Version);
4238 g_assert (create_version);
4239 mono_method_desc_free (desc);
4245 args [3] = &revision;
4246 result = mono_object_new (domain, System_Version);
4247 mono_runtime_invoke (create_version, result, args, NULL);
4252 ICALL_EXPORT MonoArray*
4253 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4255 static MonoClass *System_Reflection_AssemblyName;
4257 MonoDomain *domain = mono_object_domain (assembly);
4259 static MonoMethod *create_culture = NULL;
4260 MonoImage *image = assembly->assembly->image;
4263 if (!System_Reflection_AssemblyName)
4264 System_Reflection_AssemblyName = mono_class_from_name (
4265 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4267 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4270 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4272 if (count > 0 && !create_culture) {
4273 MonoMethodDesc *desc = mono_method_desc_new (
4274 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4275 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4276 g_assert (create_culture);
4277 mono_method_desc_free (desc);
4280 for (i = 0; i < count; i++) {
4281 MonoReflectionAssemblyName *aname;
4282 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4284 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4286 aname = (MonoReflectionAssemblyName *) mono_object_new (
4287 domain, System_Reflection_AssemblyName);
4289 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4291 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4292 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4293 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4294 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4295 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4296 aname->versioncompat = 1; /* SameMachine (default) */
4297 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4298 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4300 if (create_culture) {
4302 MonoBoolean assembly_ref = 1;
4303 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4304 args [1] = &assembly_ref;
4305 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4308 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4309 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4310 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4312 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4313 /* public key token isn't copied - the class library will
4314 automatically generate it from the public key if required */
4315 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4316 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4318 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4319 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4322 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4325 /* note: this function doesn't return the codebase on purpose (i.e. it can
4326 be used under partial trust as path information isn't present). */
4328 mono_array_setref (result, i, aname);
4333 /* move this in some file in mono/util/ */
4335 g_concat_dir_and_file (const char *dir, const char *file)
4337 g_return_val_if_fail (dir != NULL, NULL);
4338 g_return_val_if_fail (file != NULL, NULL);
4341 * If the directory name doesn't have a / on the end, we need
4342 * to add one so we get a proper path to the file
4344 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4345 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4347 return g_strconcat (dir, file, NULL);
4351 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4353 char *n = mono_string_to_utf8 (name);
4354 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4356 guint32 cols [MONO_MANIFEST_SIZE];
4357 guint32 impl, file_idx;
4361 for (i = 0; i < table->rows; ++i) {
4362 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4363 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4364 if (strcmp (val, n) == 0)
4368 if (i == table->rows)
4371 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4374 * this code should only be called after obtaining the
4375 * ResourceInfo and handling the other cases.
4377 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4378 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4380 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4385 module = assembly->assembly->image;
4387 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4389 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4392 ICALL_EXPORT gboolean
4393 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4395 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4397 guint32 cols [MONO_MANIFEST_SIZE];
4398 guint32 file_cols [MONO_FILE_SIZE];
4402 n = mono_string_to_utf8 (name);
4403 for (i = 0; i < table->rows; ++i) {
4404 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4405 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4406 if (strcmp (val, n) == 0)
4410 if (i == table->rows)
4413 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4414 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4417 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4418 case MONO_IMPLEMENTATION_FILE:
4419 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4420 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4421 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4422 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4423 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4424 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4427 info->location = RESOURCE_LOCATION_EMBEDDED;
4430 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4431 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4432 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4433 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4434 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4435 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4437 mono_set_pending_exception (ex);
4440 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4442 /* Obtain info recursively */
4443 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4444 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4447 case MONO_IMPLEMENTATION_EXP_TYPE:
4448 g_assert_not_reached ();
4456 ICALL_EXPORT MonoObject*
4457 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4459 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4460 MonoArray *result = NULL;
4465 /* check hash if needed */
4467 n = mono_string_to_utf8 (name);
4468 for (i = 0; i < table->rows; ++i) {
4469 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4470 if (strcmp (val, n) == 0) {
4473 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4474 fn = mono_string_new (mono_object_domain (assembly), n);
4476 return (MonoObject*)fn;
4484 for (i = 0; i < table->rows; ++i) {
4485 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4489 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4492 for (i = 0; i < table->rows; ++i) {
4493 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4494 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4495 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4496 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4501 return (MonoObject*)result;
4504 ICALL_EXPORT MonoArray*
4505 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4507 MonoDomain *domain = mono_domain_get();
4510 int i, j, file_count = 0;
4511 MonoImage **modules;
4512 guint32 module_count, real_module_count;
4513 MonoTableInfo *table;
4514 guint32 cols [MONO_FILE_SIZE];
4515 MonoImage *image = assembly->assembly->image;
4517 g_assert (image != NULL);
4518 g_assert (!assembly_is_dynamic (assembly->assembly));
4520 table = &image->tables [MONO_TABLE_FILE];
4521 file_count = table->rows;
4523 modules = image->modules;
4524 module_count = image->module_count;
4526 real_module_count = 0;
4527 for (i = 0; i < module_count; ++i)
4529 real_module_count ++;
4531 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4532 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4534 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4536 for (i = 0; i < module_count; ++i)
4538 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4542 for (i = 0; i < file_count; ++i, ++j) {
4543 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4544 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4545 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4547 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4549 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4550 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
4553 mono_array_setref (res, j, mono_module_get_object (domain, m));
4560 ICALL_EXPORT MonoReflectionMethod*
4561 ves_icall_GetCurrentMethod (void)
4563 MonoMethod *m = mono_method_get_last_managed ();
4565 while (m->is_inflated)
4566 m = ((MonoMethodInflated*)m)->declaring;
4568 return mono_method_get_object (mono_domain_get (), m, NULL);
4573 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4576 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4579 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4580 //method is inflated, we should inflate it on the other class
4581 MonoGenericContext ctx;
4582 ctx.method_inst = inflated->context.method_inst;
4583 ctx.class_inst = inflated->context.class_inst;
4584 if (klass->generic_class)
4585 ctx.class_inst = klass->generic_class->context.class_inst;
4586 else if (klass->generic_container)
4587 ctx.class_inst = klass->generic_container->context.class_inst;
4588 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
4589 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
4593 mono_class_setup_methods (method->klass);
4594 if (method->klass->exception_type)
4596 for (i = 0; i < method->klass->method.count; ++i) {
4597 if (method->klass->methods [i] == method) {
4602 mono_class_setup_methods (klass);
4603 if (klass->exception_type)
4605 g_assert (offset >= 0 && offset < klass->method.count);
4606 return klass->methods [offset];
4609 ICALL_EXPORT MonoReflectionMethod*
4610 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4614 klass = mono_class_from_mono_type (type);
4615 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4617 if (method->klass != klass) {
4618 method = mono_method_get_equivalent_method (method, klass);
4623 klass = method->klass;
4624 return mono_method_get_object (mono_domain_get (), method, klass);
4627 ICALL_EXPORT MonoReflectionMethodBody*
4628 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4630 return mono_method_body_get_object (mono_domain_get (), method);
4633 ICALL_EXPORT MonoReflectionAssembly*
4634 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4636 MonoMethod *dest = NULL;
4638 mono_stack_walk_no_il (get_executing, &dest);
4640 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4644 ICALL_EXPORT MonoReflectionAssembly*
4645 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4647 MonoDomain* domain = mono_domain_get ();
4649 if (!domain->entry_assembly)
4652 return mono_assembly_get_object (domain, domain->entry_assembly);
4655 ICALL_EXPORT MonoReflectionAssembly*
4656 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4662 mono_stack_walk_no_il (get_executing, &dest);
4664 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
4668 mono_raise_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
4669 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4672 ICALL_EXPORT MonoString *
4673 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4674 gboolean assembly_qualified)
4676 MonoDomain *domain = mono_object_domain (object);
4677 MonoTypeNameFormat format;
4682 format = assembly_qualified ?
4683 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4684 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4686 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4688 name = mono_type_get_name_full (object->type, format);
4692 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4697 res = mono_string_new (domain, name);
4704 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
4706 MonoClass *klass = mono_class_from_mono_type (rfield->type);
4707 mono_class_init_or_throw (klass);
4708 return mono_security_core_clr_class_level (klass);
4712 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
4714 MonoClassField *field = rfield->field;
4715 return mono_security_core_clr_field_level (field, TRUE);
4719 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
4721 MonoMethod *method = rfield->method;
4722 return mono_security_core_clr_method_level (method, TRUE);
4726 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4728 static MonoMethod *create_culture = NULL;
4731 const char *pkey_ptr;
4733 MonoBoolean assembly_ref = 0;
4735 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4736 aname->major = name->major;
4737 aname->minor = name->minor;
4738 aname->build = name->build;
4739 aname->flags = name->flags;
4740 aname->revision = name->revision;
4741 aname->hashalg = name->hash_alg;
4742 aname->versioncompat = 1; /* SameMachine (default) */
4743 aname->processor_architecture = name->arch;
4745 if (by_default_version)
4746 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4749 if (absolute != NULL && *absolute != '\0') {
4750 const gchar *prepend = "file://";
4753 codebase = g_strdup (absolute);
4758 for (i = strlen (codebase) - 1; i >= 0; i--)
4759 if (codebase [i] == '\\')
4762 if (*codebase == '/' && *(codebase + 1) == '/') {
4765 prepend = "file:///";
4769 result = g_strconcat (prepend, codebase, NULL);
4775 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4779 if (!create_culture) {
4780 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4781 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4782 g_assert (create_culture);
4783 mono_method_desc_free (desc);
4786 if (name->culture) {
4787 args [0] = mono_string_new (domain, name->culture);
4788 args [1] = &assembly_ref;
4789 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4792 if (name->public_key) {
4793 pkey_ptr = (char*)name->public_key;
4794 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4796 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4797 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4798 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4799 } else if (default_publickey) {
4800 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4801 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4804 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4805 if (name->public_key_token [0]) {
4809 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4810 p = mono_array_addr (aname->keyToken, char, 0);
4812 for (i = 0, j = 0; i < 8; i++) {
4813 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4814 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4817 } else if (default_token) {
4818 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4822 ICALL_EXPORT MonoString *
4823 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4825 MonoDomain *domain = mono_object_domain (assembly);
4826 MonoAssembly *mass = assembly->assembly;
4830 name = mono_stringify_assembly_name (&mass->aname);
4831 res = mono_string_new (domain, name);
4838 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4841 MonoAssembly *mass = assembly->assembly;
4843 if (g_path_is_absolute (mass->image->name)) {
4844 fill_reflection_assembly_name (mono_object_domain (assembly),
4845 aname, &mass->aname, mass->image->name, TRUE,
4849 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4851 fill_reflection_assembly_name (mono_object_domain (assembly),
4852 aname, &mass->aname, absolute, TRUE, TRUE,
4859 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4862 MonoImageOpenStatus status = MONO_IMAGE_OK;
4865 MonoAssemblyName name;
4868 filename = mono_string_to_utf8 (fname);
4870 dirname = g_path_get_dirname (filename);
4871 replace_shadow_path (mono_domain_get (), dirname, &filename);
4874 image = mono_image_open (filename, &status);
4880 if (status == MONO_IMAGE_IMAGE_INVALID)
4881 exc = mono_get_exception_bad_image_format2 (NULL, fname);
4883 exc = mono_get_exception_file_not_found2 (NULL, fname);
4884 mono_set_pending_exception (exc);
4888 res = mono_assembly_fill_assembly_name (image, &name);
4890 mono_image_close (image);
4892 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
4896 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
4900 mono_image_close (image);
4903 ICALL_EXPORT MonoBoolean
4904 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
4905 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
4907 MonoBoolean result = FALSE;
4908 MonoDeclSecurityEntry entry;
4910 /* SecurityAction.RequestMinimum */
4911 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
4912 *minimum = entry.blob;
4913 *minLength = entry.size;
4916 /* SecurityAction.RequestOptional */
4917 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
4918 *optional = entry.blob;
4919 *optLength = entry.size;
4922 /* SecurityAction.RequestRefuse */
4923 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
4924 *refused = entry.blob;
4925 *refLength = entry.size;
4933 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
4935 guint32 attrs, visibility;
4937 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
4938 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
4939 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
4942 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
4948 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
4952 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
4955 /* we start the count from 1 because we skip the special type <Module> */
4958 for (i = 1; i < tdef->rows; ++i) {
4959 if (mono_module_type_is_visible (tdef, image, i + 1))
4963 count = tdef->rows - 1;
4965 res = mono_array_new (domain, mono_defaults.monotype_class, count);
4966 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
4968 for (i = 1; i < tdef->rows; ++i) {
4969 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
4971 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
4972 mono_loader_assert_no_error (); /* Plug any leaks */
4975 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
4977 MonoException *ex = mono_error_convert_to_exception (&error);
4978 mono_array_setref (*exceptions, count, ex);
4987 ICALL_EXPORT MonoArray*
4988 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
4990 MonoArray *res = NULL;
4991 MonoArray *exceptions = NULL;
4992 MonoImage *image = NULL;
4993 MonoTableInfo *table = NULL;
4996 int i, len, ex_count;
4998 domain = mono_object_domain (assembly);
5000 g_assert (!assembly_is_dynamic (assembly->assembly));
5001 image = assembly->assembly->image;
5002 table = &image->tables [MONO_TABLE_FILE];
5003 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5005 /* Append data from all modules in the assembly */
5006 for (i = 0; i < table->rows; ++i) {
5007 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5008 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5011 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5012 /* Append the new types to the end of the array */
5013 if (mono_array_length (res2) > 0) {
5015 MonoArray *res3, *ex3;
5017 len1 = mono_array_length (res);
5018 len2 = mono_array_length (res2);
5020 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5021 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5022 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5025 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5026 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5027 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5034 /* the ReflectionTypeLoadException must have all the types (Types property),
5035 * NULL replacing types which throws an exception. The LoaderException must
5036 * contain all exceptions for NULL items.
5039 len = mono_array_length (res);
5042 for (i = 0; i < len; i++) {
5043 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5047 klass = mono_type_get_class (t->type);
5048 if ((klass != NULL) && klass->exception_type) {
5049 /* keep the class in the list */
5050 list = g_list_append (list, klass);
5051 /* and replace Type with NULL */
5052 mono_array_setref (res, i, NULL);
5059 if (list || ex_count) {
5061 MonoException *exc = NULL;
5062 MonoArray *exl = NULL;
5063 int j, length = g_list_length (list) + ex_count;
5065 mono_loader_clear_error ();
5067 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5068 /* Types for which mono_class_get_checked () succeeded */
5069 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5070 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5071 mono_array_setref (exl, i, exc);
5073 /* Types for which it don't */
5074 for (j = 0; j < mono_array_length (exceptions); ++j) {
5075 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5077 g_assert (i < length);
5078 mono_array_setref (exl, i, exc);
5085 exc = mono_get_exception_reflection_type_load (res, exl);
5086 mono_loader_clear_error ();
5087 mono_set_pending_exception (exc);
5094 ICALL_EXPORT gboolean
5095 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5097 MonoAssemblyName aname;
5098 MonoDomain *domain = mono_object_domain (name);
5100 gboolean is_version_defined;
5101 gboolean is_token_defined;
5103 aname.public_key = NULL;
5104 val = mono_string_to_utf8 (assname);
5105 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5106 g_free ((guint8*) aname.public_key);
5111 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5112 FALSE, is_token_defined);
5114 mono_assembly_name_free (&aname);
5115 g_free ((guint8*) aname.public_key);
5121 ICALL_EXPORT MonoReflectionType*
5122 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5125 MonoDomain *domain = mono_object_domain (module);
5128 g_assert (module->image);
5130 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5131 /* These images do not have a global type */
5134 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5135 mono_error_raise_exception (&error);
5136 return mono_type_get_object (domain, &klass->byval_arg);
5140 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5142 /*if (module->image)
5143 mono_image_close (module->image);*/
5146 ICALL_EXPORT MonoString*
5147 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5149 MonoDomain *domain = mono_object_domain (module);
5151 g_assert (module->image);
5152 return mono_string_new (domain, module->image->guid);
5155 ICALL_EXPORT gpointer
5156 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5159 if (module->image && module->image->is_module_handle)
5160 return module->image->raw_data;
5163 return (gpointer) (-1);
5167 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5169 if (image_is_dynamic (image)) {
5170 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5171 *pe_kind = dyn->pe_kind;
5172 *machine = dyn->machine;
5175 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5176 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5181 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5183 return (image->md_version_major << 16) | (image->md_version_minor);
5186 ICALL_EXPORT MonoArray*
5187 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5189 MonoArray *exceptions;
5193 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5195 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5196 for (i = 0; i < mono_array_length (exceptions); ++i) {
5197 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5199 mono_set_pending_exception (ex);
5208 mono_memberref_is_method (MonoImage *image, guint32 token)
5210 if (!image_is_dynamic (image)) {
5211 guint32 cols [MONO_MEMBERREF_SIZE];
5213 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5214 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5215 mono_metadata_decode_blob_size (sig, &sig);
5216 return (*sig != 0x6);
5218 MonoClass *handle_class;
5220 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5223 return mono_defaults.methodhandle_class == handle_class;
5228 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5231 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5232 mono_array_addr (type_args, MonoType*, 0));
5234 context->class_inst = NULL;
5236 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5237 mono_array_addr (method_args, MonoType*, 0));
5239 context->method_inst = NULL;
5242 ICALL_EXPORT MonoType*
5243 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5246 int table = mono_metadata_token_table (token);
5247 int index = mono_metadata_token_index (token);
5248 MonoGenericContext context;
5251 *resolve_error = ResolveTokenError_Other;
5253 /* Validate token */
5254 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5255 (table != MONO_TABLE_TYPESPEC)) {
5256 *resolve_error = ResolveTokenError_BadTable;
5260 if (image_is_dynamic (image)) {
5261 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5262 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5263 return klass ? &klass->byval_arg : NULL;
5266 init_generic_context_from_args (&context, type_args, method_args);
5267 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5268 return klass ? &klass->byval_arg : NULL;
5271 if ((index <= 0) || (index > image->tables [table].rows)) {
5272 *resolve_error = ResolveTokenError_OutOfRange;
5276 init_generic_context_from_args (&context, type_args, method_args);
5277 klass = mono_class_get_checked (image, token, &error);
5279 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5280 mono_error_raise_exception (&error);
5283 return &klass->byval_arg;
5288 ICALL_EXPORT MonoMethod*
5289 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5292 int table = mono_metadata_token_table (token);
5293 int index = mono_metadata_token_index (token);
5294 MonoGenericContext context;
5297 *resolve_error = ResolveTokenError_Other;
5299 /* Validate token */
5300 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5301 (table != MONO_TABLE_MEMBERREF)) {
5302 *resolve_error = ResolveTokenError_BadTable;
5306 if (image_is_dynamic (image)) {
5307 if (table == MONO_TABLE_METHOD)
5308 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5310 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5311 *resolve_error = ResolveTokenError_BadTable;
5315 init_generic_context_from_args (&context, type_args, method_args);
5316 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5319 if ((index <= 0) || (index > image->tables [table].rows)) {
5320 *resolve_error = ResolveTokenError_OutOfRange;
5323 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5324 *resolve_error = ResolveTokenError_BadTable;
5328 init_generic_context_from_args (&context, type_args, method_args);
5329 method = mono_get_method_checked (image, token, NULL, &context, &error);
5330 mono_error_raise_exception (&error);
5335 ICALL_EXPORT MonoString*
5336 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5338 int index = mono_metadata_token_index (token);
5340 *error = ResolveTokenError_Other;
5342 /* Validate token */
5343 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5344 *error = ResolveTokenError_BadTable;
5348 if (image_is_dynamic (image))
5349 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5351 if ((index <= 0) || (index >= image->heap_us.size)) {
5352 *error = ResolveTokenError_OutOfRange;
5356 /* FIXME: What to do if the index points into the middle of a string ? */
5358 return mono_ldstr (mono_domain_get (), image, index);
5361 ICALL_EXPORT MonoClassField*
5362 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5366 int table = mono_metadata_token_table (token);
5367 int index = mono_metadata_token_index (token);
5368 MonoGenericContext context;
5369 MonoClassField *field;
5371 *resolve_error = ResolveTokenError_Other;
5373 /* Validate token */
5374 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5375 *resolve_error = ResolveTokenError_BadTable;
5379 if (image_is_dynamic (image)) {
5380 if (table == MONO_TABLE_FIELD)
5381 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5383 if (mono_memberref_is_method (image, token)) {
5384 *resolve_error = ResolveTokenError_BadTable;
5388 init_generic_context_from_args (&context, type_args, method_args);
5389 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5392 if ((index <= 0) || (index > image->tables [table].rows)) {
5393 *resolve_error = ResolveTokenError_OutOfRange;
5396 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5397 *resolve_error = ResolveTokenError_BadTable;
5401 init_generic_context_from_args (&context, type_args, method_args);
5402 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5403 mono_error_raise_exception (&error);
5409 ICALL_EXPORT MonoObject*
5410 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5412 int table = mono_metadata_token_table (token);
5414 *error = ResolveTokenError_Other;
5417 case MONO_TABLE_TYPEDEF:
5418 case MONO_TABLE_TYPEREF:
5419 case MONO_TABLE_TYPESPEC: {
5420 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5422 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5426 case MONO_TABLE_METHOD:
5427 case MONO_TABLE_METHODSPEC: {
5428 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5430 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5434 case MONO_TABLE_FIELD: {
5435 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5437 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5441 case MONO_TABLE_MEMBERREF:
5442 if (mono_memberref_is_method (image, token)) {
5443 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5445 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5450 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5452 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5459 *error = ResolveTokenError_BadTable;
5465 ICALL_EXPORT MonoArray*
5466 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5468 int table = mono_metadata_token_table (token);
5469 int idx = mono_metadata_token_index (token);
5470 MonoTableInfo *tables = image->tables;
5475 *error = ResolveTokenError_OutOfRange;
5477 /* FIXME: Support other tables ? */
5478 if (table != MONO_TABLE_STANDALONESIG)
5481 if (image_is_dynamic (image))
5484 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5487 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5489 ptr = mono_metadata_blob_heap (image, sig);
5490 len = mono_metadata_decode_blob_size (ptr, &ptr);
5492 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5493 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5497 ICALL_EXPORT MonoReflectionType*
5498 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5501 int isbyref = 0, rank;
5502 char *str = mono_string_to_utf8 (smodifiers);
5505 klass = mono_class_from_mono_type (tb->type.type);
5507 /* logic taken from mono_reflection_parse_type(): keep in sync */
5511 if (isbyref) { /* only one level allowed by the spec */
5518 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5521 klass = mono_ptr_class_get (&klass->byval_arg);
5522 mono_class_init (klass);
5533 else if (*p != '*') { /* '*' means unknown lower bound */
5544 klass = mono_array_class_get (klass, rank);
5545 mono_class_init (klass);
5552 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5555 ICALL_EXPORT MonoBoolean
5556 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5562 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5568 check_for_invalid_type (MonoClass *klass)
5572 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5575 name = mono_type_get_full_name (klass);
5576 str = mono_string_new (mono_domain_get (), name);
5578 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5581 ICALL_EXPORT MonoReflectionType *
5582 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5584 MonoClass *klass, *aklass;
5586 klass = mono_class_from_mono_type (type->type);
5587 check_for_invalid_type (klass);
5589 if (rank == 0) //single dimentional array
5590 aklass = mono_array_class_get (klass, 1);
5592 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5594 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5597 ICALL_EXPORT MonoReflectionType *
5598 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5602 klass = mono_class_from_mono_type (type->type);
5603 mono_class_init_or_throw (klass);
5604 check_for_invalid_type (klass);
5606 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5609 ICALL_EXPORT MonoReflectionType *
5610 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5612 MonoClass *klass, *pklass;
5614 klass = mono_class_from_mono_type (type->type);
5615 mono_class_init_or_throw (klass);
5616 check_for_invalid_type (klass);
5618 pklass = mono_ptr_class_get (type->type);
5620 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5623 ICALL_EXPORT MonoObject *
5624 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5625 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5627 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5628 MonoObject *delegate;
5630 MonoMethod *method = info->method;
5632 mono_class_init_or_throw (delegate_class);
5634 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5636 if (mono_security_core_clr_enabled ()) {
5637 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5641 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5643 if (method_is_dynamic (method)) {
5644 /* Creating a trampoline would leak memory */
5645 func = mono_compile_method (method);
5647 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5648 method = mono_object_get_virtual_method (target, method);
5649 func = mono_create_ftnptr (mono_domain_get (),
5650 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5653 mono_delegate_ctor_with_method (delegate, target, func, method);
5658 ICALL_EXPORT MonoMulticastDelegate *
5659 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
5661 MonoMulticastDelegate *ret;
5663 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
5665 ret = (MonoMulticastDelegate*) mono_object_new (mono_object_domain (delegate), mono_object_class (delegate));
5666 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
5671 ICALL_EXPORT MonoReflectionMethod*
5672 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
5674 return mono_method_get_object (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target));
5679 static inline gint32
5680 mono_array_get_byte_length (MonoArray *array)
5686 klass = array->obj.vtable->klass;
5688 if (array->bounds == NULL)
5689 length = array->max_length;
5692 for (i = 0; i < klass->rank; ++ i)
5693 length *= array->bounds [i].length;
5696 switch (klass->element_class->byval_arg.type) {
5699 case MONO_TYPE_BOOLEAN:
5703 case MONO_TYPE_CHAR:
5711 return length * sizeof (gpointer);
5722 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
5724 return mono_array_get_byte_length (array);
5728 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
5730 return mono_array_get (array, gint8, idx);
5734 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
5736 mono_array_set (array, gint8, idx, value);
5739 ICALL_EXPORT MonoBoolean
5740 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
5742 guint8 *src_buf, *dest_buf;
5745 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
5749 g_assert (count >= 0);
5751 /* This is called directly from the class libraries without going through the managed wrapper */
5752 MONO_CHECK_ARG_NULL (src, FALSE);
5753 MONO_CHECK_ARG_NULL (dest, FALSE);
5755 /* watch out for integer overflow */
5756 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
5759 src_buf = (guint8 *)src->vector + src_offset;
5760 dest_buf = (guint8 *)dest->vector + dest_offset;
5763 memcpy (dest_buf, src_buf, count);
5765 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
5770 #ifndef DISABLE_REMOTING
5771 ICALL_EXPORT MonoObject *
5772 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
5774 MonoDomain *domain = mono_object_domain (this_obj);
5776 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
5777 MonoTransparentProxy *tp;
5781 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
5782 tp = (MonoTransparentProxy*) res;
5784 MONO_OBJECT_SETREF (tp, rp, rp);
5785 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
5786 klass = mono_class_from_mono_type (type);
5788 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
5789 mono_class_setup_vtable (klass);
5790 if (klass->exception_type)
5791 mono_raise_exception (mono_class_get_exception_for_failure (klass));
5793 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
5794 tp->remote_class = mono_remote_class (domain, class_name, klass);
5796 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
5800 ICALL_EXPORT MonoReflectionType *
5801 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
5803 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
5807 /* System.Environment */
5810 ves_icall_System_Environment_get_UserName (void)
5812 /* using glib is more portable */
5813 return mono_string_new (mono_domain_get (), g_get_user_name ());
5817 ICALL_EXPORT MonoString *
5818 ves_icall_System_Environment_get_MachineName (void)
5820 #if defined (HOST_WIN32)
5825 len = MAX_COMPUTERNAME_LENGTH + 1;
5826 buf = g_new (gunichar2, len);
5829 if (GetComputerName (buf, (PDWORD) &len))
5830 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
5834 #elif !defined(DISABLE_SOCKETS)
5838 #if defined _SC_HOST_NAME_MAX
5839 n = sysconf (_SC_HOST_NAME_MAX);
5843 buf = g_malloc (n+1);
5845 if (gethostname (buf, n) == 0){
5847 result = mono_string_new (mono_domain_get (), buf);
5854 return mono_string_new (mono_domain_get (), "mono");
5859 ves_icall_System_Environment_get_Platform (void)
5861 #if defined (TARGET_WIN32)
5864 #elif defined(__MACH__)
5867 // Notice that the value is hidden from user code, and only exposed
5868 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
5869 // define and making assumptions based on Unix/128/4 values before there
5870 // was a MacOS define. Lots of code would assume that not-Unix meant
5871 // Windows, but in this case, it would be OSX.
5880 ICALL_EXPORT MonoString *
5881 ves_icall_System_Environment_get_NewLine (void)
5883 #if defined (HOST_WIN32)
5884 return mono_string_new (mono_domain_get (), "\r\n");
5886 return mono_string_new (mono_domain_get (), "\n");
5890 ICALL_EXPORT MonoBoolean
5891 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
5893 #if SIZEOF_VOID_P == 8
5897 gboolean isWow64Process = FALSE;
5898 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
5899 return (MonoBoolean)isWow64Process;
5901 #elif defined(HAVE_SYS_UTSNAME_H)
5902 struct utsname name;
5904 if (uname (&name) >= 0) {
5905 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
5912 ICALL_EXPORT MonoString *
5913 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
5921 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
5922 value = g_getenv (utf8_name);
5929 return mono_string_new (mono_domain_get (), value);
5933 * There is no standard way to get at environ.
5936 #ifndef __MINGW32_VERSION
5937 #if defined(__APPLE__)
5938 #if defined (TARGET_OSX)
5939 /* Apple defines this in crt_externs.h but doesn't provide that header for
5940 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
5941 * in fact exist on all implementations (so far)
5943 gchar ***_NSGetEnviron(void);
5944 #define environ (*_NSGetEnviron())
5946 static char *mono_environ[1] = { NULL };
5947 #define environ mono_environ
5948 #endif /* defined (TARGET_OSX) */
5956 ICALL_EXPORT MonoArray *
5957 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
5968 env_strings = GetEnvironmentStrings();
5971 env_string = env_strings;
5972 while (*env_string != '\0') {
5973 /* weird case that MS seems to skip */
5974 if (*env_string != '=')
5976 while (*env_string != '\0')
5982 domain = mono_domain_get ();
5983 names = mono_array_new (domain, mono_defaults.string_class, n);
5987 env_string = env_strings;
5988 while (*env_string != '\0') {
5989 /* weird case that MS seems to skip */
5990 if (*env_string != '=') {
5991 equal_str = wcschr(env_string, '=');
5992 g_assert(equal_str);
5993 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
5994 mono_array_setref (names, n, str);
5997 while (*env_string != '\0')
6002 FreeEnvironmentStrings (env_strings);
6015 for (e = environ; *e != 0; ++ e)
6018 domain = mono_domain_get ();
6019 names = mono_array_new (domain, mono_defaults.string_class, n);
6022 for (e = environ; *e != 0; ++ e) {
6023 parts = g_strsplit (*e, "=", 2);
6025 str = mono_string_new (domain, *parts);
6026 mono_array_setref (names, n, str);
6039 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6041 #if !GLIB_CHECK_VERSION(2,4,0)
6042 #define g_setenv(a,b,c) setenv(a,b,c)
6043 #define g_unsetenv(a) unsetenv(a)
6047 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6050 gunichar2 *utf16_name, *utf16_value;
6052 gchar *utf8_name, *utf8_value;
6057 utf16_name = mono_string_to_utf16 (name);
6058 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6059 SetEnvironmentVariable (utf16_name, NULL);
6060 g_free (utf16_name);
6064 utf16_value = mono_string_to_utf16 (value);
6066 SetEnvironmentVariable (utf16_name, utf16_value);
6068 g_free (utf16_name);
6069 g_free (utf16_value);
6071 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6073 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6074 g_unsetenv (utf8_name);
6079 utf8_value = mono_string_to_utf8_checked (value, &error);
6080 if (!mono_error_ok (&error)) {
6082 mono_error_raise_exception (&error);
6084 g_setenv (utf8_name, utf8_value, TRUE);
6087 g_free (utf8_value);
6092 ves_icall_System_Environment_Exit (int result)
6094 mono_environment_exitcode_set (result);
6096 /* FIXME: There are some cleanup hangs that should be worked out, but
6097 * if the program is going to exit, everything will be cleaned up when
6098 * NaCl exits anyway.
6100 #ifndef __native_client__
6101 if (!mono_runtime_try_shutdown ())
6102 mono_thread_exit ();
6104 /* Suspend all managed threads since the runtime is going away */
6105 mono_thread_suspend_all_other_threads ();
6107 mono_runtime_quit ();
6110 /* we may need to do some cleanup here... */
6114 ICALL_EXPORT MonoString*
6115 ves_icall_System_Environment_GetGacPath (void)
6117 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6120 ICALL_EXPORT MonoString*
6121 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6123 #if defined (HOST_WIN32)
6124 #ifndef CSIDL_FLAG_CREATE
6125 #define CSIDL_FLAG_CREATE 0x8000
6128 WCHAR path [MAX_PATH];
6129 /* Create directory if no existing */
6130 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6134 return mono_string_new_utf16 (mono_domain_get (), path, len);
6137 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6139 return mono_string_new (mono_domain_get (), "");
6142 ICALL_EXPORT MonoArray *
6143 ves_icall_System_Environment_GetLogicalDrives (void)
6145 gunichar2 buf [256], *ptr, *dname;
6147 guint initial_size = 127, size = 128;
6150 MonoString *drivestr;
6151 MonoDomain *domain = mono_domain_get ();
6157 while (size > initial_size) {
6158 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6159 if (size > initial_size) {
6162 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6163 initial_size = size;
6177 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6182 while (*u16) { u16++; len ++; }
6183 drivestr = mono_string_new_utf16 (domain, dname, len);
6184 mono_array_setref (result, ndrives++, drivestr);
6194 ICALL_EXPORT MonoString *
6195 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6197 gunichar2 volume_name [MAX_PATH + 1];
6199 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6201 return mono_string_from_utf16 (volume_name);
6204 ICALL_EXPORT MonoString *
6205 ves_icall_System_Environment_InternalGetHome (void)
6207 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6210 static const char *encodings [] = {
6212 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6213 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6214 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6216 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6217 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6218 "x_unicode_2_0_utf_7",
6220 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6221 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6223 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6226 "unicodefffe", "utf_16be",
6233 * Returns the internal codepage, if the value of "int_code_page" is
6234 * 1 at entry, and we can not compute a suitable code page number,
6235 * returns the code page as a string
6237 ICALL_EXPORT MonoString*
6238 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6243 char *codepage = NULL;
6245 int want_name = *int_code_page;
6248 *int_code_page = -1;
6250 g_get_charset (&cset);
6251 c = codepage = strdup (cset);
6252 for (c = codepage; *c; c++){
6253 if (isascii (*c) && isalpha (*c))
6258 /* g_print ("charset: %s\n", cset); */
6260 /* handle some common aliases */
6263 for (i = 0; p != 0; ){
6266 p = encodings [++i];
6269 if (strcmp (p, codepage) == 0){
6270 *int_code_page = code;
6273 p = encodings [++i];
6276 if (strstr (codepage, "utf_8") != NULL)
6277 *int_code_page |= 0x10000000;
6280 if (want_name && *int_code_page == -1)
6281 return mono_string_new (mono_domain_get (), cset);
6286 ICALL_EXPORT MonoBoolean
6287 ves_icall_System_Environment_get_HasShutdownStarted (void)
6289 if (mono_runtime_is_shutting_down ())
6292 if (mono_domain_is_unloading (mono_domain_get ()))
6299 ves_icall_System_Environment_BroadcastSettingChange (void)
6302 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6307 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
6313 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
6314 MonoReflectionMethod *method,
6315 MonoArray *out_args)
6317 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
6320 #ifndef DISABLE_REMOTING
6321 ICALL_EXPORT MonoBoolean
6322 ves_icall_IsTransparentProxy (MonoObject *proxy)
6327 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6333 ICALL_EXPORT MonoReflectionMethod *
6334 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6335 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6339 MonoMethod **vtable;
6340 MonoMethod *res = NULL;
6342 MONO_CHECK_ARG_NULL (rtype, NULL);
6343 MONO_CHECK_ARG_NULL (rmethod, NULL);
6345 method = rmethod->method;
6346 klass = mono_class_from_mono_type (rtype->type);
6347 mono_class_init_or_throw (klass);
6349 if (MONO_CLASS_IS_INTERFACE (klass))
6352 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6355 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6356 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6362 mono_class_setup_vtable (klass);
6363 vtable = klass->vtable;
6365 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6366 gboolean variance_used = FALSE;
6367 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6368 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6370 res = vtable [offs + method->slot];
6372 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6375 if (method->slot != -1)
6376 res = vtable [method->slot];
6382 return mono_method_get_object (mono_domain_get (), res, NULL);
6386 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6391 klass = mono_class_from_mono_type (type->type);
6392 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6394 mono_vtable_set_is_remote (vtable, enable);
6397 #else /* DISABLE_REMOTING */
6400 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6402 g_assert_not_reached ();
6407 ICALL_EXPORT MonoObject *
6408 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6413 domain = mono_object_domain (type);
6414 klass = mono_class_from_mono_type (type->type);
6415 mono_class_init_or_throw (klass);
6417 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
6418 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6422 if (klass->rank >= 1) {
6423 g_assert (klass->rank == 1);
6424 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6426 /* Bypass remoting object creation check */
6427 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6431 ICALL_EXPORT MonoString *
6432 ves_icall_System_IO_get_temp_path (void)
6434 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6437 #ifndef PLATFORM_NO_DRIVEINFO
6438 ICALL_EXPORT MonoBoolean
6439 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6440 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6444 ULARGE_INTEGER wapi_free_bytes_avail;
6445 ULARGE_INTEGER wapi_total_number_of_bytes;
6446 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6448 *error = ERROR_SUCCESS;
6449 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6450 &wapi_total_number_of_free_bytes);
6453 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6454 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6455 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6457 *free_bytes_avail = 0;
6458 *total_number_of_bytes = 0;
6459 *total_number_of_free_bytes = 0;
6460 *error = GetLastError ();
6466 ICALL_EXPORT guint32
6467 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6469 return GetDriveType (mono_string_chars (root_path_name));
6473 ICALL_EXPORT gpointer
6474 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6476 return mono_compile_method (method);
6479 ICALL_EXPORT MonoString *
6480 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6485 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6487 #if defined (HOST_WIN32)
6488 /* Avoid mixing '/' and '\\' */
6491 for (i = strlen (path) - 1; i >= 0; i--)
6492 if (path [i] == '/')
6496 mcpath = mono_string_new (mono_domain_get (), path);
6503 get_bundled_app_config (void)
6505 const gchar *app_config;
6508 gchar *config_file_name, *config_file_path;
6509 gsize len, config_file_path_length, config_ext_length;
6512 domain = mono_domain_get ();
6513 file = domain->setup->configuration_file;
6514 if (!file || file->length == 0)
6517 // Retrieve config file and remove the extension
6518 config_file_name = mono_string_to_utf8 (file);
6519 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6520 if (!config_file_path)
6521 config_file_path = config_file_name;
6523 config_file_path_length = strlen (config_file_path);
6524 config_ext_length = strlen (".config");
6525 if (config_file_path_length <= config_ext_length)
6528 len = config_file_path_length - config_ext_length;
6529 module = (gchar *)g_malloc0 (len + 1);
6530 memcpy (module, config_file_path, len);
6531 // Get the config file from the module name
6532 app_config = mono_config_string_for_assembly_file (module);
6535 if (config_file_name != config_file_path)
6536 g_free (config_file_name);
6537 g_free (config_file_path);
6542 return mono_string_new (mono_domain_get (), app_config);
6546 get_bundled_machine_config (void)
6548 const gchar *machine_config;
6550 machine_config = mono_get_machine_config ();
6552 if (!machine_config)
6555 return mono_string_new (mono_domain_get (), machine_config);
6558 ICALL_EXPORT MonoString *
6559 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6564 path = g_path_get_dirname (mono_get_config_dir ());
6566 #if defined (HOST_WIN32)
6567 /* Avoid mixing '/' and '\\' */
6570 for (i = strlen (path) - 1; i >= 0; i--)
6571 if (path [i] == '/')
6575 ipath = mono_string_new (mono_domain_get (), path);
6581 ICALL_EXPORT gboolean
6582 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6584 MonoPEResourceDataEntry *entry;
6587 if (!assembly || !result || !size)
6592 image = assembly->assembly->image;
6593 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6597 *result = mono_image_rva_map (image, entry->rde_data_offset);
6602 *size = entry->rde_size;
6607 ICALL_EXPORT MonoBoolean
6608 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6610 return mono_is_debugger_attached ();
6613 ICALL_EXPORT MonoBoolean
6614 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
6616 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
6617 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
6623 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
6625 if (mono_get_runtime_callbacks ()->debug_log)
6626 mono_get_runtime_callbacks ()->debug_log (level, category, message);
6630 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6632 #if defined (HOST_WIN32)
6633 OutputDebugString (mono_string_chars (message));
6635 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6639 /* Only used for value types */
6640 ICALL_EXPORT MonoObject *
6641 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6646 domain = mono_object_domain (type);
6647 klass = mono_class_from_mono_type (type->type);
6648 mono_class_init_or_throw (klass);
6650 if (mono_class_is_nullable (klass))
6651 /* No arguments -> null */
6654 return mono_object_new (domain, klass);
6657 ICALL_EXPORT MonoReflectionMethod *
6658 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6660 MonoClass *klass, *parent;
6661 MonoGenericContext *generic_inst = NULL;
6662 MonoMethod *method = m->method;
6663 MonoMethod *result = NULL;
6666 if (method->klass == NULL)
6669 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6670 MONO_CLASS_IS_INTERFACE (method->klass) ||
6671 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6674 slot = mono_method_get_vtable_slot (method);
6678 klass = method->klass;
6679 if (klass->generic_class) {
6680 generic_inst = mono_class_get_context (klass);
6681 klass = klass->generic_class->container_class;
6685 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6686 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6687 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
6688 or klass is the generic container class and generic_inst is the instantiation.
6690 when we go to the parent, if the parent is an open constructed type, we need to
6691 replace the type parameters by the definitions from the generic_inst, and then take it
6692 apart again into the klass and the generic_inst.
6694 For cases like this:
6695 class C<T> : B<T, int> {
6696 public override void Foo () { ... }
6698 class B<U,V> : A<HashMap<U,V>> {
6699 public override void Foo () { ... }
6702 public virtual void Foo () { ... }
6705 if at each iteration the parent isn't open, we can skip inflating it. if at some
6706 iteration the parent isn't generic (after possible inflation), we set generic_inst to
6709 MonoGenericContext *parent_inst = NULL;
6710 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
6712 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
6713 mono_error_raise_exception(&error);
6715 if (parent->generic_class) {
6716 parent_inst = mono_class_get_context (parent);
6717 parent = parent->generic_class->container_class;
6720 mono_class_setup_vtable (parent);
6721 if (parent->vtable_size <= slot)
6724 generic_inst = parent_inst;
6727 klass = klass->parent;
6730 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
6732 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6733 mono_error_raise_exception(&error);
6735 generic_inst = NULL;
6737 if (klass->generic_class) {
6738 generic_inst = mono_class_get_context (klass);
6739 klass = klass->generic_class->container_class;
6746 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
6747 mono_error_raise_exception(&error);
6750 if (klass == method->klass)
6753 /*This is possible if definition == FALSE.
6754 * Do it here to be really sure we don't read invalid memory.
6756 if (slot >= klass->vtable_size)
6759 mono_class_setup_vtable (klass);
6761 result = klass->vtable [slot];
6762 if (result == NULL) {
6763 /* It is an abstract method */
6764 gpointer iter = NULL;
6765 while ((result = mono_class_get_methods (klass, &iter)))
6766 if (result->slot == slot)
6773 return mono_method_get_object (mono_domain_get (), result, NULL);
6776 ICALL_EXPORT MonoString*
6777 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6779 MonoMethod *method = m->method;
6781 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6786 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6788 iter->sig = *(MonoMethodSignature**)argsp;
6790 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6791 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6794 /* FIXME: it's not documented what start is exactly... */
6798 iter->args = argsp + sizeof (gpointer);
6800 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6802 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6805 ICALL_EXPORT MonoTypedRef
6806 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6808 guint32 i, arg_size;
6812 i = iter->sig->sentinelpos + iter->next_arg;
6814 g_assert (i < iter->sig->param_count);
6816 res.type = iter->sig->params [i];
6817 res.klass = mono_class_from_mono_type (res.type);
6818 arg_size = mono_type_stack_size (res.type, &align);
6819 #if defined(__arm__) || defined(__mips__)
6820 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6822 res.value = iter->args;
6823 #if defined(__native_client__) && SIZEOF_REGISTER == 8
6824 /* Values are stored as 8 byte register sized objects, but 'value'
6825 * is dereferenced as a pointer in other routines.
6827 res.value = (char*)res.value + 4;
6829 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6830 if (arg_size <= sizeof (gpointer)) {
6832 int padding = arg_size - mono_type_size (res.type, &dummy);
6833 res.value = (guint8*)res.value + padding;
6836 iter->args = (char*)iter->args + arg_size;
6839 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6844 ICALL_EXPORT MonoTypedRef
6845 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
6847 guint32 i, arg_size;
6851 i = iter->sig->sentinelpos + iter->next_arg;
6853 g_assert (i < iter->sig->param_count);
6855 while (i < iter->sig->param_count) {
6856 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
6858 res.type = iter->sig->params [i];
6859 res.klass = mono_class_from_mono_type (res.type);
6860 /* FIXME: endianess issue... */
6861 arg_size = mono_type_stack_size (res.type, &align);
6862 #if defined(__arm__) || defined(__mips__)
6863 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
6865 res.value = iter->args;
6866 iter->args = (char*)iter->args + arg_size;
6868 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
6871 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
6879 ICALL_EXPORT MonoType*
6880 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
6884 i = iter->sig->sentinelpos + iter->next_arg;
6886 g_assert (i < iter->sig->param_count);
6888 return iter->sig->params [i];
6891 ICALL_EXPORT MonoObject*
6892 mono_TypedReference_ToObject (MonoTypedRef* tref)
6894 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
6895 MonoObject** objp = (MonoObject **)tref->value;
6899 return mono_value_box (mono_domain_get (), tref->klass, tref->value);
6902 ICALL_EXPORT MonoTypedRef
6903 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
6906 MonoReflectionField *f;
6908 MonoType *ftype = NULL;
6912 memset (&res, 0, sizeof (res));
6915 g_assert (mono_array_length (fields) > 0);
6917 klass = target->vtable->klass;
6919 for (i = 0; i < mono_array_length (fields); ++i) {
6920 f = mono_array_get (fields, MonoReflectionField*, i);
6922 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
6925 if (f->field->parent != klass) {
6926 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
6930 p = (guint8*)target + f->field->offset;
6932 p += f->field->offset - sizeof (MonoObject);
6933 klass = mono_class_from_mono_type (f->field->type);
6934 ftype = f->field->type;
6938 res.klass = mono_class_from_mono_type (ftype);
6945 prelink_method (MonoMethod *method)
6947 const char *exc_class, *exc_arg;
6948 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
6950 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
6952 mono_raise_exception(
6953 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
6955 /* create the wrapper, too? */
6959 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
6961 prelink_method (method->method);
6965 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
6967 MonoClass *klass = mono_class_from_mono_type (type->type);
6969 gpointer iter = NULL;
6971 mono_class_init_or_throw (klass);
6973 while ((m = mono_class_get_methods (klass, &iter)))
6977 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
6979 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
6980 gint32 const **exponents,
6981 gunichar2 const **digitLowerTable,
6982 gunichar2 const **digitUpperTable,
6983 gint64 const **tenPowersList,
6984 gint32 const **decHexDigits)
6986 *mantissas = Formatter_MantissaBitsTable;
6987 *exponents = Formatter_TensExponentTable;
6988 *digitLowerTable = Formatter_DigitLowerTable;
6989 *digitUpperTable = Formatter_DigitUpperTable;
6990 *tenPowersList = Formatter_TenPowersList;
6991 *decHexDigits = Formatter_DecHexDigits;
6995 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
6996 * and avoid useless allocations.
7001 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7005 for (i = 0; i < type->num_mods; ++i) {
7006 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7011 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7013 for (i = 0; i < type->num_mods; ++i) {
7014 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7016 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7017 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7018 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7025 ICALL_EXPORT MonoArray*
7026 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7028 MonoType *type = param->ClassImpl->type;
7029 MonoClass *member_class = mono_object_class (param->MemberImpl);
7030 MonoMethod *method = NULL;
7033 MonoMethodSignature *sig;
7035 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7036 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7037 method = rmethod->method;
7038 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7039 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7040 if (!(method = prop->property->get))
7041 method = prop->property->set;
7044 char *type_name = mono_type_get_full_name (member_class);
7045 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7046 MonoException *ex = mono_get_exception_not_supported (msg);
7049 mono_set_pending_exception (ex);
7053 image = method->klass->image;
7054 pos = param->PositionImpl;
7055 sig = mono_method_signature (method);
7059 type = sig->params [pos];
7061 return type_array_from_modifiers (image, type, optional);
7065 get_property_type (MonoProperty *prop)
7067 MonoMethodSignature *sig;
7069 sig = mono_method_signature (prop->get);
7071 } else if (prop->set) {
7072 sig = mono_method_signature (prop->set);
7073 return sig->params [sig->param_count - 1];
7078 ICALL_EXPORT MonoArray*
7079 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7081 MonoType *type = get_property_type (property->property);
7082 MonoImage *image = property->klass->image;
7086 return type_array_from_modifiers (image, type, optional);
7090 *Construct a MonoType suited to be used to decode a constant blob object.
7092 * @type is the target type which will be constructed
7093 * @blob_type is the blob type, for example, that comes from the constant table
7094 * @real_type is the expected constructed type.
7097 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7099 type->type = blob_type;
7100 type->data.klass = NULL;
7101 if (blob_type == MONO_TYPE_CLASS)
7102 type->data.klass = mono_defaults.object_class;
7103 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7104 /* For enums, we need to use the base type */
7105 type->type = MONO_TYPE_VALUETYPE;
7106 type->data.klass = mono_class_from_mono_type (real_type);
7108 type->data.klass = mono_class_from_mono_type (real_type);
7111 ICALL_EXPORT MonoObject*
7112 property_info_get_default_value (MonoReflectionProperty *property)
7115 MonoProperty *prop = property->property;
7116 MonoType *type = get_property_type (prop);
7117 MonoDomain *domain = mono_object_domain (property);
7118 MonoTypeEnum def_type;
7119 const char *def_value;
7122 mono_class_init (prop->parent);
7124 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7125 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7129 def_value = mono_class_get_property_default_value (prop, &def_type);
7131 mono_type_from_blob_type (&blob_type, def_type, type);
7132 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7137 ICALL_EXPORT MonoBoolean
7138 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7140 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7141 MonoCustomAttrInfo *cinfo;
7144 mono_class_init_or_throw (attr_class);
7146 cinfo = mono_reflection_get_custom_attrs_info (obj);
7149 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7151 mono_custom_attrs_free (cinfo);
7155 ICALL_EXPORT MonoArray*
7156 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7158 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7163 mono_class_init_or_throw (attr_class);
7165 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7166 mono_error_raise_exception (&error);
7168 if (mono_loader_get_last_error ()) {
7169 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7176 ICALL_EXPORT MonoString*
7177 ves_icall_Mono_Runtime_GetDisplayName (void)
7180 MonoString *display_name;
7182 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7183 display_name = mono_string_new (mono_domain_get (), info);
7185 return display_name;
7188 ICALL_EXPORT MonoString*
7189 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7191 MonoString *message;
7195 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7196 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7199 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7201 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7208 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7211 char *path_str = mono_string_to_utf8 (path);
7213 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7221 #ifndef DISABLE_ICALL_TABLES
7223 #define ICALL_TYPE(id,name,first)
7224 #define ICALL(id,name,func) Icall_ ## id,
7227 #include "metadata/icall-def.h"
7233 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7234 #define ICALL(id,name,func)
7236 #include "metadata/icall-def.h"
7242 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7243 #define ICALL(id,name,func)
7245 guint16 first_icall;
7248 static const IcallTypeDesc
7249 icall_type_descs [] = {
7250 #include "metadata/icall-def.h"
7254 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7257 #define ICALL_TYPE(id,name,first)
7260 #ifdef HAVE_ARRAY_ELEM_INIT
7261 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7262 #define MSGSTRFIELD1(line) str##line
7264 static const struct msgstrtn_t {
7265 #define ICALL(id,name,func)
7267 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7268 #include "metadata/icall-def.h"
7270 } icall_type_names_str = {
7271 #define ICALL_TYPE(id,name,first) (name),
7272 #include "metadata/icall-def.h"
7275 static const guint16 icall_type_names_idx [] = {
7276 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7277 #include "metadata/icall-def.h"
7280 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7282 static const struct msgstr_t {
7284 #define ICALL_TYPE(id,name,first)
7285 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7286 #include "metadata/icall-def.h"
7288 } icall_names_str = {
7289 #define ICALL(id,name,func) (name),
7290 #include "metadata/icall-def.h"
7293 static const guint16 icall_names_idx [] = {
7294 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7295 #include "metadata/icall-def.h"
7298 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7304 #define ICALL_TYPE(id,name,first) name,
7305 #define ICALL(id,name,func)
7306 static const char* const
7307 icall_type_names [] = {
7308 #include "metadata/icall-def.h"
7312 #define icall_type_name_get(id) (icall_type_names [(id)])
7316 #define ICALL_TYPE(id,name,first)
7317 #define ICALL(id,name,func) name,
7318 static const char* const
7320 #include "metadata/icall-def.h"
7323 #define icall_name_get(id) icall_names [(id)]
7325 #endif /* !HAVE_ARRAY_ELEM_INIT */
7329 #define ICALL_TYPE(id,name,first)
7330 #define ICALL(id,name,func) func,
7331 static const gconstpointer
7332 icall_functions [] = {
7333 #include "metadata/icall-def.h"
7337 #ifdef ENABLE_ICALL_SYMBOL_MAP
7340 #define ICALL_TYPE(id,name,first)
7341 #define ICALL(id,name,func) #func,
7342 static const gconstpointer
7343 icall_symbols [] = {
7344 #include "metadata/icall-def.h"
7349 #endif /* DISABLE_ICALL_TABLES */
7351 static mono_mutex_t icall_mutex;
7352 static GHashTable *icall_hash = NULL;
7353 static GHashTable *jit_icall_hash_name = NULL;
7354 static GHashTable *jit_icall_hash_addr = NULL;
7357 mono_icall_init (void)
7359 #ifndef DISABLE_ICALL_TABLES
7362 /* check that tables are sorted: disable in release */
7365 const char *prev_class = NULL;
7366 const char *prev_method;
7368 for (i = 0; i < Icall_type_num; ++i) {
7369 const IcallTypeDesc *desc;
7372 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7373 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7374 prev_class = icall_type_name_get (i);
7375 desc = &icall_type_descs [i];
7376 num_icalls = icall_desc_num_icalls (desc);
7377 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7378 for (j = 0; j < num_icalls; ++j) {
7379 const char *methodn = icall_name_get (desc->first_icall + j);
7380 if (prev_method && strcmp (prev_method, methodn) >= 0)
7381 g_print ("method %s should come before method %s\n", methodn, prev_method);
7382 prev_method = methodn;
7388 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7389 mono_os_mutex_init (&icall_mutex);
7393 mono_icall_lock (void)
7395 mono_locks_os_acquire (&icall_mutex, IcallLock);
7399 mono_icall_unlock (void)
7401 mono_locks_os_release (&icall_mutex, IcallLock);
7405 mono_icall_cleanup (void)
7407 g_hash_table_destroy (icall_hash);
7408 g_hash_table_destroy (jit_icall_hash_name);
7409 g_hash_table_destroy (jit_icall_hash_addr);
7410 mono_os_mutex_destroy (&icall_mutex);
7414 mono_add_internal_call (const char *name, gconstpointer method)
7418 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7420 mono_icall_unlock ();
7423 #ifndef DISABLE_ICALL_TABLES
7425 #ifdef HAVE_ARRAY_ELEM_INIT
7427 compare_method_imap (const void *key, const void *elem)
7429 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7430 return strcmp (key, method_name);
7434 find_method_icall (const IcallTypeDesc *imap, const char *name)
7436 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);
7439 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7443 compare_class_imap (const void *key, const void *elem)
7445 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7446 return strcmp (key, class_name);
7449 static const IcallTypeDesc*
7450 find_class_icalls (const char *name)
7452 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);
7455 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7458 #else /* HAVE_ARRAY_ELEM_INIT */
7461 compare_method_imap (const void *key, const void *elem)
7463 const char** method_name = (const char**)elem;
7464 return strcmp (key, *method_name);
7468 find_method_icall (const IcallTypeDesc *imap, const char *name)
7470 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7473 return (gpointer)icall_functions [(nameslot - icall_names)];
7477 compare_class_imap (const void *key, const void *elem)
7479 const char** class_name = (const char**)elem;
7480 return strcmp (key, *class_name);
7483 static const IcallTypeDesc*
7484 find_class_icalls (const char *name)
7486 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7489 return &icall_type_descs [nameslot - icall_type_names];
7492 #endif /* HAVE_ARRAY_ELEM_INIT */
7494 #endif /* DISABLE_ICALL_TABLES */
7497 * we should probably export this as an helper (handle nested types).
7498 * Returns the number of chars written in buf.
7501 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7503 int nspacelen, cnamelen;
7504 nspacelen = strlen (klass->name_space);
7505 cnamelen = strlen (klass->name);
7506 if (nspacelen + cnamelen + 2 > bufsize)
7509 memcpy (buf, klass->name_space, nspacelen);
7510 buf [nspacelen ++] = '.';
7512 memcpy (buf + nspacelen, klass->name, cnamelen);
7513 buf [nspacelen + cnamelen] = 0;
7514 return nspacelen + cnamelen;
7517 #ifdef DISABLE_ICALL_TABLES
7519 no_icall_table (void)
7521 g_assert_not_reached ();
7526 mono_lookup_internal_call (MonoMethod *method)
7531 int typelen = 0, mlen, siglen;
7533 #ifndef DISABLE_ICALL_TABLES
7534 const IcallTypeDesc *imap = NULL;
7537 g_assert (method != NULL);
7539 if (method->is_inflated)
7540 method = ((MonoMethodInflated *) method)->declaring;
7542 if (method->klass->nested_in) {
7543 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7547 mname [pos++] = '/';
7550 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7556 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7561 #ifndef DISABLE_ICALL_TABLES
7562 imap = find_class_icalls (mname);
7565 mname [typelen] = ':';
7566 mname [typelen + 1] = ':';
7568 mlen = strlen (method->name);
7569 memcpy (mname + typelen + 2, method->name, mlen);
7570 sigstart = mname + typelen + 2 + mlen;
7573 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7574 siglen = strlen (tmpsig);
7575 if (typelen + mlen + siglen + 6 > sizeof (mname))
7578 memcpy (sigstart + 1, tmpsig, siglen);
7579 sigstart [siglen + 1] = ')';
7580 sigstart [siglen + 2] = 0;
7585 res = g_hash_table_lookup (icall_hash, mname);
7587 mono_icall_unlock ();;
7590 /* try without signature */
7592 res = g_hash_table_lookup (icall_hash, mname);
7594 mono_icall_unlock ();
7598 #ifdef DISABLE_ICALL_TABLES
7599 mono_icall_unlock ();
7600 /* Fail only when the result is actually used */
7601 /* mono_marshal_get_native_wrapper () depends on this */
7602 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
7603 return ves_icall_System_String_ctor_RedirectToCreateString;
7605 return no_icall_table;
7607 /* it wasn't found in the static call tables */
7609 mono_icall_unlock ();
7612 res = find_method_icall (imap, sigstart - mlen);
7614 mono_icall_unlock ();
7617 /* try _with_ signature */
7619 res = find_method_icall (imap, sigstart - mlen);
7621 mono_icall_unlock ();
7625 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7626 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7627 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7628 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
7629 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");
7630 g_print ("If you see other errors or faults after this message they are probably related\n");
7631 g_print ("and you need to fix your mono install first.\n");
7633 mono_icall_unlock ();
7639 #ifdef ENABLE_ICALL_SYMBOL_MAP
7641 func_cmp (gconstpointer key, gconstpointer p)
7643 return (gsize)key - (gsize)*(gsize*)p;
7648 * mono_lookup_icall_symbol:
7650 * Given the icall METHOD, returns its C symbol.
7653 mono_lookup_icall_symbol (MonoMethod *m)
7655 #ifdef DISABLE_ICALL_TABLES
7656 g_assert_not_reached ();
7659 #ifdef ENABLE_ICALL_SYMBOL_MAP
7663 static gconstpointer *functions_sorted;
7664 static const char**symbols_sorted;
7665 static gboolean inited;
7670 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7671 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7672 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7673 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
7674 /* Bubble sort the two arrays */
7678 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
7679 if (functions_sorted [i] > functions_sorted [i + 1]) {
7682 tmp = functions_sorted [i];
7683 functions_sorted [i] = functions_sorted [i + 1];
7684 functions_sorted [i + 1] = tmp;
7685 tmp = symbols_sorted [i];
7686 symbols_sorted [i] = symbols_sorted [i + 1];
7687 symbols_sorted [i + 1] = tmp;
7694 func = mono_lookup_internal_call (m);
7697 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
7701 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
7703 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
7704 g_assert_not_reached ();
7711 type_from_typename (char *type_name)
7713 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7715 if (!strcmp (type_name, "int"))
7716 klass = mono_defaults.int_class;
7717 else if (!strcmp (type_name, "ptr"))
7718 klass = mono_defaults.int_class;
7719 else if (!strcmp (type_name, "void"))
7720 klass = mono_defaults.void_class;
7721 else if (!strcmp (type_name, "int32"))
7722 klass = mono_defaults.int32_class;
7723 else if (!strcmp (type_name, "uint32"))
7724 klass = mono_defaults.uint32_class;
7725 else if (!strcmp (type_name, "int8"))
7726 klass = mono_defaults.sbyte_class;
7727 else if (!strcmp (type_name, "uint8"))
7728 klass = mono_defaults.byte_class;
7729 else if (!strcmp (type_name, "int16"))
7730 klass = mono_defaults.int16_class;
7731 else if (!strcmp (type_name, "uint16"))
7732 klass = mono_defaults.uint16_class;
7733 else if (!strcmp (type_name, "long"))
7734 klass = mono_defaults.int64_class;
7735 else if (!strcmp (type_name, "ulong"))
7736 klass = mono_defaults.uint64_class;
7737 else if (!strcmp (type_name, "float"))
7738 klass = mono_defaults.single_class;
7739 else if (!strcmp (type_name, "double"))
7740 klass = mono_defaults.double_class;
7741 else if (!strcmp (type_name, "object"))
7742 klass = mono_defaults.object_class;
7743 else if (!strcmp (type_name, "obj"))
7744 klass = mono_defaults.object_class;
7745 else if (!strcmp (type_name, "string"))
7746 klass = mono_defaults.string_class;
7747 else if (!strcmp (type_name, "bool"))
7748 klass = mono_defaults.boolean_class;
7749 else if (!strcmp (type_name, "boolean"))
7750 klass = mono_defaults.boolean_class;
7752 g_error ("%s", type_name);
7753 g_assert_not_reached ();
7755 return &klass->byval_arg;
7759 * LOCKING: Take the corlib image lock.
7761 MonoMethodSignature*
7762 mono_create_icall_signature (const char *sigstr)
7767 MonoMethodSignature *res, *res2;
7768 MonoImage *corlib = mono_defaults.corlib;
7770 mono_image_lock (corlib);
7771 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7772 mono_image_unlock (corlib);
7777 parts = g_strsplit (sigstr, " ", 256);
7786 res = mono_metadata_signature_alloc (corlib, len - 1);
7791 * Under windows, the default pinvoke calling convention is STDCALL but
7794 res->call_convention = MONO_CALL_C;
7797 res->ret = type_from_typename (parts [0]);
7798 for (i = 1; i < len; ++i) {
7799 res->params [i - 1] = type_from_typename (parts [i]);
7804 mono_image_lock (corlib);
7805 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
7807 res = res2; /*Value is allocated in the image pool*/
7809 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
7810 mono_image_unlock (corlib);
7816 mono_find_jit_icall_by_name (const char *name)
7818 MonoJitICallInfo *info;
7819 g_assert (jit_icall_hash_name);
7822 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7823 mono_icall_unlock ();
7828 mono_find_jit_icall_by_addr (gconstpointer addr)
7830 MonoJitICallInfo *info;
7831 g_assert (jit_icall_hash_addr);
7834 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7835 mono_icall_unlock ();
7841 * mono_get_jit_icall_info:
7843 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7844 * caller should access it while holding the icall lock.
7847 mono_get_jit_icall_info (void)
7849 return jit_icall_hash_name;
7853 * mono_lookup_jit_icall_symbol:
7855 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
7858 mono_lookup_jit_icall_symbol (const char *name)
7860 MonoJitICallInfo *info;
7861 const char *res = NULL;
7864 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
7866 res = info->c_symbol;
7867 mono_icall_unlock ();
7872 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7875 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7876 mono_icall_unlock ();
7880 * 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
7881 * icalls without wrappers in some cases.
7884 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
7886 MonoJitICallInfo *info;
7893 if (!jit_icall_hash_name) {
7894 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7895 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7898 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7899 g_warning ("jit icall already defined \"%s\"\n", name);
7900 g_assert_not_reached ();
7903 info = g_new0 (MonoJitICallInfo, 1);
7908 info->c_symbol = c_symbol;
7909 info->no_raise = no_raise;
7912 info->wrapper = func;
7914 info->wrapper = NULL;
7917 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7918 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7920 mono_icall_unlock ();
7925 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7927 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);