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/exception-internals.h>
49 #include <mono/metadata/file-io.h>
50 #include <mono/metadata/console-io.h>
51 #include <mono/metadata/mono-route.h>
52 #include <mono/metadata/socket-io.h>
53 #include <mono/metadata/mono-endian.h>
54 #include <mono/metadata/tokentype.h>
55 #include <mono/metadata/domain-internals.h>
56 #include <mono/metadata/metadata-internals.h>
57 #include <mono/metadata/class-internals.h>
58 #include <mono/metadata/reflection-internals.h>
59 #include <mono/metadata/marshal.h>
60 #include <mono/metadata/gc-internals.h>
61 #include <mono/metadata/mono-gc.h>
62 #include <mono/metadata/rand.h>
63 #include <mono/metadata/sysmath.h>
64 #include <mono/metadata/string-icalls.h>
65 #include <mono/metadata/debug-helpers.h>
66 #include <mono/metadata/process.h>
67 #include <mono/metadata/environment.h>
68 #include <mono/metadata/profiler-private.h>
69 #include <mono/metadata/locales.h>
70 #include <mono/metadata/filewatcher.h>
71 #include <mono/metadata/security.h>
72 #include <mono/metadata/mono-config.h>
73 #include <mono/metadata/cil-coff.h>
74 #include <mono/metadata/number-formatter.h>
75 #include <mono/metadata/security-manager.h>
76 #include <mono/metadata/security-core-clr.h>
77 #include <mono/metadata/mono-perfcounters.h>
78 #include <mono/metadata/mono-debug.h>
79 #include <mono/metadata/mono-ptr-array.h>
80 #include <mono/metadata/verify-internals.h>
81 #include <mono/metadata/runtime.h>
82 #include <mono/metadata/file-mmap.h>
83 #include <mono/metadata/seq-points-data.h>
84 #include <mono/io-layer/io-layer.h>
85 #include <mono/utils/monobitset.h>
86 #include <mono/utils/mono-time.h>
87 #include <mono/utils/mono-proclib.h>
88 #include <mono/utils/mono-string.h>
89 #include <mono/utils/mono-error-internals.h>
90 #include <mono/utils/mono-mmap.h>
91 #include <mono/utils/mono-io-portability.h>
92 #include <mono/utils/mono-digest.h>
93 #include <mono/utils/bsearch.h>
94 #include <mono/utils/mono-os-mutex.h>
95 #include <mono/utils/mono-threads.h>
97 #if defined (HOST_WIN32)
101 #include "decimal-ms.h"
102 #include "number-ms.h"
104 #if !defined(HOST_WIN32) && defined(HAVE_SYS_UTSNAME_H)
105 #include <sys/utsname.h>
108 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void);
110 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
112 /* Lazy class loading functions */
113 static GENERATE_GET_CLASS_WITH_CACHE (system_version, System, Version)
114 static GENERATE_GET_CLASS_WITH_CACHE (assembly_name, System.Reflection, AssemblyName)
115 static GENERATE_GET_CLASS_WITH_CACHE (constructor_info, System.Reflection, ConstructorInfo)
116 static GENERATE_GET_CLASS_WITH_CACHE (property_info, System.Reflection, PropertyInfo)
117 static GENERATE_GET_CLASS_WITH_CACHE (event_info, System.Reflection, EventInfo)
118 static GENERATE_GET_CLASS_WITH_CACHE (module, System.Reflection, Module)
121 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error);
123 static inline MonoBoolean
124 is_generic_parameter (MonoType *type)
126 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
130 mono_class_init_checked (MonoClass *klass, MonoError *error)
132 mono_error_init (error);
134 if (!mono_class_init (klass))
135 mono_error_set_exception_instance (error, mono_class_get_exception_for_failure (klass));
138 ICALL_EXPORT MonoObject *
139 ves_icall_System_Array_GetValueImpl (MonoArray *arr, guint32 pos)
145 MonoObject *result = NULL;
147 ac = (MonoClass *)arr->obj.vtable->klass;
149 esize = mono_array_element_size (ac);
150 ea = (gpointer*)((char*)arr->vector + (pos * esize));
152 if (ac->element_class->valuetype) {
153 result = mono_value_box_checked (arr->obj.vtable->domain, ac->element_class, ea, &error);
154 mono_error_set_pending_exception (&error);
156 result = (MonoObject *)*ea;
160 ICALL_EXPORT MonoObject *
161 ves_icall_System_Array_GetValue (MonoArray *arr, MonoArray *idxs)
167 MONO_CHECK_ARG_NULL (idxs, NULL);
170 ic = (MonoClass *)io->obj.vtable->klass;
172 ac = (MonoClass *)arr->obj.vtable->klass;
174 g_assert (ic->rank == 1);
175 if (io->bounds != NULL || io->max_length != ac->rank) {
176 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
180 ind = (gint32 *)io->vector;
182 if (arr->bounds == NULL) {
183 if (*ind < 0 || *ind >= arr->max_length) {
184 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
188 return ves_icall_System_Array_GetValueImpl (arr, *ind);
191 for (i = 0; i < ac->rank; i++) {
192 if ((ind [i] < arr->bounds [i].lower_bound) ||
193 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
194 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
199 pos = ind [0] - arr->bounds [0].lower_bound;
200 for (i = 1; i < ac->rank; i++)
201 pos = pos * arr->bounds [i].length + ind [i] -
202 arr->bounds [i].lower_bound;
204 return ves_icall_System_Array_GetValueImpl (arr, pos);
208 ves_icall_System_Array_SetValueImpl (MonoArray *arr, MonoObject *value, guint32 pos)
210 MonoClass *ac, *vc, *ec;
220 vc = value->vtable->klass;
224 ac = arr->obj.vtable->klass;
225 ec = ac->element_class;
227 esize = mono_array_element_size (ac);
228 ea = (gpointer*)((char*)arr->vector + (pos * esize));
229 va = (gpointer*)((char*)value + sizeof (MonoObject));
231 if (mono_class_is_nullable (ec)) {
232 mono_nullable_init ((guint8*)ea, value, ec);
237 mono_gc_bzero_atomic (ea, esize);
241 #define NO_WIDENING_CONVERSION G_STMT_START{\
242 mono_set_pending_exception (mono_get_exception_argument ( \
243 "value", "not a widening conversion")); \
247 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
248 if (esize < vsize + (extra)) { \
249 mono_set_pending_exception (mono_get_exception_argument ( \
250 "value", "not a widening conversion")); \
255 #define INVALID_CAST G_STMT_START{ \
256 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
257 mono_set_pending_exception (mono_get_exception_invalid_cast ()); \
261 /* Check element (destination) type. */
262 switch (ec->byval_arg.type) {
263 case MONO_TYPE_STRING:
264 switch (vc->byval_arg.type) {
265 case MONO_TYPE_STRING:
271 case MONO_TYPE_BOOLEAN:
272 switch (vc->byval_arg.type) {
273 case MONO_TYPE_BOOLEAN:
286 NO_WIDENING_CONVERSION;
295 if (!ec->valuetype) {
296 if (!mono_object_isinst (value, ec))
298 mono_gc_wbarrier_set_arrayref (arr, ea, (MonoObject*)value);
302 if (mono_object_isinst (value, ec)) {
303 if (ec->has_references)
304 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
306 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
313 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
315 et = ec->byval_arg.type;
316 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
317 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
319 vt = vc->byval_arg.type;
320 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
321 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
323 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
329 case MONO_TYPE_CHAR: \
330 CHECK_WIDENING_CONVERSION(0); \
331 *(etype *) ea = (etype) u64; \
333 /* You can't assign a signed value to an unsigned array. */ \
338 /* You can't assign a floating point number to an integer array. */ \
341 NO_WIDENING_CONVERSION; \
345 #define ASSIGN_SIGNED(etype) G_STMT_START{\
351 CHECK_WIDENING_CONVERSION(0); \
352 *(etype *) ea = (etype) i64; \
354 /* You can assign an unsigned value to a signed array if the array's */ \
355 /* element size is larger than the value size. */ \
360 case MONO_TYPE_CHAR: \
361 CHECK_WIDENING_CONVERSION(1); \
362 *(etype *) ea = (etype) u64; \
364 /* You can't assign a floating point number to an integer array. */ \
367 NO_WIDENING_CONVERSION; \
371 #define ASSIGN_REAL(etype) G_STMT_START{\
375 CHECK_WIDENING_CONVERSION(0); \
376 *(etype *) ea = (etype) r64; \
378 /* All integer values fit into a floating point array, so we don't */ \
379 /* need to CHECK_WIDENING_CONVERSION here. */ \
384 *(etype *) ea = (etype) i64; \
390 case MONO_TYPE_CHAR: \
391 *(etype *) ea = (etype) u64; \
398 u64 = *(guint8 *) va;
401 u64 = *(guint16 *) va;
404 u64 = *(guint32 *) va;
407 u64 = *(guint64 *) va;
413 i64 = *(gint16 *) va;
416 i64 = *(gint32 *) va;
419 i64 = *(gint64 *) va;
422 r64 = *(gfloat *) va;
425 r64 = *(gdouble *) va;
428 u64 = *(guint16 *) va;
430 case MONO_TYPE_BOOLEAN:
431 /* Boolean is only compatible with itself. */
444 NO_WIDENING_CONVERSION;
451 /* If we can't do a direct copy, let's try a widening conversion. */
454 ASSIGN_UNSIGNED (guint16);
456 ASSIGN_UNSIGNED (guint8);
458 ASSIGN_UNSIGNED (guint16);
460 ASSIGN_UNSIGNED (guint32);
462 ASSIGN_UNSIGNED (guint64);
464 ASSIGN_SIGNED (gint8);
466 ASSIGN_SIGNED (gint16);
468 ASSIGN_SIGNED (gint32);
470 ASSIGN_SIGNED (gint64);
472 ASSIGN_REAL (gfloat);
474 ASSIGN_REAL (gdouble);
478 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
482 #undef NO_WIDENING_CONVERSION
483 #undef CHECK_WIDENING_CONVERSION
484 #undef ASSIGN_UNSIGNED
490 ves_icall_System_Array_SetValue (MonoArray *arr, MonoObject *value,
496 MONO_CHECK_ARG_NULL (idxs,);
498 ic = idxs->obj.vtable->klass;
499 ac = arr->obj.vtable->klass;
501 g_assert (ic->rank == 1);
502 if (idxs->bounds != NULL || idxs->max_length != ac->rank) {
503 mono_set_pending_exception (mono_get_exception_argument (NULL, NULL));
507 ind = (gint32 *)idxs->vector;
509 if (arr->bounds == NULL) {
510 if (*ind < 0 || *ind >= arr->max_length) {
511 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
515 ves_icall_System_Array_SetValueImpl (arr, value, *ind);
519 for (i = 0; i < ac->rank; i++)
520 if ((ind [i] < arr->bounds [i].lower_bound) ||
521 (ind [i] >= (mono_array_lower_bound_t)arr->bounds [i].length + arr->bounds [i].lower_bound)) {
522 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
526 pos = ind [0] - arr->bounds [0].lower_bound;
527 for (i = 1; i < ac->rank; i++)
528 pos = pos * arr->bounds [i].length + ind [i] -
529 arr->bounds [i].lower_bound;
531 ves_icall_System_Array_SetValueImpl (arr, value, pos);
534 ICALL_EXPORT MonoArray *
535 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
538 MonoClass *aklass, *klass;
541 gboolean bounded = FALSE;
543 MONO_CHECK_ARG_NULL (type, NULL);
544 MONO_CHECK_ARG_NULL (lengths, NULL);
546 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
548 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
550 for (i = 0; i < mono_array_length (lengths); i++) {
551 if (mono_array_get (lengths, gint32, i) < 0) {
552 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
557 klass = mono_class_from_mono_type (type->type);
558 mono_class_init_checked (klass, &error);
559 mono_error_raise_exception (&error);
561 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
562 /* vectors are not the same as one dimensional arrays with no-zero bounds */
567 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
569 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
570 for (i = 0; i < aklass->rank; ++i) {
571 sizes [i] = mono_array_get (lengths, guint32, i);
573 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
575 sizes [i + aklass->rank] = 0;
578 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
579 mono_error_set_pending_exception (&error);
584 ICALL_EXPORT MonoArray *
585 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
588 MonoClass *aklass, *klass;
591 gboolean bounded = FALSE;
593 MONO_CHECK_ARG_NULL (type, NULL);
594 MONO_CHECK_ARG_NULL (lengths, NULL);
596 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0, NULL);
598 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds), NULL);
600 for (i = 0; i < mono_array_length (lengths); i++) {
601 if ((mono_array_get (lengths, gint64, i) < 0) ||
602 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX)) {
603 mono_set_pending_exception (mono_get_exception_argument_out_of_range (NULL));
608 klass = mono_class_from_mono_type (type->type);
609 mono_class_init_checked (klass, &error);
610 mono_error_raise_exception (&error);
612 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
613 /* vectors are not the same as one dimensional arrays with no-zero bounds */
618 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
620 sizes = (uintptr_t *)alloca (aklass->rank * sizeof(intptr_t) * 2);
621 for (i = 0; i < aklass->rank; ++i) {
622 sizes [i] = mono_array_get (lengths, guint64, i);
624 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
626 sizes [i + aklass->rank] = 0;
629 array = mono_array_new_full_checked (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank, &error);
630 mono_error_set_pending_exception (&error);
636 ves_icall_System_Array_GetRank (MonoObject *arr)
638 return arr->vtable->klass->rank;
642 ves_icall_System_Array_GetLength (MonoArray *arr, gint32 dimension)
644 gint32 rank = arr->obj.vtable->klass->rank;
647 if ((dimension < 0) || (dimension >= rank)) {
648 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
652 if (arr->bounds == NULL)
653 length = arr->max_length;
655 length = arr->bounds [dimension].length;
657 #ifdef MONO_BIG_ARRAYS
658 if (length > G_MAXINT32) {
659 mono_set_pending_exception (mono_get_exception_overflow ());
667 ves_icall_System_Array_GetLongLength (MonoArray *arr, gint32 dimension)
669 gint32 rank = arr->obj.vtable->klass->rank;
671 if ((dimension < 0) || (dimension >= rank)) {
672 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
676 if (arr->bounds == NULL)
677 return arr->max_length;
679 return arr->bounds [dimension].length;
683 ves_icall_System_Array_GetLowerBound (MonoArray *arr, gint32 dimension)
685 gint32 rank = arr->obj.vtable->klass->rank;
687 if ((dimension < 0) || (dimension >= rank)) {
688 mono_set_pending_exception (mono_get_exception_index_out_of_range ());
692 if (arr->bounds == NULL)
695 return arr->bounds [dimension].lower_bound;
699 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
701 int sz = mono_array_element_size (mono_object_class (arr));
702 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
705 ICALL_EXPORT gboolean
706 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
711 MonoVTable *src_vtable;
712 MonoVTable *dest_vtable;
713 MonoClass *src_class;
714 MonoClass *dest_class;
716 src_vtable = source->obj.vtable;
717 dest_vtable = dest->obj.vtable;
719 if (src_vtable->rank != dest_vtable->rank)
722 if (source->bounds || dest->bounds)
725 /* there's no integer overflow since mono_array_length returns an unsigned integer */
726 if ((dest_idx + length > mono_array_length_fast (dest)) ||
727 (source_idx + length > mono_array_length_fast (source)))
730 src_class = src_vtable->klass->element_class;
731 dest_class = dest_vtable->klass->element_class;
734 * Handle common cases.
737 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
738 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
740 if (src_class == mono_defaults.object_class && dest_class->valuetype)
743 /* Check if we're copying a char[] <==> (u)short[] */
744 if (src_class != dest_class) {
745 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
748 /* 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. */
749 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
753 if (dest_class->valuetype) {
754 element_size = mono_array_element_size (source->obj.vtable->klass);
755 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
756 if (dest_class->has_references) {
757 mono_value_copy_array (dest, dest_idx, source_addr, length);
759 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
760 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
763 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
770 ves_icall_System_Array_GetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
776 ac = (MonoClass *)arr->obj.vtable->klass;
778 esize = mono_array_element_size (ac);
779 ea = (gpointer*)((char*)arr->vector + (pos * esize));
781 mono_gc_memmove_atomic (value, ea, esize);
785 ves_icall_System_Array_SetGenericValueImpl (MonoArray *arr, guint32 pos, gpointer value)
791 ac = (MonoClass *)arr->obj.vtable->klass;
792 ec = ac->element_class;
794 esize = mono_array_element_size (ac);
795 ea = (gpointer*)((char*)arr->vector + (pos * esize));
797 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
798 g_assert (esize == sizeof (gpointer));
799 mono_gc_wbarrier_generic_store (ea, *(MonoObject **)value);
801 g_assert (ec->inited);
802 g_assert (esize == mono_class_value_size (ec, NULL));
803 if (ec->has_references)
804 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
806 mono_gc_memmove_atomic (ea, value, esize);
811 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
813 MonoClass *klass = array->obj.vtable->klass;
814 guint32 size = mono_array_element_size (klass);
815 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
817 const char *field_data;
819 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
820 MonoException *exc = mono_get_exception_argument("array",
821 "Cannot initialize array of non-primitive type.");
822 mono_set_pending_exception (exc);
826 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
827 MonoException *exc = mono_get_exception_argument("field_handle",
828 "Field doesn't have an RVA");
829 mono_set_pending_exception (exc);
833 size *= array->max_length;
834 field_data = mono_field_get_data (field_handle);
836 if (size > mono_type_size (field_handle->type, &align)) {
837 MonoException *exc = mono_get_exception_argument("field_handle",
838 "Field not large enough to fill array");
839 mono_set_pending_exception (exc);
843 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
845 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
846 guint ## n *src = (guint ## n *) field_data; \
848 nEnt = (size / sizeof(guint ## n)); \
850 for (i = 0; i < nEnt; i++) { \
851 data[i] = read ## n (&src[i]); \
855 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
857 switch (type->type) {
874 memcpy (mono_array_addr (array, char, 0), field_data, size);
878 memcpy (mono_array_addr (array, char, 0), field_data, size);
883 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
885 return offsetof (MonoString, chars);
888 ICALL_EXPORT MonoObject *
889 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
891 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
895 MonoObject *ret = mono_object_clone_checked (obj, &error);
896 mono_error_set_pending_exception (&error);
903 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
909 MONO_CHECK_ARG_NULL (handle,);
911 klass = mono_class_from_mono_type (handle);
912 MONO_CHECK_ARG (handle, klass,);
914 if (klass->generic_container)
917 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
918 if (!is_ok (&error)) {
919 mono_error_set_pending_exception (&error);
923 /* This will call the type constructor */
924 if (!mono_runtime_class_init_full (vtable, &error))
925 mono_error_set_pending_exception (&error);
929 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
933 mono_image_check_for_module_cctor (image);
934 if (image->has_module_cctor) {
935 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
936 if (!mono_error_ok (&error)) {
937 mono_error_set_pending_exception (&error);
940 /*It's fine to raise the exception here*/
941 MonoVTable * vtable = mono_class_vtable_full (mono_domain_get (), module_klass, &error);
942 if (!is_ok (&error)) {
943 mono_error_set_pending_exception (&error);
946 if (!mono_runtime_class_init_full (vtable, &error))
947 mono_error_set_pending_exception (&error);
951 ICALL_EXPORT MonoBoolean
952 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
957 /* later make this configurable and per-arch */
958 int min_size = 4096 * 4 * sizeof (void*);
959 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
960 /* if we have no info we are optimistic and assume there is enough room */
964 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
968 current = (guint8 *)&stack_addr;
969 if (current > stack_addr) {
970 if ((current - stack_addr) < min_size)
973 if (current - (stack_addr - stack_size) < min_size)
979 ICALL_EXPORT MonoObject *
980 ves_icall_System_Object_MemberwiseClone (MonoObject *this_obj)
983 MonoObject *ret = mono_object_clone_checked (this_obj, &error);
984 mono_error_set_pending_exception (&error);
990 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this_obj, MonoArray **fields)
994 MonoObject **values = NULL;
997 gint32 result = (int)(gsize)mono_defaults.int32_class;
998 MonoClassField* field;
1001 klass = mono_object_class (this_obj);
1003 if (mono_class_num_fields (klass) == 0)
1007 * Compute the starting value of the hashcode for fields of primitive
1008 * types, and return the remaining fields in an array to the managed side.
1009 * This way, we can avoid costly reflection operations in managed code.
1012 while ((field = mono_class_get_fields (klass, &iter))) {
1013 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1015 if (mono_field_is_deleted (field))
1017 /* FIXME: Add more types */
1018 switch (field->type->type) {
1020 result ^= *(gint32*)((guint8*)this_obj + field->offset);
1022 case MONO_TYPE_STRING: {
1024 s = *(MonoString**)((guint8*)this_obj + field->offset);
1026 result ^= mono_string_hash (s);
1031 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1032 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1033 if (!is_ok (&error)) {
1034 mono_error_set_pending_exception (&error);
1037 values [count++] = o;
1043 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1044 for (i = 0; i < count; ++i)
1045 mono_array_setref (*fields, i, values [i]);
1052 ICALL_EXPORT MonoBoolean
1053 ves_icall_System_ValueType_Equals (MonoObject *this_obj, MonoObject *that, MonoArray **fields)
1057 MonoObject **values = NULL;
1059 MonoClassField* field;
1063 MONO_CHECK_ARG_NULL (that, FALSE);
1065 if (this_obj->vtable != that->vtable)
1068 klass = mono_object_class (this_obj);
1070 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1071 return (*(gint32*)((guint8*)this_obj + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1074 * Do the comparison for fields of primitive type and return a result if
1075 * possible. Otherwise, return the remaining fields in an array to the
1076 * managed side. This way, we can avoid costly reflection operations in
1081 while ((field = mono_class_get_fields (klass, &iter))) {
1082 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1084 if (mono_field_is_deleted (field))
1086 /* FIXME: Add more types */
1087 switch (field->type->type) {
1090 case MONO_TYPE_BOOLEAN:
1091 if (*((guint8*)this_obj + field->offset) != *((guint8*)that + field->offset))
1096 case MONO_TYPE_CHAR:
1097 if (*(gint16*)((guint8*)this_obj + field->offset) != *(gint16*)((guint8*)that + field->offset))
1102 if (*(gint32*)((guint8*)this_obj + field->offset) != *(gint32*)((guint8*)that + field->offset))
1107 if (*(gint64*)((guint8*)this_obj + field->offset) != *(gint64*)((guint8*)that + field->offset))
1111 if (*(float*)((guint8*)this_obj + field->offset) != *(float*)((guint8*)that + field->offset))
1115 if (*(double*)((guint8*)this_obj + field->offset) != *(double*)((guint8*)that + field->offset))
1120 case MONO_TYPE_STRING: {
1121 MonoString *s1, *s2;
1122 guint32 s1len, s2len;
1123 s1 = *(MonoString**)((guint8*)this_obj + field->offset);
1124 s2 = *(MonoString**)((guint8*)that + field->offset);
1127 if ((s1 == NULL) || (s2 == NULL))
1129 s1len = mono_string_length (s1);
1130 s2len = mono_string_length (s2);
1134 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1140 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1141 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, this_obj, &error);
1142 if (!is_ok (&error)) {
1143 mono_error_set_pending_exception (&error);
1146 values [count++] = o;
1147 o = mono_field_get_value_object_checked (mono_object_domain (this_obj), field, that, &error);
1148 if (!is_ok (&error)) {
1149 mono_error_set_pending_exception (&error);
1152 values [count++] = o;
1155 if (klass->enumtype)
1156 /* enums only have one non-static field */
1162 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1163 for (i = 0; i < count; ++i)
1164 mono_array_setref_fast (*fields, i, values [i]);
1171 ICALL_EXPORT MonoReflectionType *
1172 ves_icall_System_Object_GetType (MonoObject *obj)
1175 MonoReflectionType *ret;
1176 #ifndef DISABLE_REMOTING
1177 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1178 ret = mono_type_get_object_checked (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg, &error);
1181 ret = mono_type_get_object_checked (mono_object_domain (obj), &obj->vtable->klass->byval_arg, &error);
1183 mono_error_raise_exception (&error);
1189 ves_icall_MonoType_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1191 mtype->type = &obj->vtable->klass->byval_arg;
1192 g_assert (mtype->type->type);
1196 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1198 MONO_CHECK_ARG_NULL (obj, 0);
1201 gint32 result = mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE, &error);
1202 mono_error_raise_exception (&error);
1207 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1208 MonoReflectionMethod *method,
1209 MonoArray *opt_param_types)
1211 MONO_CHECK_ARG_NULL (method, 0);
1214 gint32 result = mono_image_create_method_token (
1215 mb->dynamic_image, (MonoObject *) method, opt_param_types, &error);
1216 mono_error_raise_exception (&error);
1221 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1224 mono_image_create_pefile (mb, file, &error);
1225 mono_error_raise_exception (&error);
1229 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1232 if (!mono_image_build_metadata (mb, &error))
1233 mono_error_raise_exception (&error);
1237 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1239 mono_image_register_token (mb->dynamic_image, token, obj);
1242 ICALL_EXPORT MonoObject*
1243 ves_icall_ModuleBuilder_GetRegisteredToken (MonoReflectionModuleBuilder *mb, guint32 token)
1247 mono_loader_lock ();
1248 obj = (MonoObject *)mono_g_hash_table_lookup (mb->dynamic_image->tokens, GUINT_TO_POINTER (token));
1249 mono_loader_unlock ();
1254 ICALL_EXPORT MonoReflectionModule*
1255 ves_icall_System_Reflection_Emit_AssemblyBuilder_InternalAddModule (MonoReflectionAssemblyBuilder *ab, MonoString *fileName)
1258 MonoReflectionModule *result = mono_image_load_module_dynamic (ab, fileName, &error);
1259 mono_error_set_pending_exception (&error);
1263 ICALL_EXPORT MonoArray*
1264 ves_icall_System_Reflection_Emit_CustomAttributeBuilder_GetBlob (MonoReflectionAssembly *assembly, MonoObject *ctor, MonoArray *ctorArgs, MonoArray *properties, MonoArray *propValues, MonoArray *fields, MonoArray* fieldValues)
1267 MonoArray *result = mono_reflection_get_custom_attrs_blob_checked (assembly, ctor, ctorArgs, properties, propValues, fields, fieldValues, &error);
1268 mono_error_set_pending_exception (&error);
1273 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1275 MonoMethod **dest = (MonoMethod **)data;
1277 /* skip unmanaged frames */
1293 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1295 MonoMethod **dest = (MonoMethod **)data;
1297 /* skip unmanaged frames */
1302 if (!strcmp (m->klass->name_space, "System.Reflection"))
1311 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1313 MonoMethod **dest = (MonoMethod **)data;
1315 /* skip unmanaged frames */
1319 if (m->wrapper_type != MONO_WRAPPER_NONE)
1322 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1336 static MonoReflectionType *
1337 type_from_parsed_name (MonoTypeNameParse *info, MonoBoolean ignoreCase, MonoError *error)
1339 MonoMethod *m, *dest;
1341 MonoType *type = NULL;
1342 MonoAssembly *assembly = NULL;
1343 gboolean type_resolve = FALSE;
1345 mono_error_init (error);
1348 * We must compute the calling assembly as type loading must happen under a metadata context.
1349 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1350 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1352 m = mono_method_get_last_managed ();
1355 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1360 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1361 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1362 * to crash. This only seems to happen in some strange remoting
1363 * scenarios and I was unable to figure out what's happening there.
1364 * Dec 10, 2005 - Martin.
1368 assembly = dest->klass->image->assembly;
1369 type_resolve = TRUE;
1371 g_warning (G_STRLOC);
1374 if (info->assembly.name)
1375 assembly = mono_assembly_load (&info->assembly, assembly ? assembly->basedir : NULL, NULL);
1379 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1380 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1381 return_val_if_nok (error, NULL);
1384 if (!info->assembly.name && !type) {
1386 type = mono_reflection_get_type_checked (NULL, info, ignoreCase, &type_resolve, error);
1387 return_val_if_nok (error, NULL);
1389 if (assembly && !type && type_resolve) {
1390 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1391 type = mono_reflection_get_type_checked (assembly->image, info, ignoreCase, &type_resolve, error);
1392 return_val_if_nok (error, NULL);
1398 return mono_type_get_object_checked (mono_domain_get (), type, error);
1401 ICALL_EXPORT MonoReflectionType*
1402 ves_icall_System_Type_internal_from_name (MonoString *name,
1403 MonoBoolean throwOnError,
1404 MonoBoolean ignoreCase)
1407 char *str = mono_string_to_utf8 (name);
1408 MonoTypeNameParse info;
1409 MonoReflectionType *type;
1412 parsedOk = mono_reflection_parse_type (str, &info);
1414 /* mono_reflection_parse_type() mangles the string */
1416 mono_reflection_free_type_info (&info);
1419 mono_set_pending_exception (mono_get_exception_argument("typeName", "failed parse"));
1424 type = type_from_parsed_name (&info, ignoreCase, &error);
1426 mono_reflection_free_type_info (&info);
1429 if (!mono_error_ok (&error)) {
1431 mono_error_set_pending_exception (&error);
1433 mono_error_cleanup (&error);
1438 MonoException *e = NULL;
1441 e = mono_get_exception_type_load (name, NULL);
1443 mono_loader_clear_error ();
1445 mono_set_pending_exception (e);
1454 ICALL_EXPORT MonoReflectionType*
1455 ves_icall_System_Type_internal_from_handle (MonoType *handle)
1458 MonoReflectionType *ret;
1459 MonoDomain *domain = mono_domain_get ();
1461 ret = mono_type_get_object_checked (domain, handle, &error);
1462 mono_error_raise_exception (&error);
1467 /* System.TypeCode */
1486 TYPECODE_STRING = 18
1489 ICALL_EXPORT guint32
1490 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1492 int t = type->type->type;
1494 if (type->type->byref)
1495 return TYPECODE_OBJECT;
1499 case MONO_TYPE_VOID:
1500 return TYPECODE_OBJECT;
1501 case MONO_TYPE_BOOLEAN:
1502 return TYPECODE_BOOLEAN;
1504 return TYPECODE_BYTE;
1506 return TYPECODE_SBYTE;
1508 return TYPECODE_UINT16;
1510 return TYPECODE_INT16;
1511 case MONO_TYPE_CHAR:
1512 return TYPECODE_CHAR;
1516 return TYPECODE_OBJECT;
1518 return TYPECODE_UINT32;
1520 return TYPECODE_INT32;
1522 return TYPECODE_UINT64;
1524 return TYPECODE_INT64;
1526 return TYPECODE_SINGLE;
1528 return TYPECODE_DOUBLE;
1529 case MONO_TYPE_VALUETYPE: {
1530 MonoClass *klass = type->type->data.klass;
1532 if (klass->enumtype) {
1533 t = mono_class_enum_basetype (klass)->type;
1535 } else if (mono_is_corlib_image (klass->image)) {
1536 if (strcmp (klass->name_space, "System") == 0) {
1537 if (strcmp (klass->name, "Decimal") == 0)
1538 return TYPECODE_DECIMAL;
1539 else if (strcmp (klass->name, "DateTime") == 0)
1540 return TYPECODE_DATETIME;
1543 return TYPECODE_OBJECT;
1545 case MONO_TYPE_STRING:
1546 return TYPECODE_STRING;
1547 case MONO_TYPE_SZARRAY:
1548 case MONO_TYPE_ARRAY:
1549 case MONO_TYPE_OBJECT:
1551 case MONO_TYPE_MVAR:
1552 case MONO_TYPE_TYPEDBYREF:
1553 return TYPECODE_OBJECT;
1554 case MONO_TYPE_CLASS:
1556 MonoClass *klass = type->type->data.klass;
1557 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1558 if (strcmp (klass->name, "DBNull") == 0)
1559 return TYPECODE_DBNULL;
1562 return TYPECODE_OBJECT;
1563 case MONO_TYPE_GENERICINST:
1564 return TYPECODE_OBJECT;
1566 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1572 mono_type_is_primitive (MonoType *type)
1574 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1575 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1579 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1581 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1582 return mono_class_enum_basetype (type->data.klass);
1583 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1584 return mono_class_enum_basetype (type->data.generic_class->container_class);
1588 ICALL_EXPORT guint32
1589 ves_icall_RuntimeTypeHandle_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1594 g_assert (type != NULL);
1596 klass = mono_class_from_mono_type (type->type);
1597 klassc = mono_class_from_mono_type (c->type);
1599 if (type->type->byref ^ c->type->byref)
1602 if (type->type->byref) {
1603 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1604 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1606 klass = mono_class_from_mono_type (t);
1607 klassc = mono_class_from_mono_type (ot);
1609 if (mono_type_is_primitive (t)) {
1610 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1611 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1612 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1613 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1614 return t->type == ot->type;
1616 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1619 if (klass->valuetype)
1620 return klass == klassc;
1621 return klass->valuetype == klassc->valuetype;
1624 return mono_class_is_assignable_from (klass, klassc);
1627 ICALL_EXPORT guint32
1628 ves_icall_RuntimeTypeHandle_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1631 MonoClass *klass = mono_class_from_mono_type (type->type);
1632 mono_class_init_checked (klass, &error);
1633 mono_error_raise_exception (&error);
1634 return mono_object_isinst (obj, klass) != NULL;
1637 ICALL_EXPORT guint32
1638 ves_icall_RuntimeTypeHandle_GetAttributes (MonoReflectionType *type)
1640 MonoClass *klass = mono_class_from_mono_type (type->type);
1641 return klass->flags;
1644 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1645 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1648 MonoClass *klass = field->field->parent;
1649 MonoMarshalType *info;
1653 if (klass->generic_container ||
1654 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1657 ftype = mono_field_get_type (field->field);
1658 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1661 info = mono_marshal_load_type_info (klass);
1663 for (i = 0; i < info->num_fields; ++i) {
1664 if (info->fields [i].field == field->field) {
1665 if (!info->fields [i].mspec)
1668 MonoReflectionMarshalAsAttribute* obj;
1669 obj = mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec, &error);
1670 if (!mono_error_ok (&error))
1671 mono_error_set_pending_exception (&error);
1680 ICALL_EXPORT MonoReflectionField*
1681 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1684 gboolean found = FALSE;
1691 klass = handle->parent;
1693 klass = mono_class_from_mono_type (type);
1695 /* Check that the field belongs to the class */
1696 for (k = klass; k; k = k->parent) {
1697 if (k == handle->parent) {
1704 /* The managed code will throw the exception */
1708 MonoReflectionField *result = mono_field_get_object_checked (mono_domain_get (), klass, handle, &error);
1709 mono_error_raise_exception (&error);
1713 ICALL_EXPORT MonoArray*
1714 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1717 MonoType *type = mono_field_get_type_checked (field->field, &error);
1720 if (!mono_error_ok (&error)) {
1721 mono_error_set_pending_exception (&error);
1725 res = type_array_from_modifiers (field->field->parent->image, type, optional, &error);
1726 mono_error_raise_exception (&error);
1731 vell_icall_get_method_attributes (MonoMethod *method)
1733 return method->flags;
1737 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1740 MonoReflectionType *rt;
1741 MonoDomain *domain = mono_domain_get ();
1742 MonoMethodSignature* sig;
1744 sig = mono_method_signature_checked (method, &error);
1745 if (!mono_error_ok (&error)) {
1746 mono_error_set_pending_exception (&error);
1750 rt = mono_type_get_object_checked (domain, &method->klass->byval_arg, &error);
1751 if (!mono_error_ok (&error)) {
1752 mono_error_set_pending_exception (&error);
1756 MONO_STRUCT_SETREF (info, parent, rt);
1758 rt = mono_type_get_object_checked (domain, sig->ret, &error);
1759 if (!mono_error_ok (&error)) {
1760 mono_error_set_pending_exception (&error);
1764 MONO_STRUCT_SETREF (info, ret, rt);
1766 info->attrs = method->flags;
1767 info->implattrs = method->iflags;
1768 if (sig->call_convention == MONO_CALL_DEFAULT)
1769 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1771 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1776 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1779 ICALL_EXPORT MonoArray*
1780 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1783 MonoDomain *domain = mono_domain_get ();
1785 MonoArray *result = mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL, &error);
1786 mono_error_set_pending_exception (&error);
1790 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1791 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1794 MonoDomain *domain = mono_domain_get ();
1795 MonoReflectionMarshalAsAttribute* res = NULL;
1796 MonoMarshalSpec **mspecs;
1799 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1800 mono_method_get_marshal_info (method, mspecs);
1803 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0], &error);
1804 if (!mono_error_ok (&error)) {
1805 mono_error_set_pending_exception (&error);
1810 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1812 mono_metadata_free_marshal_spec (mspecs [i]);
1819 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1821 MonoClass *parent = field->field->parent;
1822 if (!parent->size_inited)
1823 mono_class_init (parent);
1824 mono_class_setup_fields_locking (parent);
1826 return field->field->offset - sizeof (MonoObject);
1829 ICALL_EXPORT MonoReflectionType*
1830 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1833 MonoReflectionType *ret;
1836 parent = declaring? field->field->parent: field->klass;
1838 ret = mono_type_get_object_checked (mono_object_domain (field), &parent->byval_arg, &error);
1839 mono_error_raise_exception (&error);
1845 ICALL_EXPORT MonoObject *
1846 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1849 MonoClass *fklass = field->klass;
1850 MonoClassField *cf = field->field;
1851 MonoDomain *domain = mono_object_domain (field);
1853 if (fklass->image->assembly->ref_only) {
1854 mono_set_pending_exception (mono_get_exception_invalid_operation (
1855 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1859 if (mono_security_core_clr_enabled ())
1860 mono_security_core_clr_ensure_reflection_access_field (cf);
1862 MonoObject * result = mono_field_get_value_object_checked (domain, cf, obj, &error);
1863 mono_error_set_pending_exception (&error);
1868 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1871 MonoClassField *cf = field->field;
1875 if (field->klass->image->assembly->ref_only) {
1876 mono_set_pending_exception (mono_get_exception_invalid_operation (
1877 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1881 if (mono_security_core_clr_enabled ())
1882 mono_security_core_clr_ensure_reflection_access_field (cf);
1884 type = mono_field_get_type_checked (cf, &error);
1885 if (!mono_error_ok (&error)) {
1886 mono_error_set_pending_exception (&error);
1890 v = (gchar *) value;
1892 switch (type->type) {
1895 case MONO_TYPE_BOOLEAN:
1898 case MONO_TYPE_CHAR:
1907 case MONO_TYPE_VALUETYPE:
1910 v += sizeof (MonoObject);
1912 case MONO_TYPE_STRING:
1913 case MONO_TYPE_OBJECT:
1914 case MONO_TYPE_CLASS:
1915 case MONO_TYPE_ARRAY:
1916 case MONO_TYPE_SZARRAY:
1919 case MONO_TYPE_GENERICINST: {
1920 MonoGenericClass *gclass = type->data.generic_class;
1921 g_assert (!gclass->context.class_inst->is_open);
1923 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1924 MonoClass *nklass = mono_class_from_mono_type (type);
1925 MonoObject *nullable;
1928 * Convert the boxed vtype into a Nullable structure.
1929 * This is complicated by the fact that Nullables have
1930 * a variable structure.
1932 nullable = mono_object_new_checked (mono_domain_get (), nklass, &error);
1933 if (!mono_error_ok (&error)) {
1934 mono_error_set_pending_exception (&error);
1938 mono_nullable_init ((guint8 *)mono_object_unbox (nullable), value, nklass);
1940 v = (gchar *)mono_object_unbox (nullable);
1943 if (gclass->container_class->valuetype && (v != NULL))
1944 v += sizeof (MonoObject);
1948 g_error ("type 0x%x not handled in "
1949 "ves_icall_FieldInfo_SetValueInternal", type->type);
1954 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1955 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, &error);
1956 if (!is_ok (&error)) {
1957 mono_error_set_pending_exception (&error);
1960 if (!vtable->initialized) {
1961 if (!mono_runtime_class_init_full (vtable, &error)) {
1962 mono_error_set_pending_exception (&error);
1966 mono_field_static_set_value (vtable, cf, v);
1968 mono_field_set_value (obj, cf, v);
1973 ves_icall_System_RuntimeFieldHandle_SetValueDirect (MonoReflectionField *field, MonoReflectionType *field_type, MonoTypedRef *obj, MonoObject *value, MonoReflectionType *context_type)
1982 if (!MONO_TYPE_ISSTRUCT (&f->parent->byval_arg)) {
1983 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
1987 if (MONO_TYPE_IS_REFERENCE (f->type))
1988 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), value, FALSE);
1990 mono_copy_value (f->type, (guint8*)obj->value + f->offset - sizeof (MonoObject), mono_object_unbox (value), FALSE);
1993 ICALL_EXPORT MonoObject *
1994 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *rfield)
1996 MonoObject *o = NULL;
1997 MonoClassField *field = rfield->field;
1999 MonoDomain *domain = mono_object_domain (rfield);
2001 MonoTypeEnum def_type;
2002 const char *def_value;
2006 mono_class_init (field->parent);
2008 t = mono_field_get_type_checked (field, &error);
2009 if (!mono_error_ok (&error)) {
2010 mono_error_set_pending_exception (&error);
2014 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT)) {
2015 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2019 if (image_is_dynamic (field->parent->image)) {
2020 MonoClass *klass = field->parent;
2021 int fidx = field - klass->fields;
2023 g_assert (fidx >= 0 && fidx < klass->field.count);
2024 g_assert (klass->ext);
2025 g_assert (klass->ext->field_def_values);
2026 def_type = klass->ext->field_def_values [fidx].def_type;
2027 def_value = klass->ext->field_def_values [fidx].data;
2028 if (def_type == MONO_TYPE_END) {
2029 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2033 def_value = mono_class_get_field_default_value (field, &def_type);
2034 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
2036 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
2041 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
2045 case MONO_TYPE_BOOLEAN:
2048 case MONO_TYPE_CHAR:
2056 case MONO_TYPE_R8: {
2059 /* boxed value type */
2060 t = g_new0 (MonoType, 1);
2062 klass = mono_class_from_mono_type (t);
2064 o = mono_object_new_checked (domain, klass, &error);
2065 if (!mono_error_ok (&error)) {
2066 mono_error_set_pending_exception (&error);
2069 v = ((gchar *) o) + sizeof (MonoObject);
2070 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2073 case MONO_TYPE_STRING:
2074 case MONO_TYPE_CLASS:
2075 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2078 g_assert_not_reached ();
2084 ICALL_EXPORT MonoReflectionType*
2085 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
2088 MonoReflectionType *ret;
2091 type = mono_field_get_type_checked (ref_field->field, &error);
2092 if (!mono_error_ok (&error)) {
2093 mono_error_set_pending_exception (&error);
2097 ret = mono_type_get_object_checked (mono_object_domain (ref_field), type, &error);
2098 if (!mono_error_ok (&error)) {
2099 mono_error_set_pending_exception (&error);
2106 /* From MonoProperty.cs */
2108 PInfo_Attributes = 1,
2109 PInfo_GetMethod = 1 << 1,
2110 PInfo_SetMethod = 1 << 2,
2111 PInfo_ReflectedType = 1 << 3,
2112 PInfo_DeclaringType = 1 << 4,
2117 ves_icall_MonoPropertyInfo_get_property_info (const MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2120 MonoReflectionType *rt;
2121 MonoReflectionMethod *rm;
2122 MonoDomain *domain = mono_object_domain (property);
2123 const MonoProperty *pproperty = property->property;
2125 if ((req_info & PInfo_ReflectedType) != 0) {
2126 rt = mono_type_get_object_checked (domain, &property->klass->byval_arg, &error);
2127 mono_error_raise_exception (&error);
2129 MONO_STRUCT_SETREF (info, parent, rt);
2131 if ((req_info & PInfo_DeclaringType) != 0) {
2132 rt = mono_type_get_object_checked (domain, &pproperty->parent->byval_arg, &error);
2133 mono_error_raise_exception (&error);
2135 MONO_STRUCT_SETREF (info, declaring_type, rt);
2138 if ((req_info & PInfo_Name) != 0)
2139 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, pproperty->name));
2141 if ((req_info & PInfo_Attributes) != 0)
2142 info->attrs = pproperty->attrs;
2144 if ((req_info & PInfo_GetMethod) != 0) {
2145 if (pproperty->get &&
2146 (((pproperty->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2147 pproperty->get->klass == property->klass)) {
2148 rm = mono_method_get_object_checked (domain, pproperty->get, property->klass, &error);
2149 mono_error_raise_exception (&error);
2154 MONO_STRUCT_SETREF (info, get, rm);
2156 if ((req_info & PInfo_SetMethod) != 0) {
2157 if (pproperty->set &&
2158 (((pproperty->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) ||
2159 pproperty->set->klass == property->klass)) {
2160 rm = mono_method_get_object_checked (domain, pproperty->set, property->klass, &error);
2161 mono_error_raise_exception (&error);
2166 MONO_STRUCT_SETREF (info, set, rm);
2169 * There may be other methods defined for properties, though, it seems they are not exposed
2170 * in the reflection API
2175 ves_icall_MonoEventInfo_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2178 MonoReflectionType *rt;
2179 MonoReflectionMethod *rm;
2180 MonoDomain *domain = mono_object_domain (event);
2182 rt = mono_type_get_object_checked (domain, &event->klass->byval_arg, &error);
2183 mono_error_raise_exception (&error);
2185 MONO_STRUCT_SETREF (info, reflected_type, rt);
2187 rt = mono_type_get_object_checked (domain, &event->event->parent->byval_arg, &error);
2188 mono_error_raise_exception (&error);
2190 MONO_STRUCT_SETREF (info, declaring_type, rt);
2192 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2193 info->attrs = event->event->attrs;
2195 if (event->event->add) {
2196 rm = mono_method_get_object_checked (domain, event->event->add, NULL, &error);
2197 mono_error_raise_exception (&error);
2202 MONO_STRUCT_SETREF (info, add_method, rm);
2204 if (event->event->remove) {
2205 rm = mono_method_get_object_checked (domain, event->event->remove, NULL, &error);
2206 mono_error_raise_exception (&error);
2211 MONO_STRUCT_SETREF (info, remove_method, rm);
2213 if (event->event->raise) {
2214 rm = mono_method_get_object_checked (domain, event->event->raise, NULL, &error);
2215 mono_error_raise_exception (&error);
2220 MONO_STRUCT_SETREF (info, raise_method, rm);
2222 #ifndef MONO_SMALL_CONFIG
2223 if (event->event->other) {
2225 while (event->event->other [n])
2227 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2229 for (i = 0; i < n; i++) {
2230 rm = mono_method_get_object_checked (domain, event->event->other [i], NULL, &error);
2231 mono_error_raise_exception (&error);
2232 mono_array_setref (info->other_methods, i, rm);
2239 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2244 mono_class_setup_interfaces (klass, error);
2245 if (!mono_error_ok (error))
2248 for (i = 0; i < klass->interface_count; i++) {
2249 ic = klass->interfaces [i];
2250 g_hash_table_insert (ifaces, ic, ic);
2252 collect_interfaces (ic, ifaces, error);
2253 if (!mono_error_ok (error))
2259 MonoArray *iface_array;
2260 MonoGenericContext *context;
2264 } FillIfaceArrayData;
2267 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2269 MonoReflectionType *rt;
2270 FillIfaceArrayData *data = (FillIfaceArrayData *)user_data;
2271 MonoClass *ic = (MonoClass *)key;
2272 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2274 if (!mono_error_ok (data->error))
2277 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2278 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2279 if (!mono_error_ok (data->error))
2283 rt = mono_type_get_object_checked (data->domain, ret, data->error);
2284 if (!mono_error_ok (data->error))
2287 mono_array_setref (data->iface_array, data->next_idx++, rt);
2290 mono_metadata_free_type (inflated);
2294 get_interfaces_hash (gconstpointer v1)
2296 MonoClass *k = (MonoClass*)v1;
2298 return k->type_token;
2301 ICALL_EXPORT MonoArray*
2302 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2305 MonoClass *klass = mono_class_from_mono_type (type->type);
2307 FillIfaceArrayData data = { 0 };
2310 GHashTable *iface_hash = g_hash_table_new (get_interfaces_hash, NULL);
2312 if (klass->generic_class && klass->generic_class->context.class_inst->is_open) {
2313 data.context = mono_class_get_context (klass);
2314 klass = klass->generic_class->container_class;
2317 for (parent = klass; parent; parent = parent->parent) {
2318 mono_class_setup_interfaces (parent, &error);
2319 if (!mono_error_ok (&error))
2321 collect_interfaces (parent, iface_hash, &error);
2322 if (!mono_error_ok (&error))
2326 data.error = &error;
2327 data.domain = mono_object_domain (type);
2329 len = g_hash_table_size (iface_hash);
2331 g_hash_table_destroy (iface_hash);
2332 if (!data.domain->empty_types)
2333 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2334 return data.domain->empty_types;
2337 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2338 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2339 if (!mono_error_ok (&error))
2342 g_hash_table_destroy (iface_hash);
2343 return data.iface_array;
2346 g_hash_table_destroy (iface_hash);
2347 mono_error_set_pending_exception (&error);
2352 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2354 gboolean variance_used;
2355 MonoClass *klass = mono_class_from_mono_type (type->type);
2356 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2357 MonoReflectionMethod *member;
2360 int i = 0, len, ioffset;
2364 mono_class_init_checked (klass, &error);
2365 mono_error_raise_exception (&error);
2366 mono_class_init_checked (iclass, &error);
2367 mono_error_raise_exception (&error);
2369 mono_class_setup_vtable (klass);
2371 ioffset = mono_class_interface_offset_with_variance (klass, iclass, &variance_used);
2375 len = mono_class_num_methods (iclass);
2376 domain = mono_object_domain (type);
2377 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2378 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2380 while ((method = mono_class_get_methods (iclass, &iter))) {
2381 member = mono_method_get_object_checked (domain, method, iclass, &error);
2382 mono_error_raise_exception (&error);
2383 mono_array_setref (*methods, i, member);
2384 member = mono_method_get_object_checked (domain, klass->vtable [i + ioffset], klass, &error);
2385 mono_error_raise_exception (&error);
2386 mono_array_setref (*targets, i, member);
2393 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2396 MonoClass *klass = mono_class_from_mono_type (type->type);
2398 mono_class_init_checked (klass, &error);
2399 mono_error_raise_exception (&error);
2401 if (image_is_dynamic (klass->image)) {
2402 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2403 *packing = tb->packing_size;
2404 *size = tb->class_size;
2406 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2410 ICALL_EXPORT MonoReflectionType*
2411 ves_icall_RuntimeTypeHandle_GetElementType (MonoReflectionType *type)
2414 MonoReflectionType *ret;
2417 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY) {
2418 ret = mono_type_get_object_checked (mono_object_domain (type), &type->type->data.klass->byval_arg, &error);
2419 mono_error_raise_exception (&error);
2424 klass = mono_class_from_mono_type (type->type);
2425 mono_class_init_checked (klass, &error);
2426 mono_error_raise_exception (&error);
2428 // GetElementType should only return a type for:
2429 // Array Pointer PassedByRef
2430 if (type->type->byref)
2431 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->byval_arg, &error);
2432 else if (klass->element_class && MONO_CLASS_IS_ARRAY (klass))
2433 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2434 else if (klass->element_class && type->type->type == MONO_TYPE_PTR)
2435 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->element_class->byval_arg, &error);
2439 mono_error_raise_exception (&error);
2444 ICALL_EXPORT MonoReflectionType*
2445 ves_icall_RuntimeTypeHandle_GetBaseType (MonoReflectionType *type)
2448 MonoReflectionType *ret;
2450 if (type->type->byref)
2453 MonoClass *klass = mono_class_from_mono_type (type->type);
2457 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->parent->byval_arg, &error);
2458 mono_error_raise_exception (&error);
2463 ICALL_EXPORT MonoBoolean
2464 ves_icall_RuntimeTypeHandle_IsPointer (MonoReflectionType *type)
2466 return type->type->type == MONO_TYPE_PTR;
2469 ICALL_EXPORT MonoBoolean
2470 ves_icall_RuntimeTypeHandle_IsPrimitive (MonoReflectionType *type)
2472 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)));
2475 ICALL_EXPORT MonoBoolean
2476 ves_icall_RuntimeTypeHandle_IsByRef (MonoReflectionType *type)
2478 return type->type->byref;
2481 ICALL_EXPORT MonoBoolean
2482 ves_icall_RuntimeTypeHandle_IsComObject (MonoReflectionType *type)
2485 MonoClass *klass = mono_class_from_mono_type (type->type);
2486 mono_class_init_checked (klass, &error);
2487 mono_error_raise_exception (&error);
2489 return mono_class_is_com_object (klass);
2492 ICALL_EXPORT guint32
2493 ves_icall_reflection_get_token (MonoObject* obj)
2496 guint32 result = mono_reflection_get_token_checked (obj, &error);
2497 mono_error_set_pending_exception (&error);
2501 ICALL_EXPORT MonoReflectionModule*
2502 ves_icall_RuntimeTypeHandle_GetModule (MonoReflectionType *type)
2505 MonoReflectionModule *result = NULL;
2506 MonoClass *klass = mono_class_from_mono_type (type->type);
2507 result = mono_module_get_object_checked (mono_object_domain (type), klass->image, &error);
2508 if (!mono_error_ok (&error))
2509 mono_error_set_pending_exception (&error);
2513 ICALL_EXPORT MonoReflectionAssembly*
2514 ves_icall_RuntimeTypeHandle_GetAssembly (MonoReflectionType *type)
2517 MonoDomain *domain = mono_domain_get ();
2518 MonoClass *klass = mono_class_from_mono_type (type->type);
2519 MonoReflectionAssembly *result = mono_assembly_get_object_checked (domain, klass->image->assembly, &error);
2521 mono_error_set_pending_exception (&error);
2525 ICALL_EXPORT MonoReflectionType*
2526 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2529 MonoReflectionType *ret;
2530 MonoDomain *domain = mono_domain_get ();
2533 if (type->type->byref)
2535 if (type->type->type == MONO_TYPE_VAR) {
2536 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2537 klass = param ? param->owner.klass : NULL;
2538 } else if (type->type->type == MONO_TYPE_MVAR) {
2539 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2540 klass = param ? param->owner.method->klass : NULL;
2542 klass = mono_class_from_mono_type (type->type)->nested_in;
2548 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
2549 mono_error_raise_exception (&error);
2554 ICALL_EXPORT MonoString*
2555 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2557 MonoDomain *domain = mono_domain_get ();
2558 MonoClass *klass = mono_class_from_mono_type (type->type);
2560 if (type->type->byref) {
2561 char *n = g_strdup_printf ("%s&", klass->name);
2562 MonoString *res = mono_string_new (domain, n);
2568 return mono_string_new (domain, klass->name);
2572 ICALL_EXPORT MonoString*
2573 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2575 MonoDomain *domain = mono_domain_get ();
2576 MonoClass *klass = mono_class_from_mono_type (type->type);
2578 while (klass->nested_in)
2579 klass = klass->nested_in;
2581 if (klass->name_space [0] == '\0')
2584 return mono_string_new (domain, klass->name_space);
2588 ves_icall_RuntimeTypeHandle_GetArrayRank (MonoReflectionType *type)
2592 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY) {
2593 mono_set_pending_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2597 klass = mono_class_from_mono_type (type->type);
2603 create_type_array (MonoDomain *domain, MonoBoolean runtimeTypeArray, int count)
2606 res = mono_array_new (domain, runtimeTypeArray ? mono_defaults.runtimetype_class : mono_defaults.systemtype_class, count);
2610 ICALL_EXPORT MonoArray*
2611 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type, MonoBoolean runtimeTypeArray)
2614 MonoReflectionType *rt;
2616 MonoClass *klass, *pklass;
2617 MonoDomain *domain = mono_object_domain (type);
2620 klass = mono_class_from_mono_type (type->type);
2622 if (klass->generic_container) {
2623 MonoGenericContainer *container = klass->generic_container;
2624 res = create_type_array (domain, runtimeTypeArray, container->type_argc);
2625 for (i = 0; i < container->type_argc; ++i) {
2626 pklass = mono_class_from_generic_parameter_internal (mono_generic_container_get_param (container, i));
2628 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
2629 mono_error_raise_exception (&error);
2631 mono_array_setref (res, i, rt);
2633 } else if (klass->generic_class) {
2634 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2635 res = create_type_array (domain, runtimeTypeArray, inst->type_argc);
2636 for (i = 0; i < inst->type_argc; ++i) {
2637 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
2638 mono_error_raise_exception (&error);
2640 mono_array_setref (res, i, rt);
2648 ICALL_EXPORT gboolean
2649 ves_icall_RuntimeTypeHandle_IsGenericTypeDefinition (MonoReflectionType *type)
2653 if (!IS_MONOTYPE (type))
2656 if (type->type->byref)
2659 klass = mono_class_from_mono_type (type->type);
2660 return klass->generic_container != NULL;
2663 ICALL_EXPORT MonoReflectionType*
2664 ves_icall_RuntimeTypeHandle_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2667 MonoReflectionType *ret;
2670 if (type->type->byref)
2673 klass = mono_class_from_mono_type (type->type);
2675 if (klass->generic_container) {
2676 return type; /* check this one */
2678 if (klass->generic_class) {
2679 MonoClass *generic_class = klass->generic_class->container_class;
2682 tb = mono_class_get_ref_info (generic_class);
2684 if (generic_class->wastypebuilder && tb)
2685 return (MonoReflectionType *)tb;
2687 ret = mono_type_get_object_checked (mono_object_domain (type), &generic_class->byval_arg, &error);
2688 mono_error_raise_exception (&error);
2696 ICALL_EXPORT MonoReflectionType*
2697 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2700 MonoReflectionType *ret;
2702 MonoType *geninst, **types;
2705 g_assert (IS_MONOTYPE (type));
2706 mono_class_init_checked (mono_class_from_mono_type (type->type), &error);
2707 mono_error_raise_exception (&error);
2709 count = mono_array_length (type_array);
2710 types = g_new0 (MonoType *, count);
2712 for (i = 0; i < count; i++) {
2713 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (type_array, gpointer, i);
2714 types [i] = t->type;
2717 geninst = mono_reflection_bind_generic_parameters (type, count, types, &error);
2720 mono_error_set_pending_exception (&error);
2724 klass = mono_class_from_mono_type (geninst);
2726 /*we might inflate to the GTD*/
2727 if (klass->generic_class && !mono_verifier_class_is_valid_generic_instantiation (klass)) {
2728 mono_set_pending_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2732 ret = mono_type_get_object_checked (mono_object_domain (type), geninst, &error);
2733 mono_error_raise_exception (&error);
2738 ICALL_EXPORT gboolean
2739 ves_icall_RuntimeTypeHandle_HasInstantiation (MonoReflectionType *type)
2743 if (!IS_MONOTYPE (type))
2746 if (type->type->byref)
2749 klass = mono_class_from_mono_type (type->type);
2750 return klass->generic_class != NULL || klass->generic_container != NULL;
2754 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2756 if (!IS_MONOTYPE (type))
2759 if (is_generic_parameter (type->type))
2760 return mono_type_get_generic_param_num (type->type);
2764 ICALL_EXPORT GenericParameterAttributes
2765 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2767 g_assert (IS_MONOTYPE (type));
2768 g_assert (is_generic_parameter (type->type));
2769 return (GenericParameterAttributes)mono_generic_param_info (type->type->data.generic_param)->flags;
2772 ICALL_EXPORT MonoArray *
2773 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2776 MonoReflectionType *rt;
2777 MonoGenericParamInfo *param_info;
2783 g_assert (IS_MONOTYPE (type));
2785 domain = mono_object_domain (type);
2786 param_info = mono_generic_param_info (type->type->data.generic_param);
2787 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2790 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2791 for (i = 0; i < count; i++) {
2792 rt = mono_type_get_object_checked (domain, ¶m_info->constraints [i]->byval_arg, &error);
2793 mono_error_raise_exception (&error);
2795 mono_array_setref (res, i, rt);
2802 ICALL_EXPORT MonoBoolean
2803 ves_icall_RuntimeTypeHandle_IsGenericVariable (MonoReflectionType *type)
2805 return is_generic_parameter (type->type);
2808 ICALL_EXPORT MonoBoolean
2809 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2811 return is_generic_parameter (tb->type.type);
2815 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2816 MonoReflectionType *t)
2818 enumtype->type = t->type;
2821 ICALL_EXPORT MonoReflectionMethod*
2822 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2823 MonoReflectionMethod* generic)
2830 MonoReflectionMethod *ret = NULL;
2832 domain = ((MonoObject *)type)->vtable->domain;
2834 klass = mono_class_from_mono_type (type->type);
2835 mono_class_init_checked (klass, &error);
2836 mono_error_raise_exception (&error);
2839 while ((method = mono_class_get_methods (klass, &iter))) {
2840 if (method->token == generic->method->token) {
2841 ret = mono_method_get_object_checked (domain, method, klass, &error);
2842 mono_error_raise_exception (&error);
2849 ICALL_EXPORT MonoReflectionMethod *
2850 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2853 MonoType *type = ref_type->type;
2855 MonoReflectionMethod *ret = NULL;
2857 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR)) {
2858 mono_set_pending_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2861 if (type->type == MONO_TYPE_VAR)
2864 method = mono_type_get_generic_param_owner (type)->owner.method;
2867 ret = mono_method_get_object_checked (mono_object_domain (ref_type), method, method->klass, &error);
2868 if (!mono_error_ok (&error))
2869 mono_set_pending_exception (mono_error_convert_to_exception (&error));
2873 ICALL_EXPORT MonoBoolean
2874 ves_icall_System_RuntimeType_IsTypeExportedToWindowsRuntime (void)
2876 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2880 ICALL_EXPORT MonoBoolean
2881 ves_icall_System_RuntimeType_IsWindowsRuntimeObjectType (void)
2883 mono_set_pending_exception (mono_get_exception_not_implemented (NULL));
2888 ves_icall_MonoMethod_GetPInvoke (MonoReflectionMethod *method, int* flags, MonoString** entry_point, MonoString** dll_name)
2890 MonoDomain *domain = mono_domain_get ();
2891 MonoImage *image = method->method->klass->image;
2892 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method->method;
2893 MonoTableInfo *tables = image->tables;
2894 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2895 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2896 guint32 im_cols [MONO_IMPLMAP_SIZE];
2897 guint32 scope_token;
2898 const char *import = NULL;
2899 const char *scope = NULL;
2901 if (image_is_dynamic (image)) {
2902 MonoReflectionMethodAux *method_aux =
2903 (MonoReflectionMethodAux *)g_hash_table_lookup (((MonoDynamicImage*)image)->method_aux_hash, method->method);
2905 import = method_aux->dllentry;
2906 scope = method_aux->dll;
2909 if (!import || !scope) {
2910 mono_set_pending_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2915 if (piinfo->implmap_idx) {
2916 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2918 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2919 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2920 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2921 scope = mono_metadata_string_heap (image, scope_token);
2925 *flags = piinfo->piflags;
2926 *entry_point = mono_string_new (domain, import);
2927 *dll_name = mono_string_new (domain, scope);
2930 ICALL_EXPORT MonoReflectionMethod *
2931 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2933 MonoMethodInflated *imethod;
2935 MonoReflectionMethod *ret = NULL;
2938 if (method->method->is_generic)
2941 if (!method->method->is_inflated)
2944 imethod = (MonoMethodInflated *) method->method;
2946 result = imethod->declaring;
2947 /* Not a generic method. */
2948 if (!result->is_generic)
2951 if (image_is_dynamic (method->method->klass->image)) {
2952 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2953 MonoReflectionMethod *res;
2956 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2957 * the dynamic case as well ?
2959 mono_image_lock ((MonoImage*)image);
2960 res = (MonoReflectionMethod *)mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2961 mono_image_unlock ((MonoImage*)image);
2967 if (imethod->context.class_inst) {
2968 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2969 /*Generic methods gets the context of the GTD.*/
2970 if (mono_class_get_context (klass)) {
2971 result = mono_class_inflate_generic_method_full_checked (result, klass, mono_class_get_context (klass), &error);
2972 if (!mono_error_ok (&error))
2977 ret = mono_method_get_object_checked (mono_object_domain (method), result, NULL, &error);
2979 if (!mono_error_ok (&error))
2980 mono_error_set_pending_exception (&error);
2984 ICALL_EXPORT gboolean
2985 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2987 return mono_method_signature (method->method)->generic_param_count != 0;
2990 ICALL_EXPORT gboolean
2991 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2993 return method->method->is_generic;
2996 ICALL_EXPORT MonoArray*
2997 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3000 MonoReflectionType *rt;
3005 domain = mono_object_domain (method);
3007 if (method->method->is_inflated) {
3008 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3011 count = inst->type_argc;
3012 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3014 for (i = 0; i < count; i++) {
3015 rt = mono_type_get_object_checked (domain, inst->type_argv [i], &error);
3016 mono_error_raise_exception (&error);
3018 mono_array_setref (res, i, rt);
3025 count = mono_method_signature (method->method)->generic_param_count;
3026 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3028 for (i = 0; i < count; i++) {
3029 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3030 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3031 MonoClass *pklass = mono_class_from_generic_parameter_internal (param);
3033 rt = mono_type_get_object_checked (domain, &pklass->byval_arg, &error);
3034 mono_error_raise_exception (&error);
3036 mono_array_setref (res, i, rt);
3042 ICALL_EXPORT MonoObject *
3043 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoException **exc)
3047 * Invoke from reflection is supposed to always be a virtual call (the API
3048 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3049 * greater flexibility.
3051 MonoMethod *m = method->method;
3052 MonoMethodSignature *sig = mono_method_signature (m);
3055 void *obj = this_arg;
3059 if (mono_security_core_clr_enabled ())
3060 mono_security_core_clr_ensure_reflection_access_method (m);
3062 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3063 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, &error)) {
3064 mono_error_cleanup (&error); /* FIXME does this make sense? */
3065 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
3070 if (!mono_object_isinst (this_arg, m->klass)) {
3071 char *this_name = mono_type_get_full_name (mono_object_get_class (this_arg));
3072 char *target_name = mono_type_get_full_name (m->klass);
3073 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
3074 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
3076 g_free (target_name);
3080 m = mono_object_get_virtual_method (this_arg, m);
3081 /* must pass the pointer to the value for valuetype methods */
3082 if (m->klass->valuetype)
3083 obj = mono_object_unbox (this_arg);
3084 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3085 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3090 if (sig->ret->byref) {
3091 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"));
3095 pcount = params? mono_array_length (params): 0;
3096 if (pcount != sig->param_count) {
3097 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3101 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this_arg) {
3102 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."));
3106 image = m->klass->image;
3107 if (image->assembly->ref_only) {
3108 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."));
3112 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
3113 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
3117 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3121 intptr_t *lower_bounds;
3122 pcount = mono_array_length (params);
3123 lengths = (uintptr_t *)alloca (sizeof (uintptr_t) * pcount);
3124 /* Note: the synthetized array .ctors have int32 as argument type */
3125 for (i = 0; i < pcount; ++i)
3126 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3128 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
3129 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
3130 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3131 if (!mono_error_ok (&error)) {
3132 mono_error_set_pending_exception (&error);
3136 for (i = 0; i < mono_array_length (arr); ++i) {
3137 MonoArray *subarray = mono_array_new_full_checked (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL, &error);
3138 if (!mono_error_ok (&error)) {
3139 mono_error_set_pending_exception (&error);
3142 mono_array_setref_fast (arr, i, subarray);
3144 return (MonoObject*)arr;
3147 if (m->klass->rank == pcount) {
3148 /* Only lengths provided. */
3149 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, NULL, &error);
3150 if (!mono_error_ok (&error)) {
3151 mono_error_set_pending_exception (&error);
3155 return (MonoObject*)arr;
3157 g_assert (pcount == (m->klass->rank * 2));
3158 /* The arguments are lower-bound-length pairs */
3159 lower_bounds = (intptr_t *)g_alloca (sizeof (intptr_t) * pcount);
3161 for (i = 0; i < pcount / 2; ++i) {
3162 lower_bounds [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2)) + sizeof (MonoObject));
3163 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, (i * 2) + 1) + sizeof (MonoObject));
3166 arr = mono_array_new_full_checked (mono_object_domain (params), m->klass, lengths, lower_bounds, &error);
3167 if (!mono_error_ok (&error)) {
3168 mono_error_set_pending_exception (&error);
3172 return (MonoObject*)arr;
3175 return mono_runtime_invoke_array (m, obj, params, NULL);
3178 #ifndef DISABLE_REMOTING
3179 ICALL_EXPORT MonoObject *
3180 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this_arg, MonoArray *params, MonoArray **outArgs)
3183 MonoDomain *domain = mono_object_domain (method);
3184 MonoMethod *m = method->method;
3185 MonoMethodSignature *sig = mono_method_signature (m);
3186 MonoArray *out_args;
3188 int i, j, outarg_count = 0;
3190 if (m->klass == mono_defaults.object_class) {
3191 if (!strcmp (m->name, "FieldGetter")) {
3192 MonoClass *k = this_arg->vtable->klass;
3196 /* If this is a proxy, then it must be a CBO */
3197 if (k == mono_defaults.transparent_proxy_class) {
3198 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3199 this_arg = tp->rp->unwrapped_server;
3200 g_assert (this_arg);
3201 k = this_arg->vtable->klass;
3204 name = mono_array_get (params, MonoString *, 1);
3205 str = mono_string_to_utf8 (name);
3208 MonoClassField* field = mono_class_get_field_from_name (k, str);
3210 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3211 if (field_klass->valuetype) {
3212 result = mono_value_box_checked (domain, field_klass, (char *)this_arg + field->offset, &error);
3213 mono_error_set_pending_exception (&error);
3214 /* fallthru to cleanup */
3216 result = (MonoObject *)*((gpointer *)((char *)this_arg + field->offset));
3218 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3219 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3220 mono_array_setref (out_args, 0, result);
3228 g_assert_not_reached ();
3230 } else if (!strcmp (m->name, "FieldSetter")) {
3231 MonoClass *k = this_arg->vtable->klass;
3237 /* If this is a proxy, then it must be a CBO */
3238 if (k == mono_defaults.transparent_proxy_class) {
3239 MonoTransparentProxy *tp = (MonoTransparentProxy*) this_arg;
3240 this_arg = tp->rp->unwrapped_server;
3241 g_assert (this_arg);
3242 k = this_arg->vtable->klass;
3245 name = mono_array_get (params, MonoString *, 1);
3246 str = mono_string_to_utf8 (name);
3249 MonoClassField* field = mono_class_get_field_from_name (k, str);
3251 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3252 MonoObject *val = (MonoObject *)mono_array_get (params, gpointer, 2);
3254 if (field_klass->valuetype) {
3255 size = mono_type_size (field->type, &align);
3256 g_assert (size == mono_class_value_size (field_klass, NULL));
3257 mono_gc_wbarrier_value_copy ((char *)this_arg + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3259 mono_gc_wbarrier_set_field (this_arg, (char*)this_arg + field->offset, val);
3262 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3263 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3273 g_assert_not_reached ();
3278 for (i = 0; i < mono_array_length (params); i++) {
3279 if (sig->params [i]->byref)
3283 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3285 /* handle constructors only for objects already allocated */
3286 if (!strcmp (method->method->name, ".ctor"))
3287 g_assert (this_arg);
3289 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3290 g_assert (!method->method->klass->valuetype);
3291 result = mono_runtime_invoke_array (method->method, this_arg, params, NULL);
3293 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3294 if (sig->params [i]->byref) {
3296 arg = mono_array_get (params, gpointer, i);
3297 mono_array_setref (out_args, j, arg);
3302 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3309 read_enum_value (const char *mem, int type)
3312 case MONO_TYPE_BOOLEAN:
3314 return *(guint8*)mem;
3316 return *(gint8*)mem;
3317 case MONO_TYPE_CHAR:
3319 return read16 (mem);
3321 return (gint16) read16 (mem);
3323 return read32 (mem);
3325 return (gint32) read32 (mem);
3328 return read64 (mem);
3330 g_assert_not_reached ();
3336 write_enum_value (char *mem, int type, guint64 value)
3340 case MONO_TYPE_I1: {
3341 guint8 *p = (guint8*)mem;
3346 case MONO_TYPE_I2: {
3347 guint16 *p = (guint16 *)mem;
3352 case MONO_TYPE_I4: {
3353 guint32 *p = (guint32 *)mem;
3358 case MONO_TYPE_I8: {
3359 guint64 *p = (guint64 *)mem;
3364 g_assert_not_reached ();
3369 ICALL_EXPORT MonoObject *
3370 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, guint64 value)
3378 domain = mono_object_domain (enumType);
3379 enumc = mono_class_from_mono_type (enumType->type);
3381 mono_class_init_checked (enumc, &error);
3382 mono_error_raise_exception (&error);
3384 etype = mono_class_enum_basetype (enumc);
3386 res = mono_object_new_checked (domain, enumc, &error);
3387 mono_error_raise_exception (&error);
3388 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, value);
3393 ICALL_EXPORT MonoBoolean
3394 ves_icall_System_Enum_InternalHasFlag (MonoObject *a, MonoObject *b)
3396 int size = mono_class_value_size (a->vtable->klass, NULL);
3397 guint64 a_val = 0, b_val = 0;
3399 memcpy (&a_val, mono_object_unbox (a), size);
3400 memcpy (&b_val, mono_object_unbox (b), size);
3402 return (a_val & b_val) == b_val;
3405 ICALL_EXPORT MonoObject *
3406 ves_icall_System_Enum_get_value (MonoObject *eobj)
3418 g_assert (eobj->vtable->klass->enumtype);
3420 enumc = mono_class_from_mono_type (mono_class_enum_basetype (eobj->vtable->klass));
3421 res = mono_object_new_checked (mono_object_domain (eobj), enumc, &error);
3422 mono_error_raise_exception (&error);
3423 dst = (char *)res + sizeof (MonoObject);
3424 src = (char *)eobj + sizeof (MonoObject);
3425 size = mono_class_value_size (enumc, NULL);
3427 memcpy (dst, src, size);
3432 ICALL_EXPORT MonoReflectionType *
3433 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3436 MonoReflectionType *ret;
3440 klass = mono_class_from_mono_type (type->type);
3441 mono_class_init_checked (klass, &error);
3442 mono_error_raise_exception (&error);
3444 etype = mono_class_enum_basetype (klass);
3446 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3450 ret = mono_type_get_object_checked (mono_object_domain (type), etype, &error);
3451 mono_error_raise_exception (&error);
3457 ves_icall_System_Enum_compare_value_to (MonoObject *eobj, MonoObject *other)
3459 gpointer tdata = (char *)eobj + sizeof (MonoObject);
3460 gpointer odata = (char *)other + sizeof (MonoObject);
3461 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3462 g_assert (basetype);
3467 if (eobj->vtable->klass != other->vtable->klass)
3470 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3471 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3472 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3475 return me > other ? 1 : -1; \
3478 switch (basetype->type) {
3480 COMPARE_ENUM_VALUES (guint8);
3482 COMPARE_ENUM_VALUES (gint8);
3483 case MONO_TYPE_CHAR:
3485 COMPARE_ENUM_VALUES (guint16);
3487 COMPARE_ENUM_VALUES (gint16);
3489 COMPARE_ENUM_VALUES (guint32);
3491 COMPARE_ENUM_VALUES (gint32);
3493 COMPARE_ENUM_VALUES (guint64);
3495 COMPARE_ENUM_VALUES (gint64);
3499 #undef COMPARE_ENUM_VALUES
3500 /* indicates that the enum was of an unsupported unerlying type */
3505 ves_icall_System_Enum_get_hashcode (MonoObject *eobj)
3507 gpointer data = (char *)eobj + sizeof (MonoObject);
3508 MonoType *basetype = mono_class_enum_basetype (eobj->vtable->klass);
3509 g_assert (basetype);
3511 switch (basetype->type) {
3512 case MONO_TYPE_I1: {
3513 gint8 value = *((gint8*)data);
3514 return ((int)value ^ (int)value << 8);
3517 return *((guint8*)data);
3518 case MONO_TYPE_CHAR:
3520 return *((guint16*)data);
3522 case MONO_TYPE_I2: {
3523 gint16 value = *((gint16*)data);
3524 return ((int)(guint16)value | (((int)value) << 16));
3527 return *((guint32*)data);
3529 return *((gint32*)data);
3531 case MONO_TYPE_I8: {
3532 gint64 value = *((gint64*)data);
3533 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3536 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3541 ICALL_EXPORT MonoBoolean
3542 ves_icall_System_Enum_GetEnumValuesAndNames (MonoReflectionType *type, MonoArray **values, MonoArray **names)
3545 MonoDomain *domain = mono_object_domain (type);
3546 MonoClass *enumc = mono_class_from_mono_type (type->type);
3547 guint j = 0, nvalues;
3549 MonoClassField *field;
3551 guint64 field_value, previous_value = 0;
3552 gboolean sorted = TRUE;
3554 mono_class_init_checked (enumc, &error);
3555 mono_error_raise_exception (&error);
3557 if (!enumc->enumtype) {
3558 mono_set_pending_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3562 base_type = mono_class_enum_basetype (enumc)->type;
3564 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3565 *names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3566 *values = mono_array_new (domain, mono_defaults.uint64_class, nvalues);
3569 while ((field = mono_class_get_fields (enumc, &iter))) {
3571 MonoTypeEnum def_type;
3573 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3575 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3577 if (mono_field_is_deleted (field))
3579 mono_array_setref (*names, j, mono_string_new (domain, mono_field_get_name (field)));
3581 p = mono_class_get_field_default_value (field, &def_type);
3582 /* len = */ mono_metadata_decode_blob_size (p, &p);
3584 field_value = read_enum_value (p, base_type);
3585 mono_array_set (*values, guint64, j, field_value);
3587 if (previous_value > field_value)
3590 previous_value = field_value;
3598 BFLAGS_IgnoreCase = 1,
3599 BFLAGS_DeclaredOnly = 2,
3600 BFLAGS_Instance = 4,
3602 BFLAGS_Public = 0x10,
3603 BFLAGS_NonPublic = 0x20,
3604 BFLAGS_FlattenHierarchy = 0x40,
3605 BFLAGS_InvokeMethod = 0x100,
3606 BFLAGS_CreateInstance = 0x200,
3607 BFLAGS_GetField = 0x400,
3608 BFLAGS_SetField = 0x800,
3609 BFLAGS_GetProperty = 0x1000,
3610 BFLAGS_SetProperty = 0x2000,
3611 BFLAGS_ExactBinding = 0x10000,
3612 BFLAGS_SuppressChangeType = 0x20000,
3613 BFLAGS_OptionalParamBinding = 0x40000
3616 ICALL_EXPORT MonoArray*
3617 ves_icall_Type_GetFields_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
3621 MonoClass *startklass, *klass, *refklass;
3626 char *utf8_name = NULL;
3627 int (*compare_func) (const char *s1, const char *s2) = NULL;
3628 MonoClassField *field;
3629 MonoPtrArray tmp_array;
3631 domain = ((MonoObject *)type)->vtable->domain;
3632 if (type->type->byref)
3633 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3635 klass = startklass = mono_class_from_mono_type (type->type);
3636 refklass = mono_class_from_mono_type (reftype->type);
3638 mono_ptr_array_init (tmp_array, 2, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection fields list");
3641 if (mono_class_has_failure (klass)) {
3642 mono_ptr_array_destroy (tmp_array);
3643 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3648 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3649 guint32 flags = mono_field_get_flags (field);
3651 if (mono_field_is_deleted_with_flags (field, flags))
3653 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3654 if (bflags & BFLAGS_Public)
3656 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3657 if (bflags & BFLAGS_NonPublic) {
3664 if (flags & FIELD_ATTRIBUTE_STATIC) {
3665 if (bflags & BFLAGS_Static)
3666 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3669 if (bflags & BFLAGS_Instance)
3677 if (utf8_name == NULL) {
3678 utf8_name = mono_string_to_utf8 (name);
3679 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3682 if (compare_func (mono_field_get_name (field), utf8_name))
3686 member = (MonoObject*)mono_field_get_object_checked (domain, refklass, field, &error);
3687 if (!mono_error_ok (&error))
3689 mono_ptr_array_append (tmp_array, member);
3691 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3694 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3696 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3697 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3699 mono_ptr_array_destroy (tmp_array);
3701 if (utf8_name != NULL)
3706 mono_ptr_array_destroy (tmp_array);
3707 mono_error_raise_exception (&error);
3708 g_assert_not_reached ();
3712 method_nonpublic (MonoMethod* method, gboolean start_klass)
3714 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3715 case METHOD_ATTRIBUTE_ASSEM:
3716 return (start_klass || mono_defaults.generic_ilist_class);
3717 case METHOD_ATTRIBUTE_PRIVATE:
3719 case METHOD_ATTRIBUTE_PUBLIC:
3727 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3730 MonoClass *startklass;
3734 /*FIXME, use MonoBitSet*/
3735 guint32 method_slots_default [8];
3736 guint32 *method_slots = NULL;
3737 int (*compare_func) (const char *s1, const char *s2) = NULL;
3739 array = g_ptr_array_new ();
3744 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3746 /* An optimization for calls made from Delegate:CreateDelegate () */
3747 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3748 method = mono_get_delegate_invoke (klass);
3749 if (mono_loader_get_last_error ())
3752 g_ptr_array_add (array, method);
3756 mono_class_setup_methods (klass);
3757 mono_class_setup_vtable (klass);
3758 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3761 if (is_generic_parameter (&klass->byval_arg))
3762 nslots = mono_class_get_vtable_size (klass->parent);
3764 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3765 if (nslots >= sizeof (method_slots_default) * 8) {
3766 method_slots = g_new0 (guint32, nslots / 32 + 1);
3768 method_slots = method_slots_default;
3769 memset (method_slots, 0, sizeof (method_slots_default));
3772 mono_class_setup_methods (klass);
3773 mono_class_setup_vtable (klass);
3774 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
3778 while ((method = mono_class_get_methods (klass, &iter))) {
3780 if (method->slot != -1) {
3781 g_assert (method->slot < nslots);
3782 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3784 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3785 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3788 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3790 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3791 if (bflags & BFLAGS_Public)
3793 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3799 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3800 if (bflags & BFLAGS_Static)
3801 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3804 if (bflags & BFLAGS_Instance)
3812 if (compare_func (name, method->name))
3817 g_ptr_array_add (array, method);
3819 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3821 if (method_slots != method_slots_default)
3822 g_free (method_slots);
3827 if (method_slots != method_slots_default)
3828 g_free (method_slots);
3829 g_ptr_array_free (array, TRUE);
3831 if (mono_class_has_failure (klass)) {
3832 *ex = mono_class_get_exception_for_failure (klass);
3834 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3835 mono_loader_clear_error ();
3840 ICALL_EXPORT MonoArray*
3841 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3843 static MonoClass *MethodInfo_array;
3847 MonoVTable *array_vtable;
3848 MonoException *ex = NULL;
3849 const char *mname = NULL;
3850 GPtrArray *method_array;
3851 MonoClass *klass, *refklass;
3854 mono_error_init (&error);
3856 if (!MethodInfo_array) {
3857 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3858 mono_memory_barrier ();
3859 MethodInfo_array = klass;
3862 klass = mono_class_from_mono_type (type->type);
3863 refklass = mono_class_from_mono_type (reftype->type);
3864 domain = ((MonoObject *)type)->vtable->domain;
3865 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, &error);
3866 if (!is_ok (&error)) {
3867 mono_error_set_pending_exception (&error);
3870 if (type->type->byref) {
3871 res = mono_array_new_specific_checked (array_vtable, 0, &error);
3872 mono_error_set_pending_exception (&error);
3878 mname = mono_string_to_utf8 (name);
3880 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3881 g_free ((char*)mname);
3883 mono_set_pending_exception (ex);
3887 res = mono_array_new_specific_checked (array_vtable, method_array->len, &error);
3888 if (!mono_error_ok (&error)) {
3889 mono_error_set_pending_exception (&error);
3893 for (i = 0; i < method_array->len; ++i) {
3894 MonoMethod *method = (MonoMethod *)g_ptr_array_index (method_array, i);
3895 MonoReflectionMethod *rm = mono_method_get_object_checked (domain, method, refklass, &error);
3896 if (!mono_error_ok (&error))
3898 mono_array_setref (res, i, rm);
3902 g_ptr_array_free (method_array, TRUE);
3903 if (!mono_error_ok (&error))
3904 mono_set_pending_exception (mono_error_convert_to_exception (&error));
3908 ICALL_EXPORT MonoArray*
3909 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3912 MonoClass *startklass, *klass, *refklass;
3917 gpointer iter = NULL;
3918 MonoPtrArray tmp_array;
3921 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection constructors list"); /*FIXME, guestimating*/
3923 domain = ((MonoObject *)type)->vtable->domain;
3924 if (type->type->byref)
3925 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3926 klass = startklass = mono_class_from_mono_type (type->type);
3927 refklass = mono_class_from_mono_type (reftype->type);
3929 mono_class_setup_methods (klass);
3930 if (mono_class_has_failure (klass)) {
3931 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
3936 while ((method = mono_class_get_methods (klass, &iter))) {
3938 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3940 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3941 if (bflags & BFLAGS_Public)
3944 if (bflags & BFLAGS_NonPublic)
3950 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3951 if (bflags & BFLAGS_Static)
3952 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3955 if (bflags & BFLAGS_Instance)
3961 member = (MonoObject*)mono_method_get_object_checked (domain, method, refklass, &error);
3962 if (!mono_error_ok (&error)) {
3963 mono_error_set_pending_exception (&error);
3967 mono_ptr_array_append (tmp_array, member);
3970 res = mono_array_new_cached (domain, mono_class_get_constructor_info_class (), mono_ptr_array_size (tmp_array));
3972 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3973 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3975 mono_ptr_array_destroy (tmp_array);
3981 property_hash (gconstpointer data)
3983 MonoProperty *prop = (MonoProperty*)data;
3985 return g_str_hash (prop->name);
3989 method_declaring_signatures_equal (MonoMethod *method1, MonoMethod *method2)
3991 if (method1->is_inflated)
3992 method1 = ((MonoMethodInflated*) method1)->declaring;
3993 if (method2->is_inflated)
3994 method2 = ((MonoMethodInflated*) method2)->declaring;
3996 return mono_metadata_signature_equal (mono_method_signature (method1), mono_method_signature (method2));
4000 property_equal (MonoProperty *prop1, MonoProperty *prop2)
4002 // Properties are hide-by-name-and-signature
4003 if (!g_str_equal (prop1->name, prop2->name))
4006 /* If we see a property in a generic method, we want to
4007 compare the generic signatures, not the inflated signatures
4008 because we might conflate two properties that were
4012 public T this[T t] { getter { return t; } } // method 1
4013 public U this[U u] { getter { return u; } } // method 2
4016 If we see int Foo<int,int>::Item[int] we need to know if
4017 the indexer came from method 1 or from method 2, and we
4018 shouldn't conflate them. (Bugzilla 36283)
4020 if (prop1->get && prop2->get && !method_declaring_signatures_equal (prop1->get, prop2->get))
4023 if (prop1->set && prop2->set && !method_declaring_signatures_equal (prop1->set, prop2->set))
4030 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
4035 return method_nonpublic (accessor, start_klass);
4038 ICALL_EXPORT MonoArray*
4039 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
4043 MonoClass *startklass, *klass;
4049 gchar *propname = NULL;
4050 int (*compare_func) (const char *s1, const char *s2) = NULL;
4052 GHashTable *properties = NULL;
4053 MonoPtrArray tmp_array;
4055 mono_error_init (&error);
4057 mono_ptr_array_init (tmp_array, 8, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection properties list"); /*This the average for ASP.NET types*/
4059 domain = ((MonoObject *)type)->vtable->domain;
4060 if (type->type->byref)
4061 return mono_array_new_cached (domain, mono_class_get_property_info_class (), 0);
4062 klass = startklass = mono_class_from_mono_type (type->type);
4065 propname = mono_string_to_utf8 (name);
4066 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
4069 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4071 mono_class_setup_methods (klass);
4072 mono_class_setup_vtable (klass);
4073 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4077 while ((prop = mono_class_get_properties (klass, &iter))) {
4083 flags = method->flags;
4086 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4087 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4088 if (bflags & BFLAGS_Public)
4090 } else if (bflags & BFLAGS_NonPublic) {
4091 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4092 property_accessor_nonpublic(prop->set, startklass == klass)) {
4099 if (flags & METHOD_ATTRIBUTE_STATIC) {
4100 if (bflags & BFLAGS_Static)
4101 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4104 if (bflags & BFLAGS_Instance)
4113 if (compare_func (propname, prop->name))
4117 if (g_hash_table_lookup (properties, prop))
4120 MonoReflectionProperty *pr = mono_property_get_object_checked (domain, startklass, prop, &error);
4123 mono_ptr_array_append (tmp_array, pr);
4125 g_hash_table_insert (properties, prop, prop);
4127 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4130 g_hash_table_destroy (properties);
4133 res = mono_array_new_cached (domain, mono_class_get_property_info_class (), mono_ptr_array_size (tmp_array));
4134 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4135 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4137 mono_ptr_array_destroy (tmp_array);
4144 if (mono_class_has_failure (klass)) {
4145 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4147 mono_error_set_from_loader_error (&error);
4148 mono_loader_clear_error ();
4153 g_hash_table_destroy (properties);
4156 mono_ptr_array_destroy (tmp_array);
4158 mono_error_set_pending_exception (&error);
4164 event_hash (gconstpointer data)
4166 MonoEvent *event = (MonoEvent*)data;
4168 return g_str_hash (event->name);
4172 event_equal (MonoEvent *event1, MonoEvent *event2)
4174 // Events are hide-by-name
4175 return g_str_equal (event1->name, event2->name);
4178 ICALL_EXPORT MonoArray*
4179 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoReflectionType *reftype)
4183 MonoClass *startklass, *klass;
4189 char *utf8_name = NULL;
4190 int (*compare_func) (const char *s1, const char *s2) = NULL;
4191 GHashTable *events = NULL;
4192 MonoPtrArray tmp_array;
4194 mono_error_init (&error);
4196 mono_ptr_array_init (tmp_array, 4, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection events list");
4198 domain = mono_object_domain (type);
4199 if (type->type->byref)
4200 return mono_array_new_cached (domain, mono_class_get_event_info_class (), 0);
4201 klass = startklass = mono_class_from_mono_type (type->type);
4203 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
4205 mono_class_setup_methods (klass);
4206 mono_class_setup_vtable (klass);
4207 if (mono_class_has_failure (klass) || mono_loader_get_last_error ())
4211 while ((event = mono_class_get_events (klass, &iter))) {
4213 method = event->add;
4215 method = event->remove;
4217 method = event->raise;
4219 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4220 if (bflags & BFLAGS_Public)
4222 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4223 if (bflags & BFLAGS_NonPublic)
4228 if (bflags & BFLAGS_NonPublic)
4234 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4235 if (bflags & BFLAGS_Static)
4236 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4239 if (bflags & BFLAGS_Instance)
4244 if (bflags & BFLAGS_Instance)
4250 if (utf8_name == NULL) {
4251 utf8_name = mono_string_to_utf8 (name);
4252 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
4255 if (compare_func (event->name, utf8_name))
4259 if (g_hash_table_lookup (events, event))
4262 MonoReflectionEvent *ev_obj;
4263 ev_obj = mono_event_get_object_checked (domain, startklass, event, &error);
4266 mono_ptr_array_append (tmp_array, ev_obj);
4268 g_hash_table_insert (events, event, event);
4270 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4273 g_hash_table_destroy (events);
4275 res = mono_array_new_cached (domain, mono_class_get_event_info_class (), mono_ptr_array_size (tmp_array));
4277 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4278 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4280 mono_ptr_array_destroy (tmp_array);
4282 if (utf8_name != NULL)
4288 if (mono_class_has_failure (klass)) {
4289 mono_error_set_exception_instance (&error, mono_class_get_exception_for_failure (klass));
4291 mono_error_set_from_loader_error (&error);
4292 mono_loader_clear_error ();
4298 g_hash_table_destroy (events);
4299 if (utf8_name != NULL)
4302 mono_ptr_array_destroy (tmp_array);
4304 mono_error_set_pending_exception (&error);
4308 ICALL_EXPORT MonoArray*
4309 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, MonoString *name, guint32 bflags)
4312 MonoReflectionType *rt;
4320 MonoPtrArray tmp_array;
4322 domain = ((MonoObject *)type)->vtable->domain;
4323 if (type->type->byref)
4324 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4325 klass = mono_class_from_mono_type (type->type);
4328 * If a nested type is generic, return its generic type definition.
4329 * Note that this means that the return value is essentially the set
4330 * of nested types of the generic type definition of @klass.
4332 * A note in MSDN claims that a generic type definition can have
4333 * nested types that aren't generic. In any case, the container of that
4334 * nested type would be the generic type definition.
4336 if (klass->generic_class)
4337 klass = klass->generic_class->container_class;
4339 mono_ptr_array_init (tmp_array, 1, MONO_ROOT_SOURCE_REFLECTION, "temporary reflection nested types list");
4341 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4343 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4344 if (bflags & BFLAGS_Public)
4347 if (bflags & BFLAGS_NonPublic)
4355 str = mono_string_to_utf8 (name);
4356 mono_identifier_unescape_type_name_chars (str);
4359 if (strcmp (nested->name, str))
4363 rt = mono_type_get_object_checked (domain, &nested->byval_arg, &error);
4364 mono_error_raise_exception (&error);
4366 mono_ptr_array_append (tmp_array, (MonoObject*) rt);
4369 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4371 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4372 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4374 mono_ptr_array_destroy (tmp_array);
4381 ICALL_EXPORT MonoReflectionType*
4382 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4385 MonoReflectionType *ret;
4387 MonoType *type = NULL;
4388 MonoTypeNameParse info;
4389 gboolean type_resolve;
4391 /* On MS.NET, this does not fire a TypeResolve event */
4392 type_resolve = TRUE;
4393 str = mono_string_to_utf8 (name);
4394 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4395 if (!mono_reflection_parse_type (str, &info)) {
4397 mono_reflection_free_type_info (&info);
4399 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4402 /*g_print ("failed parse\n");*/
4406 if (info.assembly.name) {
4408 mono_reflection_free_type_info (&info);
4410 /* 1.0 and 2.0 throw different exceptions */
4411 if (mono_defaults.generic_ilist_class)
4412 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4414 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4420 if (module != NULL) {
4421 if (module->image) {
4422 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4423 if (!is_ok (&error)) {
4425 mono_reflection_free_type_info (&info);
4426 mono_error_set_pending_exception (&error);
4433 if (assembly_is_dynamic (assembly->assembly)) {
4434 /* Enumerate all modules */
4435 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4439 if (abuilder->modules) {
4440 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4441 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4442 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4443 if (!is_ok (&error)) {
4445 mono_reflection_free_type_info (&info);
4446 mono_error_set_pending_exception (&error);
4454 if (!type && abuilder->loaded_modules) {
4455 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4456 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4457 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4458 if (!is_ok (&error)) {
4460 mono_reflection_free_type_info (&info);
4461 mono_error_set_pending_exception (&error);
4470 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4471 if (!is_ok (&error)) {
4473 mono_reflection_free_type_info (&info);
4474 mono_error_set_pending_exception (&error);
4479 mono_reflection_free_type_info (&info);
4481 MonoException *e = NULL;
4484 e = mono_get_exception_type_load (name, NULL);
4486 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4487 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4489 mono_loader_clear_error ();
4492 mono_set_pending_exception (e);
4494 } else if (mono_loader_get_last_error ()) {
4496 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4499 mono_loader_clear_error ();
4502 if (type->type == MONO_TYPE_CLASS) {
4503 MonoClass *klass = mono_type_get_class (type);
4505 /* need to report exceptions ? */
4506 if (throwOnError && mono_class_has_failure (klass)) {
4507 /* report SecurityException (or others) that occured when loading the assembly */
4508 MonoException *exc = mono_class_get_exception_for_failure (klass);
4509 mono_loader_clear_error ();
4510 mono_set_pending_exception (exc);
4515 /* g_print ("got it\n"); */
4516 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4517 mono_error_set_pending_exception (&error);
4523 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4526 gchar *shadow_ini_file;
4529 /* Check for shadow-copied assembly */
4530 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4531 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4533 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4534 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4540 g_free (shadow_ini_file);
4541 if (content != NULL) {
4544 *filename = content;
4551 ICALL_EXPORT MonoString *
4552 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4554 MonoDomain *domain = mono_object_domain (assembly);
4555 MonoAssembly *mass = assembly->assembly;
4556 MonoString *res = NULL;
4561 if (g_path_is_absolute (mass->image->name)) {
4562 absolute = g_strdup (mass->image->name);
4563 dirname = g_path_get_dirname (absolute);
4565 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4566 dirname = g_strdup (mass->basedir);
4569 replace_shadow_path (domain, dirname, &absolute);
4574 for (i = strlen (absolute) - 1; i >= 0; i--)
4575 if (absolute [i] == '\\')
4580 uri = g_filename_to_uri (absolute, NULL, NULL);
4582 const char *prepend = "file://";
4584 if (*absolute == '/' && *(absolute + 1) == '/') {
4587 prepend = "file:///";
4590 uri = g_strconcat (prepend, absolute, NULL);
4594 res = mono_string_new (domain, uri);
4601 ICALL_EXPORT MonoBoolean
4602 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4604 MonoAssembly *mass = assembly->assembly;
4606 return mass->in_gac;
4609 ICALL_EXPORT MonoReflectionAssembly*
4610 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4615 MonoImageOpenStatus status;
4616 MonoReflectionAssembly* result = NULL;
4618 name = mono_string_to_utf8 (mname);
4619 res = mono_assembly_load_with_partial_name (name, &status);
4625 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4627 mono_error_set_pending_exception (&error);
4631 ICALL_EXPORT MonoString *
4632 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4634 MonoDomain *domain = mono_object_domain (assembly);
4637 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4642 ICALL_EXPORT MonoBoolean
4643 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4645 return assembly->assembly->ref_only;
4648 ICALL_EXPORT MonoString *
4649 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4651 MonoDomain *domain = mono_object_domain (assembly);
4653 return mono_string_new (domain, assembly->assembly->image->version);
4656 ICALL_EXPORT MonoReflectionMethod*
4657 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4660 MonoReflectionMethod *res = NULL;
4663 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4667 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4668 if (!mono_error_ok (&error))
4671 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4674 if (!mono_error_ok (&error))
4675 mono_error_set_pending_exception (&error);
4679 ICALL_EXPORT MonoReflectionModule*
4680 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4683 MonoReflectionModule *result = NULL;
4684 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4685 if (!mono_error_ok (&error))
4686 mono_error_set_pending_exception (&error);
4690 ICALL_EXPORT MonoArray*
4691 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4693 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4694 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4698 for (i = 0; i < table->rows; ++i) {
4699 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4700 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4706 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4708 static MonoMethod *create_version = NULL;
4712 mono_error_init (error);
4715 if (!create_version) {
4716 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4717 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4718 g_assert (create_version);
4719 mono_method_desc_free (desc);
4725 args [3] = &revision;
4726 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4727 return_val_if_nok (error, NULL);
4729 mono_runtime_invoke_checked (create_version, result, args, error);
4730 return_val_if_nok (error, NULL);
4735 ICALL_EXPORT MonoArray*
4736 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4740 MonoDomain *domain = mono_object_domain (assembly);
4742 static MonoMethod *create_culture = NULL;
4743 MonoImage *image = assembly->assembly->image;
4747 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4750 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4752 if (count > 0 && !create_culture) {
4753 MonoMethodDesc *desc = mono_method_desc_new (
4754 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4755 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4756 g_assert (create_culture);
4757 mono_method_desc_free (desc);
4760 for (i = 0; i < count; i++) {
4761 MonoObject *version;
4762 MonoReflectionAssemblyName *aname;
4763 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4765 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4767 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4768 domain, mono_class_get_assembly_name_class (), &error);
4769 mono_error_raise_exception (&error);
4771 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4773 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4774 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4775 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4776 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4777 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4778 aname->versioncompat = 1; /* SameMachine (default) */
4779 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4781 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4782 mono_error_raise_exception (&error);
4784 MONO_OBJECT_SETREF (aname, version, version);
4786 if (create_culture) {
4788 MonoBoolean assembly_ref = 1;
4789 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4790 args [1] = &assembly_ref;
4792 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4793 mono_error_raise_exception (&error);
4795 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4798 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4799 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4800 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4802 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4803 /* public key token isn't copied - the class library will
4804 automatically generate it from the public key if required */
4805 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4806 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4808 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4809 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4812 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4815 /* note: this function doesn't return the codebase on purpose (i.e. it can
4816 be used under partial trust as path information isn't present). */
4818 mono_array_setref (result, i, aname);
4823 /* move this in some file in mono/util/ */
4825 g_concat_dir_and_file (const char *dir, const char *file)
4827 g_return_val_if_fail (dir != NULL, NULL);
4828 g_return_val_if_fail (file != NULL, NULL);
4831 * If the directory name doesn't have a / on the end, we need
4832 * to add one so we get a proper path to the file
4834 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4835 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4837 return g_strconcat (dir, file, NULL);
4841 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4844 char *n = mono_string_to_utf8 (name);
4845 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4847 guint32 cols [MONO_MANIFEST_SIZE];
4848 guint32 impl, file_idx;
4852 for (i = 0; i < table->rows; ++i) {
4853 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4854 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4855 if (strcmp (val, n) == 0)
4859 if (i == table->rows)
4862 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4865 * this code should only be called after obtaining the
4866 * ResourceInfo and handling the other cases.
4868 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4869 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4871 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4876 module = assembly->assembly->image;
4879 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4880 mono_error_raise_exception (&error);
4881 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4883 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4886 ICALL_EXPORT gboolean
4887 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4890 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4892 guint32 cols [MONO_MANIFEST_SIZE];
4893 guint32 file_cols [MONO_FILE_SIZE];
4897 n = mono_string_to_utf8 (name);
4898 for (i = 0; i < table->rows; ++i) {
4899 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4900 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4901 if (strcmp (val, n) == 0)
4905 if (i == table->rows)
4908 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4909 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4912 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4913 case MONO_IMPLEMENTATION_FILE:
4914 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4915 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4916 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4917 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4918 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4919 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4922 info->location = RESOURCE_LOCATION_EMBEDDED;
4925 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4926 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4927 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4928 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4929 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4930 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4932 mono_set_pending_exception (ex);
4935 MonoReflectionAssembly *assm_obj;
4936 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4938 mono_error_set_pending_exception (&error);
4941 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4943 /* Obtain info recursively */
4944 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4945 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4948 case MONO_IMPLEMENTATION_EXP_TYPE:
4949 g_assert_not_reached ();
4957 ICALL_EXPORT MonoObject*
4958 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4960 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4961 MonoArray *result = NULL;
4966 /* check hash if needed */
4968 n = mono_string_to_utf8 (name);
4969 for (i = 0; i < table->rows; ++i) {
4970 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4971 if (strcmp (val, n) == 0) {
4974 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4975 fn = mono_string_new (mono_object_domain (assembly), n);
4977 return (MonoObject*)fn;
4985 for (i = 0; i < table->rows; ++i) {
4986 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4990 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4993 for (i = 0; i < table->rows; ++i) {
4994 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4995 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4996 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4997 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5002 return (MonoObject*)result;
5005 ICALL_EXPORT MonoArray*
5006 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5009 MonoDomain *domain = mono_domain_get();
5012 int i, j, file_count = 0;
5013 MonoImage **modules;
5014 guint32 module_count, real_module_count;
5015 MonoTableInfo *table;
5016 guint32 cols [MONO_FILE_SIZE];
5017 MonoImage *image = assembly->assembly->image;
5019 g_assert (image != NULL);
5020 g_assert (!assembly_is_dynamic (assembly->assembly));
5022 table = &image->tables [MONO_TABLE_FILE];
5023 file_count = table->rows;
5025 modules = image->modules;
5026 module_count = image->module_count;
5028 real_module_count = 0;
5029 for (i = 0; i < module_count; ++i)
5031 real_module_count ++;
5033 klass = mono_class_get_module_class ();
5034 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5036 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5037 mono_error_raise_exception (&error);
5038 mono_array_setref (res, 0, image_obj);
5040 for (i = 0; i < module_count; ++i)
5042 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5043 mono_error_raise_exception (&error);
5044 mono_array_setref (res, j, rm);
5048 for (i = 0; i < file_count; ++i, ++j) {
5049 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5050 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5051 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5052 mono_error_raise_exception (&error);
5053 mono_array_setref (res, j, rm);
5056 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5058 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5059 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5062 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5063 mono_error_raise_exception (&error);
5064 mono_array_setref (res, j, rm);
5071 ICALL_EXPORT MonoReflectionMethod*
5072 ves_icall_GetCurrentMethod (void)
5074 MonoReflectionMethod *res = NULL;
5077 MonoMethod *m = mono_method_get_last_managed ();
5080 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5084 while (m->is_inflated)
5085 m = ((MonoMethodInflated*)m)->declaring;
5087 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5088 mono_error_raise_exception (&error);
5094 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5097 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5100 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5101 //method is inflated, we should inflate it on the other class
5102 MonoGenericContext ctx;
5103 ctx.method_inst = inflated->context.method_inst;
5104 ctx.class_inst = inflated->context.class_inst;
5105 if (klass->generic_class)
5106 ctx.class_inst = klass->generic_class->context.class_inst;
5107 else if (klass->generic_container)
5108 ctx.class_inst = klass->generic_container->context.class_inst;
5109 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5110 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5114 mono_class_setup_methods (method->klass);
5115 if (mono_class_has_failure (method->klass))
5117 for (i = 0; i < method->klass->method.count; ++i) {
5118 if (method->klass->methods [i] == method) {
5123 mono_class_setup_methods (klass);
5124 if (mono_class_has_failure (klass))
5126 g_assert (offset >= 0 && offset < klass->method.count);
5127 return klass->methods [offset];
5130 ICALL_EXPORT MonoReflectionMethod*
5131 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5133 MonoReflectionMethod *res = NULL;
5137 klass = mono_class_from_mono_type (type);
5138 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5140 if (method->klass != klass) {
5141 method = mono_method_get_equivalent_method (method, klass);
5146 klass = method->klass;
5147 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5148 mono_error_raise_exception (&error);
5152 ICALL_EXPORT MonoReflectionMethodBody*
5153 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5156 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5157 mono_error_set_pending_exception (&error);
5161 ICALL_EXPORT MonoReflectionAssembly*
5162 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5165 MonoReflectionAssembly *result;
5166 MonoMethod *dest = NULL;
5168 mono_stack_walk_no_il (get_executing, &dest);
5170 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5172 mono_error_set_pending_exception (&error);
5177 ICALL_EXPORT MonoReflectionAssembly*
5178 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5181 MonoReflectionAssembly *result;
5182 MonoDomain* domain = mono_domain_get ();
5184 if (!domain->entry_assembly)
5187 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5189 mono_error_set_pending_exception (&error);
5193 ICALL_EXPORT MonoReflectionAssembly*
5194 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5199 MonoReflectionAssembly *result;
5202 mono_stack_walk_no_il (get_executing, &dest);
5204 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5208 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5211 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5213 mono_error_set_pending_exception (&error);
5217 ICALL_EXPORT MonoString *
5218 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5219 gboolean assembly_qualified)
5221 MonoDomain *domain = mono_object_domain (object);
5222 MonoTypeNameFormat format;
5227 format = assembly_qualified ?
5228 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5229 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5231 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5233 name = mono_type_get_name_full (object->type, format);
5237 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5242 res = mono_string_new (domain, name);
5249 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5252 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5254 mono_class_init_checked (klass, &error);
5255 mono_error_raise_exception (&error);
5256 return mono_security_core_clr_class_level (klass);
5260 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5262 MonoClassField *field = rfield->field;
5263 return mono_security_core_clr_field_level (field, TRUE);
5267 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5269 MonoMethod *method = rfield->method;
5270 return mono_security_core_clr_method_level (method, TRUE);
5274 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token, MonoError *error)
5276 static MonoMethod *create_culture = NULL;
5280 const char *pkey_ptr;
5282 MonoBoolean assembly_ref = 0;
5284 mono_error_init (error);
5286 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5287 aname->major = name->major;
5288 aname->minor = name->minor;
5289 aname->build = name->build;
5290 aname->flags = name->flags;
5291 aname->revision = name->revision;
5292 aname->hashalg = name->hash_alg;
5293 aname->versioncompat = 1; /* SameMachine (default) */
5294 aname->processor_architecture = name->arch;
5296 if (by_default_version) {
5297 MonoObject *version;
5299 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5300 return_if_nok (error);
5302 MONO_OBJECT_SETREF (aname, version, version);
5306 if (absolute != NULL && *absolute != '\0') {
5307 const gchar *prepend = "file://";
5310 codebase = g_strdup (absolute);
5315 for (i = strlen (codebase) - 1; i >= 0; i--)
5316 if (codebase [i] == '\\')
5319 if (*codebase == '/' && *(codebase + 1) == '/') {
5322 prepend = "file:///";
5326 result = g_strconcat (prepend, codebase, NULL);
5332 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5336 if (!create_culture) {
5337 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5338 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5339 g_assert (create_culture);
5340 mono_method_desc_free (desc);
5343 if (name->culture) {
5344 args [0] = mono_string_new (domain, name->culture);
5345 args [1] = &assembly_ref;
5347 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5348 return_if_nok (error);
5350 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5353 if (name->public_key) {
5354 pkey_ptr = (char*)name->public_key;
5355 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5357 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5358 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5359 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5360 } else if (default_publickey) {
5361 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5362 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5365 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5366 if (name->public_key_token [0]) {
5370 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5371 p = mono_array_addr (aname->keyToken, char, 0);
5373 for (i = 0, j = 0; i < 8; i++) {
5374 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5375 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5378 } else if (default_token) {
5379 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5383 ICALL_EXPORT MonoString *
5384 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5386 MonoDomain *domain = mono_object_domain (assembly);
5387 MonoAssembly *mass = assembly->assembly;
5391 name = mono_stringify_assembly_name (&mass->aname);
5392 res = mono_string_new (domain, name);
5399 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5403 MonoAssembly *mass = assembly->assembly;
5405 if (g_path_is_absolute (mass->image->name)) {
5406 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5407 mono_error_set_pending_exception (&error);
5410 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5412 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5413 mono_error_set_pending_exception (&error);
5419 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5423 MonoImageOpenStatus status = MONO_IMAGE_OK;
5426 MonoAssemblyName name;
5429 filename = mono_string_to_utf8 (fname);
5431 dirname = g_path_get_dirname (filename);
5432 replace_shadow_path (mono_domain_get (), dirname, &filename);
5435 image = mono_image_open (filename, &status);
5441 if (status == MONO_IMAGE_IMAGE_INVALID)
5442 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5444 exc = mono_get_exception_file_not_found2 (NULL, fname);
5445 mono_set_pending_exception (exc);
5449 res = mono_assembly_fill_assembly_name (image, &name);
5451 mono_image_close (image);
5453 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5457 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5458 mono_error_set_pending_exception (&error);
5460 mono_image_close (image);
5464 ICALL_EXPORT MonoBoolean
5465 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5466 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5468 MonoBoolean result = FALSE;
5469 MonoDeclSecurityEntry entry;
5471 /* SecurityAction.RequestMinimum */
5472 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5473 *minimum = entry.blob;
5474 *minLength = entry.size;
5477 /* SecurityAction.RequestOptional */
5478 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5479 *optional = entry.blob;
5480 *optLength = entry.size;
5483 /* SecurityAction.RequestRefuse */
5484 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5485 *refused = entry.blob;
5486 *refLength = entry.size;
5494 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5496 guint32 attrs, visibility;
5498 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5499 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5500 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5503 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5509 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5511 MonoReflectionType *rt;
5514 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5517 mono_error_init (error);
5519 /* we start the count from 1 because we skip the special type <Module> */
5522 for (i = 1; i < tdef->rows; ++i) {
5523 if (mono_module_type_is_visible (tdef, image, i + 1))
5527 count = tdef->rows - 1;
5529 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5530 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5532 for (i = 1; i < tdef->rows; ++i) {
5533 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5534 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5535 mono_loader_assert_no_error (); /* Plug any leaks */
5538 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5539 return_val_if_nok (error, NULL);
5541 mono_array_setref (res, count, rt);
5543 MonoException *ex = mono_error_convert_to_exception (error);
5544 mono_array_setref (*exceptions, count, ex);
5553 ICALL_EXPORT MonoArray*
5554 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5557 MonoArray *res = NULL;
5558 MonoArray *exceptions = NULL;
5559 MonoImage *image = NULL;
5560 MonoTableInfo *table = NULL;
5563 int i, len, ex_count;
5565 domain = mono_object_domain (assembly);
5567 g_assert (!assembly_is_dynamic (assembly->assembly));
5568 image = assembly->assembly->image;
5569 table = &image->tables [MONO_TABLE_FILE];
5570 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5571 mono_error_raise_exception (&error);
5573 /* Append data from all modules in the assembly */
5574 for (i = 0; i < table->rows; ++i) {
5575 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5576 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5581 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5582 mono_error_raise_exception (&error);
5584 /* Append the new types to the end of the array */
5585 if (mono_array_length (res2) > 0) {
5587 MonoArray *res3, *ex3;
5589 len1 = mono_array_length (res);
5590 len2 = mono_array_length (res2);
5592 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5593 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5594 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5597 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5598 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5599 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5606 /* the ReflectionTypeLoadException must have all the types (Types property),
5607 * NULL replacing types which throws an exception. The LoaderException must
5608 * contain all exceptions for NULL items.
5611 len = mono_array_length (res);
5614 for (i = 0; i < len; i++) {
5615 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5619 klass = mono_type_get_class (t->type);
5620 if ((klass != NULL) && mono_class_has_failure (klass)) {
5621 /* keep the class in the list */
5622 list = g_list_append (list, klass);
5623 /* and replace Type with NULL */
5624 mono_array_setref (res, i, NULL);
5631 if (list || ex_count) {
5633 MonoException *exc = NULL;
5634 MonoArray *exl = NULL;
5635 int j, length = g_list_length (list) + ex_count;
5637 mono_loader_clear_error ();
5639 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5640 /* Types for which mono_class_get_checked () succeeded */
5641 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5642 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5643 mono_array_setref (exl, i, exc);
5645 /* Types for which it don't */
5646 for (j = 0; j < mono_array_length (exceptions); ++j) {
5647 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5649 g_assert (i < length);
5650 mono_array_setref (exl, i, exc);
5657 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5658 if (!is_ok (&error)) {
5659 mono_error_set_pending_exception (&error);
5662 mono_loader_clear_error ();
5663 mono_set_pending_exception (exc);
5670 ICALL_EXPORT gboolean
5671 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5674 MonoAssemblyName aname;
5675 MonoDomain *domain = mono_object_domain (name);
5677 gboolean is_version_defined;
5678 gboolean is_token_defined;
5680 aname.public_key = NULL;
5681 val = mono_string_to_utf8 (assname);
5682 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5683 g_free ((guint8*) aname.public_key);
5688 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5689 mono_error_set_pending_exception (&error);
5691 mono_assembly_name_free (&aname);
5692 g_free ((guint8*) aname.public_key);
5698 ICALL_EXPORT MonoReflectionType*
5699 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5702 MonoReflectionType *ret;
5703 MonoDomain *domain = mono_object_domain (module);
5706 g_assert (module->image);
5708 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5709 /* These images do not have a global type */
5712 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5713 if (!mono_error_ok (&error)) {
5714 mono_error_set_pending_exception (&error);
5718 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5719 if (!mono_error_ok (&error)) {
5720 mono_error_set_pending_exception (&error);
5728 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5730 /*if (module->image)
5731 mono_image_close (module->image);*/
5734 ICALL_EXPORT MonoString*
5735 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5737 MonoDomain *domain = mono_object_domain (module);
5739 g_assert (module->image);
5740 return mono_string_new (domain, module->image->guid);
5743 ICALL_EXPORT gpointer
5744 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5747 if (module->image && module->image->is_module_handle)
5748 return module->image->raw_data;
5751 return (gpointer) (-1);
5755 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5757 if (image_is_dynamic (image)) {
5758 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5759 *pe_kind = dyn->pe_kind;
5760 *machine = dyn->machine;
5763 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5764 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5769 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5771 return (image->md_version_major << 16) | (image->md_version_minor);
5774 ICALL_EXPORT MonoArray*
5775 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5778 MonoArray *exceptions;
5782 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5786 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5787 mono_error_raise_exception (&error);
5789 for (i = 0; i < mono_array_length (exceptions); ++i) {
5790 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5792 mono_set_pending_exception (ex);
5801 mono_memberref_is_method (MonoImage *image, guint32 token)
5803 if (!image_is_dynamic (image)) {
5804 guint32 cols [MONO_MEMBERREF_SIZE];
5806 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5807 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5808 mono_metadata_decode_blob_size (sig, &sig);
5809 return (*sig != 0x6);
5811 MonoClass *handle_class;
5813 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5816 return mono_defaults.methodhandle_class == handle_class;
5821 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5824 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5825 mono_array_addr (type_args, MonoType*, 0));
5827 context->class_inst = NULL;
5829 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5830 mono_array_addr (method_args, MonoType*, 0));
5832 context->method_inst = NULL;
5835 ICALL_EXPORT MonoType*
5836 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5839 int table = mono_metadata_token_table (token);
5840 int index = mono_metadata_token_index (token);
5841 MonoGenericContext context;
5844 *resolve_error = ResolveTokenError_Other;
5846 /* Validate token */
5847 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5848 (table != MONO_TABLE_TYPESPEC)) {
5849 *resolve_error = ResolveTokenError_BadTable;
5853 if (image_is_dynamic (image)) {
5854 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5855 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5856 return klass ? &klass->byval_arg : NULL;
5859 init_generic_context_from_args (&context, type_args, method_args);
5860 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5861 return klass ? &klass->byval_arg : NULL;
5864 if ((index <= 0) || (index > image->tables [table].rows)) {
5865 *resolve_error = ResolveTokenError_OutOfRange;
5869 init_generic_context_from_args (&context, type_args, method_args);
5870 klass = mono_class_get_checked (image, token, &error);
5872 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5873 if (!mono_error_ok (&error)) {
5874 mono_error_set_pending_exception (&error);
5879 return &klass->byval_arg;
5884 ICALL_EXPORT MonoMethod*
5885 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5888 int table = mono_metadata_token_table (token);
5889 int index = mono_metadata_token_index (token);
5890 MonoGenericContext context;
5893 *resolve_error = ResolveTokenError_Other;
5895 /* Validate token */
5896 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5897 (table != MONO_TABLE_MEMBERREF)) {
5898 *resolve_error = ResolveTokenError_BadTable;
5902 if (image_is_dynamic (image)) {
5903 if (table == MONO_TABLE_METHOD)
5904 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5906 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5907 *resolve_error = ResolveTokenError_BadTable;
5911 init_generic_context_from_args (&context, type_args, method_args);
5912 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5915 if ((index <= 0) || (index > image->tables [table].rows)) {
5916 *resolve_error = ResolveTokenError_OutOfRange;
5919 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5920 *resolve_error = ResolveTokenError_BadTable;
5924 init_generic_context_from_args (&context, type_args, method_args);
5925 method = mono_get_method_checked (image, token, NULL, &context, &error);
5926 mono_error_set_pending_exception (&error);
5931 ICALL_EXPORT MonoString*
5932 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5934 int index = mono_metadata_token_index (token);
5936 *error = ResolveTokenError_Other;
5938 /* Validate token */
5939 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5940 *error = ResolveTokenError_BadTable;
5944 if (image_is_dynamic (image))
5945 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5947 if ((index <= 0) || (index >= image->heap_us.size)) {
5948 *error = ResolveTokenError_OutOfRange;
5952 /* FIXME: What to do if the index points into the middle of a string ? */
5954 return mono_ldstr (mono_domain_get (), image, index);
5957 ICALL_EXPORT MonoClassField*
5958 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5962 int table = mono_metadata_token_table (token);
5963 int index = mono_metadata_token_index (token);
5964 MonoGenericContext context;
5965 MonoClassField *field;
5967 *resolve_error = ResolveTokenError_Other;
5969 /* Validate token */
5970 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5971 *resolve_error = ResolveTokenError_BadTable;
5975 if (image_is_dynamic (image)) {
5976 if (table == MONO_TABLE_FIELD)
5977 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5979 if (mono_memberref_is_method (image, token)) {
5980 *resolve_error = ResolveTokenError_BadTable;
5984 init_generic_context_from_args (&context, type_args, method_args);
5985 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5988 if ((index <= 0) || (index > image->tables [table].rows)) {
5989 *resolve_error = ResolveTokenError_OutOfRange;
5992 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5993 *resolve_error = ResolveTokenError_BadTable;
5997 init_generic_context_from_args (&context, type_args, method_args);
5998 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5999 mono_error_set_pending_exception (&error);
6005 ICALL_EXPORT MonoObject*
6006 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6010 int table = mono_metadata_token_table (token);
6012 *error = ResolveTokenError_Other;
6015 case MONO_TABLE_TYPEDEF:
6016 case MONO_TABLE_TYPEREF:
6017 case MONO_TABLE_TYPESPEC: {
6018 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6020 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6021 mono_error_raise_exception (&merror);
6028 case MONO_TABLE_METHOD:
6029 case MONO_TABLE_METHODSPEC: {
6030 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6032 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6033 mono_error_raise_exception (&merror);
6039 case MONO_TABLE_FIELD: {
6040 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6042 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6043 mono_error_raise_exception (&merror);
6049 case MONO_TABLE_MEMBERREF:
6050 if (mono_memberref_is_method (image, token)) {
6051 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6053 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6054 mono_error_raise_exception (&merror);
6061 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6063 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6064 mono_error_raise_exception (&merror);
6073 *error = ResolveTokenError_BadTable;
6079 ICALL_EXPORT MonoArray*
6080 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6082 int table = mono_metadata_token_table (token);
6083 int idx = mono_metadata_token_index (token);
6084 MonoTableInfo *tables = image->tables;
6089 *error = ResolveTokenError_OutOfRange;
6091 /* FIXME: Support other tables ? */
6092 if (table != MONO_TABLE_STANDALONESIG)
6095 if (image_is_dynamic (image))
6098 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6101 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6103 ptr = mono_metadata_blob_heap (image, sig);
6104 len = mono_metadata_decode_blob_size (ptr, &ptr);
6106 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6107 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6111 ICALL_EXPORT MonoReflectionType*
6112 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6115 MonoReflectionType *ret;
6117 int isbyref = 0, rank;
6118 char *str = mono_string_to_utf8 (smodifiers);
6121 klass = mono_class_from_mono_type (tb->type.type);
6123 /* logic taken from mono_reflection_parse_type(): keep in sync */
6127 if (isbyref) { /* only one level allowed by the spec */
6136 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6137 mono_error_raise_exception (&error);
6141 klass = mono_ptr_class_get (&klass->byval_arg);
6142 mono_class_init (klass);
6153 else if (*p != '*') { /* '*' means unknown lower bound */
6164 klass = mono_array_class_get (klass, rank);
6165 mono_class_init (klass);
6174 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6175 mono_error_raise_exception (&error);
6180 ICALL_EXPORT MonoBoolean
6181 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6187 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6193 check_for_invalid_type (MonoClass *klass, MonoError *error)
6198 mono_error_init (error);
6200 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6203 name = mono_type_get_full_name (klass);
6204 str = mono_string_new (mono_domain_get (), name);
6206 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6209 ICALL_EXPORT MonoReflectionType *
6210 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6213 MonoReflectionType *ret;
6214 MonoClass *klass, *aklass;
6216 klass = mono_class_from_mono_type (type->type);
6217 check_for_invalid_type (klass, &error);
6218 mono_error_raise_exception (&error);
6220 if (rank == 0) //single dimentional array
6221 aklass = mono_array_class_get (klass, 1);
6223 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6225 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6226 mono_error_raise_exception (&error);
6231 ICALL_EXPORT MonoReflectionType *
6232 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6235 MonoReflectionType *ret;
6238 klass = mono_class_from_mono_type (type->type);
6239 mono_class_init_checked (klass, &error);
6240 mono_error_raise_exception (&error);
6241 check_for_invalid_type (klass, &error);
6242 mono_error_raise_exception (&error);
6244 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6245 mono_error_raise_exception (&error);
6250 ICALL_EXPORT MonoReflectionType *
6251 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6254 MonoReflectionType *ret;
6255 MonoClass *klass, *pklass;
6257 klass = mono_class_from_mono_type (type->type);
6258 mono_class_init_checked (klass, &error);
6259 mono_error_raise_exception (&error);
6260 check_for_invalid_type (klass, &error);
6261 mono_error_raise_exception (&error);
6263 pklass = mono_ptr_class_get (type->type);
6265 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6266 mono_error_raise_exception (&error);
6271 ICALL_EXPORT MonoObject *
6272 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6273 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6276 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6277 MonoObject *delegate;
6279 MonoMethod *method = info->method;
6281 mono_class_init_checked (delegate_class, &error);
6282 mono_error_raise_exception (&error);
6284 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6285 /* FIXME improve this exception message */
6286 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6288 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6289 mono_error_set_pending_exception (&error);
6293 if (mono_security_core_clr_enabled ()) {
6294 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6298 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6299 mono_error_raise_exception (&error);
6301 if (method_is_dynamic (method)) {
6302 /* Creating a trampoline would leak memory */
6303 func = mono_compile_method (method);
6305 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6306 method = mono_object_get_virtual_method (target, method);
6307 func = mono_create_ftnptr (mono_domain_get (),
6308 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6311 mono_delegate_ctor_with_method (delegate, target, func, method);
6316 ICALL_EXPORT MonoMulticastDelegate *
6317 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6320 MonoMulticastDelegate *ret;
6322 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6324 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6325 mono_error_raise_exception (&error);
6326 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6331 ICALL_EXPORT MonoReflectionMethod*
6332 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6334 MonoReflectionMethod *ret = NULL;
6336 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6337 mono_error_raise_exception (&error);
6343 static inline gint32
6344 mono_array_get_byte_length (MonoArray *array)
6350 klass = array->obj.vtable->klass;
6352 if (array->bounds == NULL)
6353 length = array->max_length;
6356 for (i = 0; i < klass->rank; ++ i)
6357 length *= array->bounds [i].length;
6360 switch (klass->element_class->byval_arg.type) {
6363 case MONO_TYPE_BOOLEAN:
6367 case MONO_TYPE_CHAR:
6375 return length * sizeof (gpointer);
6386 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6388 return mono_array_get_byte_length (array);
6392 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6394 return mono_array_get (array, gint8, idx);
6398 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6400 mono_array_set (array, gint8, idx, value);
6403 ICALL_EXPORT MonoBoolean
6404 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6406 guint8 *src_buf, *dest_buf;
6409 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6413 g_assert (count >= 0);
6415 /* This is called directly from the class libraries without going through the managed wrapper */
6416 MONO_CHECK_ARG_NULL (src, FALSE);
6417 MONO_CHECK_ARG_NULL (dest, FALSE);
6419 /* watch out for integer overflow */
6420 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6423 src_buf = (guint8 *)src->vector + src_offset;
6424 dest_buf = (guint8 *)dest->vector + dest_offset;
6427 memcpy (dest_buf, src_buf, count);
6429 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6434 #ifndef DISABLE_REMOTING
6435 ICALL_EXPORT MonoObject *
6436 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6439 MonoDomain *domain = mono_object_domain (this_obj);
6441 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6442 MonoTransparentProxy *tp;
6446 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6447 mono_error_raise_exception (&error);
6448 tp = (MonoTransparentProxy*) res;
6450 MONO_OBJECT_SETREF (tp, rp, rp);
6451 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6452 klass = mono_class_from_mono_type (type);
6454 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6455 mono_class_setup_vtable (klass);
6456 if (mono_class_has_failure (klass)) {
6457 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6461 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6462 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6463 if (!is_ok (&error)) {
6464 mono_error_set_pending_exception (&error);
6468 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6472 ICALL_EXPORT MonoReflectionType *
6473 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6476 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6477 mono_error_raise_exception (&error);
6483 /* System.Environment */
6486 ves_icall_System_Environment_get_UserName (void)
6488 /* using glib is more portable */
6489 return mono_string_new (mono_domain_get (), g_get_user_name ());
6493 ICALL_EXPORT MonoString *
6494 ves_icall_System_Environment_get_MachineName (void)
6496 #if defined (HOST_WIN32)
6501 len = MAX_COMPUTERNAME_LENGTH + 1;
6502 buf = g_new (gunichar2, len);
6505 if (GetComputerName (buf, (PDWORD) &len)) {
6507 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6508 mono_error_raise_exception (&error);
6513 #elif !defined(DISABLE_SOCKETS)
6517 #if defined _SC_HOST_NAME_MAX
6518 n = sysconf (_SC_HOST_NAME_MAX);
6522 buf = g_malloc (n+1);
6524 if (gethostname (buf, n) == 0){
6526 result = mono_string_new (mono_domain_get (), buf);
6533 return mono_string_new (mono_domain_get (), "mono");
6538 ves_icall_System_Environment_get_Platform (void)
6540 #if defined (TARGET_WIN32)
6543 #elif defined(__MACH__)
6546 // Notice that the value is hidden from user code, and only exposed
6547 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6548 // define and making assumptions based on Unix/128/4 values before there
6549 // was a MacOS define. Lots of code would assume that not-Unix meant
6550 // Windows, but in this case, it would be OSX.
6559 ICALL_EXPORT MonoString *
6560 ves_icall_System_Environment_get_NewLine (void)
6562 #if defined (HOST_WIN32)
6563 return mono_string_new (mono_domain_get (), "\r\n");
6565 return mono_string_new (mono_domain_get (), "\n");
6569 ICALL_EXPORT MonoBoolean
6570 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6572 #if SIZEOF_VOID_P == 8
6576 gboolean isWow64Process = FALSE;
6577 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6578 return (MonoBoolean)isWow64Process;
6580 #elif defined(HAVE_SYS_UTSNAME_H)
6581 struct utsname name;
6583 if (uname (&name) >= 0) {
6584 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6591 ICALL_EXPORT MonoString *
6592 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6600 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6601 value = g_getenv (utf8_name);
6608 return mono_string_new (mono_domain_get (), value);
6612 * There is no standard way to get at environ.
6615 #ifndef __MINGW32_VERSION
6616 #if defined(__APPLE__)
6617 #if defined (TARGET_OSX)
6618 /* Apple defines this in crt_externs.h but doesn't provide that header for
6619 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6620 * in fact exist on all implementations (so far)
6622 gchar ***_NSGetEnviron(void);
6623 #define environ (*_NSGetEnviron())
6625 static char *mono_environ[1] = { NULL };
6626 #define environ mono_environ
6627 #endif /* defined (TARGET_OSX) */
6635 ICALL_EXPORT MonoArray *
6636 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6647 env_strings = GetEnvironmentStrings();
6650 env_string = env_strings;
6651 while (*env_string != '\0') {
6652 /* weird case that MS seems to skip */
6653 if (*env_string != '=')
6655 while (*env_string != '\0')
6661 domain = mono_domain_get ();
6662 names = mono_array_new (domain, mono_defaults.string_class, n);
6666 env_string = env_strings;
6667 while (*env_string != '\0') {
6668 /* weird case that MS seems to skip */
6669 if (*env_string != '=') {
6670 equal_str = wcschr(env_string, '=');
6671 g_assert(equal_str);
6673 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6674 mono_error_raise_exception (&error);
6675 mono_array_setref (names, n, str);
6678 while (*env_string != '\0')
6683 FreeEnvironmentStrings (env_strings);
6696 for (e = environ; *e != 0; ++ e)
6699 domain = mono_domain_get ();
6700 names = mono_array_new (domain, mono_defaults.string_class, n);
6703 for (e = environ; *e != 0; ++ e) {
6704 parts = g_strsplit (*e, "=", 2);
6706 str = mono_string_new (domain, *parts);
6707 mono_array_setref (names, n, str);
6720 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6722 #if !GLIB_CHECK_VERSION(2,4,0)
6723 #define g_setenv(a,b,c) setenv(a,b,c)
6724 #define g_unsetenv(a) unsetenv(a)
6728 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6731 gunichar2 *utf16_name, *utf16_value;
6733 gchar *utf8_name, *utf8_value;
6738 utf16_name = mono_string_to_utf16 (name);
6739 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6740 SetEnvironmentVariable (utf16_name, NULL);
6741 g_free (utf16_name);
6745 utf16_value = mono_string_to_utf16 (value);
6747 SetEnvironmentVariable (utf16_name, utf16_value);
6749 g_free (utf16_name);
6750 g_free (utf16_value);
6752 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6754 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6755 g_unsetenv (utf8_name);
6760 utf8_value = mono_string_to_utf8_checked (value, &error);
6761 if (!mono_error_ok (&error)) {
6763 mono_error_set_pending_exception (&error);
6766 g_setenv (utf8_name, utf8_value, TRUE);
6769 g_free (utf8_value);
6774 ves_icall_System_Environment_Exit (int result)
6776 mono_environment_exitcode_set (result);
6778 /* FIXME: There are some cleanup hangs that should be worked out, but
6779 * if the program is going to exit, everything will be cleaned up when
6780 * NaCl exits anyway.
6782 #ifndef __native_client__
6783 if (!mono_runtime_try_shutdown ())
6784 mono_thread_exit ();
6786 /* Suspend all managed threads since the runtime is going away */
6787 mono_thread_suspend_all_other_threads ();
6789 mono_runtime_quit ();
6792 /* we may need to do some cleanup here... */
6796 ICALL_EXPORT MonoString*
6797 ves_icall_System_Environment_GetGacPath (void)
6799 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6802 ICALL_EXPORT MonoString*
6803 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6805 #if defined (HOST_WIN32)
6806 #ifndef CSIDL_FLAG_CREATE
6807 #define CSIDL_FLAG_CREATE 0x8000
6810 WCHAR path [MAX_PATH];
6811 /* Create directory if no existing */
6812 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6817 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6818 mono_error_raise_exception (&error);
6822 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6824 return mono_string_new (mono_domain_get (), "");
6827 ICALL_EXPORT MonoArray *
6828 ves_icall_System_Environment_GetLogicalDrives (void)
6831 gunichar2 buf [256], *ptr, *dname;
6833 guint initial_size = 127, size = 128;
6836 MonoString *drivestr;
6837 MonoDomain *domain = mono_domain_get ();
6843 while (size > initial_size) {
6844 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6845 if (size > initial_size) {
6848 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6849 initial_size = size;
6863 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6868 while (*u16) { u16++; len ++; }
6869 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6870 mono_error_raise_exception (&error);
6871 mono_array_setref (result, ndrives++, drivestr);
6881 ICALL_EXPORT MonoString *
6882 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6884 gunichar2 volume_name [MAX_PATH + 1];
6886 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6888 return mono_string_from_utf16 (volume_name);
6891 ICALL_EXPORT MonoString *
6892 ves_icall_System_Environment_InternalGetHome (void)
6894 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6897 static const char *encodings [] = {
6899 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6900 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6901 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6903 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6904 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6905 "x_unicode_2_0_utf_7",
6907 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6908 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6910 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6913 "unicodefffe", "utf_16be",
6920 * Returns the internal codepage, if the value of "int_code_page" is
6921 * 1 at entry, and we can not compute a suitable code page number,
6922 * returns the code page as a string
6924 ICALL_EXPORT MonoString*
6925 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6930 char *codepage = NULL;
6932 int want_name = *int_code_page;
6935 *int_code_page = -1;
6937 g_get_charset (&cset);
6938 c = codepage = strdup (cset);
6939 for (c = codepage; *c; c++){
6940 if (isascii (*c) && isalpha (*c))
6945 /* g_print ("charset: %s\n", cset); */
6947 /* handle some common aliases */
6950 for (i = 0; p != 0; ){
6953 p = encodings [++i];
6956 if (strcmp (p, codepage) == 0){
6957 *int_code_page = code;
6960 p = encodings [++i];
6963 if (strstr (codepage, "utf_8") != NULL)
6964 *int_code_page |= 0x10000000;
6967 if (want_name && *int_code_page == -1)
6968 return mono_string_new (mono_domain_get (), cset);
6973 ICALL_EXPORT MonoBoolean
6974 ves_icall_System_Environment_get_HasShutdownStarted (void)
6976 if (mono_runtime_is_shutting_down ())
6979 if (mono_domain_is_unloading (mono_domain_get ()))
6986 ves_icall_System_Environment_BroadcastSettingChange (void)
6989 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6994 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7000 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7001 MonoReflectionMethod *method,
7002 MonoArray *out_args)
7004 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7007 #ifndef DISABLE_REMOTING
7008 ICALL_EXPORT MonoBoolean
7009 ves_icall_IsTransparentProxy (MonoObject *proxy)
7014 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7020 ICALL_EXPORT MonoReflectionMethod *
7021 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7022 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7024 MonoReflectionMethod *ret = NULL;
7029 MonoMethod **vtable;
7030 MonoMethod *res = NULL;
7032 MONO_CHECK_ARG_NULL (rtype, NULL);
7033 MONO_CHECK_ARG_NULL (rmethod, NULL);
7035 method = rmethod->method;
7036 klass = mono_class_from_mono_type (rtype->type);
7037 mono_class_init_checked (klass, &error);
7038 mono_error_raise_exception (&error);
7040 if (MONO_CLASS_IS_INTERFACE (klass))
7043 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7046 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7047 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7053 mono_class_setup_vtable (klass);
7054 vtable = klass->vtable;
7056 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7057 gboolean variance_used = FALSE;
7058 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7059 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7061 res = vtable [offs + method->slot];
7063 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7066 if (method->slot != -1)
7067 res = vtable [method->slot];
7073 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7074 mono_error_raise_exception (&error);
7079 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7085 klass = mono_class_from_mono_type (type->type);
7086 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7087 if (!is_ok (&error)) {
7088 mono_error_set_pending_exception (&error);
7092 mono_vtable_set_is_remote (vtable, enable);
7095 #else /* DISABLE_REMOTING */
7098 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7100 g_assert_not_reached ();
7105 ICALL_EXPORT MonoObject *
7106 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7113 domain = mono_object_domain (type);
7114 klass = mono_class_from_mono_type (type->type);
7115 mono_class_init_checked (klass, &error);
7116 mono_error_raise_exception (&error);
7118 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7119 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7123 if (klass->rank >= 1) {
7124 g_assert (klass->rank == 1);
7125 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7127 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7128 if (!is_ok (&error)) {
7129 mono_error_set_pending_exception (&error);
7132 /* Bypass remoting object creation check */
7133 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7134 mono_error_set_pending_exception (&error);
7140 ICALL_EXPORT MonoString *
7141 ves_icall_System_IO_get_temp_path (void)
7143 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7146 #ifndef PLATFORM_NO_DRIVEINFO
7147 ICALL_EXPORT MonoBoolean
7148 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7149 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7153 ULARGE_INTEGER wapi_free_bytes_avail;
7154 ULARGE_INTEGER wapi_total_number_of_bytes;
7155 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7157 *error = ERROR_SUCCESS;
7158 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7159 &wapi_total_number_of_free_bytes);
7162 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7163 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7164 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7166 *free_bytes_avail = 0;
7167 *total_number_of_bytes = 0;
7168 *total_number_of_free_bytes = 0;
7169 *error = GetLastError ();
7175 ICALL_EXPORT guint32
7176 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7178 return GetDriveType (mono_string_chars (root_path_name));
7182 ICALL_EXPORT gpointer
7183 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7185 return mono_compile_method (method);
7188 ICALL_EXPORT MonoString *
7189 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7194 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7196 #if defined (HOST_WIN32)
7197 /* Avoid mixing '/' and '\\' */
7200 for (i = strlen (path) - 1; i >= 0; i--)
7201 if (path [i] == '/')
7205 mcpath = mono_string_new (mono_domain_get (), path);
7212 get_bundled_app_config (void)
7214 const gchar *app_config;
7217 gchar *config_file_name, *config_file_path;
7218 gsize len, config_file_path_length, config_ext_length;
7221 domain = mono_domain_get ();
7222 file = domain->setup->configuration_file;
7223 if (!file || file->length == 0)
7226 // Retrieve config file and remove the extension
7227 config_file_name = mono_string_to_utf8 (file);
7228 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7229 if (!config_file_path)
7230 config_file_path = config_file_name;
7232 config_file_path_length = strlen (config_file_path);
7233 config_ext_length = strlen (".config");
7234 if (config_file_path_length <= config_ext_length)
7237 len = config_file_path_length - config_ext_length;
7238 module = (gchar *)g_malloc0 (len + 1);
7239 memcpy (module, config_file_path, len);
7240 // Get the config file from the module name
7241 app_config = mono_config_string_for_assembly_file (module);
7244 if (config_file_name != config_file_path)
7245 g_free (config_file_name);
7246 g_free (config_file_path);
7251 return mono_string_new (mono_domain_get (), app_config);
7255 get_bundled_machine_config (void)
7257 const gchar *machine_config;
7259 machine_config = mono_get_machine_config ();
7261 if (!machine_config)
7264 return mono_string_new (mono_domain_get (), machine_config);
7267 ICALL_EXPORT MonoString *
7268 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7273 path = g_path_get_dirname (mono_get_config_dir ());
7275 #if defined (HOST_WIN32)
7276 /* Avoid mixing '/' and '\\' */
7279 for (i = strlen (path) - 1; i >= 0; i--)
7280 if (path [i] == '/')
7284 ipath = mono_string_new (mono_domain_get (), path);
7290 ICALL_EXPORT gboolean
7291 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7293 MonoPEResourceDataEntry *entry;
7296 if (!assembly || !result || !size)
7301 image = assembly->assembly->image;
7302 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7306 *result = mono_image_rva_map (image, entry->rde_data_offset);
7311 *size = entry->rde_size;
7316 ICALL_EXPORT MonoBoolean
7317 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7319 return mono_is_debugger_attached ();
7322 ICALL_EXPORT MonoBoolean
7323 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7325 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7326 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7332 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7334 if (mono_get_runtime_callbacks ()->debug_log)
7335 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7339 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7341 #if defined (HOST_WIN32)
7342 OutputDebugString (mono_string_chars (message));
7344 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7348 /* Only used for value types */
7349 ICALL_EXPORT MonoObject *
7350 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7357 domain = mono_object_domain (type);
7358 klass = mono_class_from_mono_type (type->type);
7359 mono_class_init_checked (klass, &error);
7360 mono_error_raise_exception (&error);
7362 if (mono_class_is_nullable (klass))
7363 /* No arguments -> null */
7366 result = mono_object_new_checked (domain, klass, &error);
7367 mono_error_raise_exception (&error);
7371 ICALL_EXPORT MonoReflectionMethod *
7372 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7374 MonoReflectionMethod *ret = NULL;
7377 MonoClass *klass, *parent;
7378 MonoGenericContext *generic_inst = NULL;
7379 MonoMethod *method = m->method;
7380 MonoMethod *result = NULL;
7383 if (method->klass == NULL)
7386 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7387 MONO_CLASS_IS_INTERFACE (method->klass) ||
7388 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7391 slot = mono_method_get_vtable_slot (method);
7395 klass = method->klass;
7396 if (klass->generic_class) {
7397 generic_inst = mono_class_get_context (klass);
7398 klass = klass->generic_class->container_class;
7402 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7403 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7404 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7405 or klass is the generic container class and generic_inst is the instantiation.
7407 when we go to the parent, if the parent is an open constructed type, we need to
7408 replace the type parameters by the definitions from the generic_inst, and then take it
7409 apart again into the klass and the generic_inst.
7411 For cases like this:
7412 class C<T> : B<T, int> {
7413 public override void Foo () { ... }
7415 class B<U,V> : A<HashMap<U,V>> {
7416 public override void Foo () { ... }
7419 public virtual void Foo () { ... }
7422 if at each iteration the parent isn't open, we can skip inflating it. if at some
7423 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7426 MonoGenericContext *parent_inst = NULL;
7427 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7429 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7430 if (!mono_error_ok (&error)) {
7431 mono_error_set_pending_exception (&error);
7435 if (parent->generic_class) {
7436 parent_inst = mono_class_get_context (parent);
7437 parent = parent->generic_class->container_class;
7440 mono_class_setup_vtable (parent);
7441 if (parent->vtable_size <= slot)
7444 generic_inst = parent_inst;
7447 klass = klass->parent;
7450 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7451 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7452 if (!mono_error_ok (&error)) {
7453 mono_error_set_pending_exception (&error);
7457 generic_inst = NULL;
7459 if (klass->generic_class) {
7460 generic_inst = mono_class_get_context (klass);
7461 klass = klass->generic_class->container_class;
7467 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7468 if (!mono_error_ok (&error)) {
7469 mono_error_set_pending_exception (&error);
7474 if (klass == method->klass)
7477 /*This is possible if definition == FALSE.
7478 * Do it here to be really sure we don't read invalid memory.
7480 if (slot >= klass->vtable_size)
7483 mono_class_setup_vtable (klass);
7485 result = klass->vtable [slot];
7486 if (result == NULL) {
7487 /* It is an abstract method */
7488 gpointer iter = NULL;
7489 while ((result = mono_class_get_methods (klass, &iter)))
7490 if (result->slot == slot)
7497 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7498 mono_error_raise_exception (&error);
7502 ICALL_EXPORT MonoString*
7503 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7505 MonoMethod *method = m->method;
7507 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7512 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7514 iter->sig = *(MonoMethodSignature**)argsp;
7516 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7517 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7520 /* FIXME: it's not documented what start is exactly... */
7524 iter->args = argsp + sizeof (gpointer);
7526 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7528 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7531 ICALL_EXPORT MonoTypedRef
7532 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7534 guint32 i, arg_size;
7538 i = iter->sig->sentinelpos + iter->next_arg;
7540 g_assert (i < iter->sig->param_count);
7542 res.type = iter->sig->params [i];
7543 res.klass = mono_class_from_mono_type (res.type);
7544 arg_size = mono_type_stack_size (res.type, &align);
7545 #if defined(__arm__) || defined(__mips__)
7546 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7548 res.value = iter->args;
7549 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7550 /* Values are stored as 8 byte register sized objects, but 'value'
7551 * is dereferenced as a pointer in other routines.
7553 res.value = (char*)res.value + 4;
7555 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7556 if (arg_size <= sizeof (gpointer)) {
7558 int padding = arg_size - mono_type_size (res.type, &dummy);
7559 res.value = (guint8*)res.value + padding;
7562 iter->args = (char*)iter->args + arg_size;
7565 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7570 ICALL_EXPORT MonoTypedRef
7571 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7573 guint32 i, arg_size;
7577 i = iter->sig->sentinelpos + iter->next_arg;
7579 g_assert (i < iter->sig->param_count);
7581 while (i < iter->sig->param_count) {
7582 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7584 res.type = iter->sig->params [i];
7585 res.klass = mono_class_from_mono_type (res.type);
7586 /* FIXME: endianess issue... */
7587 arg_size = mono_type_stack_size (res.type, &align);
7588 #if defined(__arm__) || defined(__mips__)
7589 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7591 res.value = iter->args;
7592 iter->args = (char*)iter->args + arg_size;
7594 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7597 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7605 ICALL_EXPORT MonoType*
7606 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7610 i = iter->sig->sentinelpos + iter->next_arg;
7612 g_assert (i < iter->sig->param_count);
7614 return iter->sig->params [i];
7617 ICALL_EXPORT MonoObject*
7618 mono_TypedReference_ToObject (MonoTypedRef* tref)
7621 MonoObject *result = NULL;
7622 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7623 MonoObject** objp = (MonoObject **)tref->value;
7627 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7628 mono_error_set_pending_exception (&error);
7632 ICALL_EXPORT MonoTypedRef
7633 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7636 MonoReflectionField *f;
7638 MonoType *ftype = NULL;
7642 memset (&res, 0, sizeof (res));
7645 g_assert (mono_array_length (fields) > 0);
7647 klass = target->vtable->klass;
7649 for (i = 0; i < mono_array_length (fields); ++i) {
7650 f = mono_array_get (fields, MonoReflectionField*, i);
7652 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7655 if (f->field->parent != klass) {
7656 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7660 p = (guint8*)target + f->field->offset;
7662 p += f->field->offset - sizeof (MonoObject);
7663 klass = mono_class_from_mono_type (f->field->type);
7664 ftype = f->field->type;
7668 res.klass = mono_class_from_mono_type (ftype);
7675 prelink_method (MonoMethod *method, MonoError *error)
7677 const char *exc_class, *exc_arg;
7679 mono_error_init (error);
7680 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7682 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7684 mono_error_set_exception_instance (error,
7685 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7688 /* create the wrapper, too? */
7692 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7696 prelink_method (method->method, &error);
7697 mono_error_raise_exception (&error);
7701 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7704 MonoClass *klass = mono_class_from_mono_type (type->type);
7706 gpointer iter = NULL;
7708 mono_class_init_checked (klass, &error);
7709 mono_error_raise_exception (&error);
7711 while ((m = mono_class_get_methods (klass, &iter))) {
7712 prelink_method (m, &error);
7713 mono_error_raise_exception (&error);
7717 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7719 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7720 gint32 const **exponents,
7721 gunichar2 const **digitLowerTable,
7722 gunichar2 const **digitUpperTable,
7723 gint64 const **tenPowersList,
7724 gint32 const **decHexDigits)
7726 *mantissas = Formatter_MantissaBitsTable;
7727 *exponents = Formatter_TensExponentTable;
7728 *digitLowerTable = Formatter_DigitLowerTable;
7729 *digitUpperTable = Formatter_DigitUpperTable;
7730 *tenPowersList = Formatter_TenPowersList;
7731 *decHexDigits = Formatter_DecHexDigits;
7735 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7736 * and avoid useless allocations.
7739 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7741 MonoReflectionType *rt;
7745 mono_error_init (error);
7746 for (i = 0; i < type->num_mods; ++i) {
7747 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7752 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7754 for (i = 0; i < type->num_mods; ++i) {
7755 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7756 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7757 return_val_if_nok (error, NULL);
7759 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7760 return_val_if_nok (error, NULL);
7762 mono_array_setref (res, count, rt);
7769 ICALL_EXPORT MonoArray*
7770 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7773 MonoType *type = param->ClassImpl->type;
7774 MonoClass *member_class = mono_object_class (param->MemberImpl);
7775 MonoMethod *method = NULL;
7778 MonoMethodSignature *sig;
7781 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7782 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7783 method = rmethod->method;
7784 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7785 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7786 if (!(method = prop->property->get))
7787 method = prop->property->set;
7790 char *type_name = mono_type_get_full_name (member_class);
7791 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7792 MonoException *ex = mono_get_exception_not_supported (msg);
7795 mono_set_pending_exception (ex);
7799 image = method->klass->image;
7800 pos = param->PositionImpl;
7801 sig = mono_method_signature (method);
7805 type = sig->params [pos];
7807 res = type_array_from_modifiers (image, type, optional, &error);
7808 mono_error_raise_exception (&error);
7813 get_property_type (MonoProperty *prop)
7815 MonoMethodSignature *sig;
7817 sig = mono_method_signature (prop->get);
7819 } else if (prop->set) {
7820 sig = mono_method_signature (prop->set);
7821 return sig->params [sig->param_count - 1];
7826 ICALL_EXPORT MonoArray*
7827 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7830 MonoType *type = get_property_type (property->property);
7831 MonoImage *image = property->klass->image;
7836 res = type_array_from_modifiers (image, type, optional, &error);
7837 mono_error_raise_exception (&error);
7842 *Construct a MonoType suited to be used to decode a constant blob object.
7844 * @type is the target type which will be constructed
7845 * @blob_type is the blob type, for example, that comes from the constant table
7846 * @real_type is the expected constructed type.
7849 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7851 type->type = blob_type;
7852 type->data.klass = NULL;
7853 if (blob_type == MONO_TYPE_CLASS)
7854 type->data.klass = mono_defaults.object_class;
7855 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7856 /* For enums, we need to use the base type */
7857 type->type = MONO_TYPE_VALUETYPE;
7858 type->data.klass = mono_class_from_mono_type (real_type);
7860 type->data.klass = mono_class_from_mono_type (real_type);
7863 ICALL_EXPORT MonoObject*
7864 property_info_get_default_value (MonoReflectionProperty *property)
7868 MonoProperty *prop = property->property;
7869 MonoType *type = get_property_type (prop);
7870 MonoDomain *domain = mono_object_domain (property);
7871 MonoTypeEnum def_type;
7872 const char *def_value;
7875 mono_class_init (prop->parent);
7877 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7878 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7882 def_value = mono_class_get_property_default_value (prop, &def_type);
7884 mono_type_from_blob_type (&blob_type, def_type, type);
7885 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7887 mono_error_set_pending_exception (&error);
7891 ICALL_EXPORT MonoBoolean
7892 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7895 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7896 MonoCustomAttrInfo *cinfo;
7899 mono_class_init_checked (attr_class, &error);
7900 mono_error_raise_exception (&error);
7902 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7903 if (!is_ok (&error)) {
7904 mono_error_set_pending_exception (&error);
7909 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7911 mono_custom_attrs_free (cinfo);
7915 ICALL_EXPORT MonoArray*
7916 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7918 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7923 mono_class_init_checked (attr_class, &error);
7924 mono_error_raise_exception (&error);
7927 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7928 if (!mono_error_ok (&error)) {
7929 mono_error_set_pending_exception (&error);
7933 if (mono_loader_get_last_error ()) {
7934 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7941 ICALL_EXPORT MonoArray*
7942 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7946 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7947 mono_error_set_pending_exception (&error);
7952 ICALL_EXPORT MonoString*
7953 ves_icall_Mono_Runtime_GetDisplayName (void)
7956 MonoString *display_name;
7958 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7959 display_name = mono_string_new (mono_domain_get (), info);
7961 return display_name;
7964 ICALL_EXPORT MonoString*
7965 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7968 MonoString *message;
7972 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7973 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7976 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7978 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7979 mono_error_raise_exception (&error);
7986 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7989 char *path_str = mono_string_to_utf8 (path);
7991 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
7999 ICALL_EXPORT gpointer
8000 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8002 return GetCurrentProcess ();
8005 ICALL_EXPORT MonoBoolean
8006 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8008 return GetExitCodeProcess (handle, (guint32*) exitcode);
8011 ICALL_EXPORT MonoBoolean
8012 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8014 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8015 return CloseHandle (handle);
8017 return CloseProcess (handle);
8021 ICALL_EXPORT MonoBoolean
8022 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8024 return TerminateProcess (handle, exitcode);
8028 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8030 return WaitForInputIdle (handle, milliseconds);
8033 ICALL_EXPORT MonoBoolean
8034 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8036 return GetProcessWorkingSetSize (handle, min, max);
8039 ICALL_EXPORT MonoBoolean
8040 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8042 return SetProcessWorkingSetSize (handle, min, max);
8045 ICALL_EXPORT MonoBoolean
8046 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8048 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8052 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8054 return mono_process_current_pid ();
8058 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8060 return GetPriorityClass (handle);
8063 ICALL_EXPORT MonoBoolean
8064 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8066 return SetPriorityClass (handle, priorityClass);
8069 #ifndef DISABLE_ICALL_TABLES
8071 #define ICALL_TYPE(id,name,first)
8072 #define ICALL(id,name,func) Icall_ ## id,
8075 #include "metadata/icall-def.h"
8081 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8082 #define ICALL(id,name,func)
8084 #include "metadata/icall-def.h"
8090 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8091 #define ICALL(id,name,func)
8093 guint16 first_icall;
8096 static const IcallTypeDesc
8097 icall_type_descs [] = {
8098 #include "metadata/icall-def.h"
8102 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8105 #define ICALL_TYPE(id,name,first)
8108 #ifdef HAVE_ARRAY_ELEM_INIT
8109 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8110 #define MSGSTRFIELD1(line) str##line
8112 static const struct msgstrtn_t {
8113 #define ICALL(id,name,func)
8115 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8116 #include "metadata/icall-def.h"
8118 } icall_type_names_str = {
8119 #define ICALL_TYPE(id,name,first) (name),
8120 #include "metadata/icall-def.h"
8123 static const guint16 icall_type_names_idx [] = {
8124 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8125 #include "metadata/icall-def.h"
8128 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8130 static const struct msgstr_t {
8132 #define ICALL_TYPE(id,name,first)
8133 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8134 #include "metadata/icall-def.h"
8136 } icall_names_str = {
8137 #define ICALL(id,name,func) (name),
8138 #include "metadata/icall-def.h"
8141 static const guint16 icall_names_idx [] = {
8142 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8143 #include "metadata/icall-def.h"
8146 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8152 #define ICALL_TYPE(id,name,first) name,
8153 #define ICALL(id,name,func)
8154 static const char* const
8155 icall_type_names [] = {
8156 #include "metadata/icall-def.h"
8160 #define icall_type_name_get(id) (icall_type_names [(id)])
8164 #define ICALL_TYPE(id,name,first)
8165 #define ICALL(id,name,func) name,
8166 static const char* const
8168 #include "metadata/icall-def.h"
8171 #define icall_name_get(id) icall_names [(id)]
8173 #endif /* !HAVE_ARRAY_ELEM_INIT */
8177 #define ICALL_TYPE(id,name,first)
8178 #define ICALL(id,name,func) func,
8179 static const gconstpointer
8180 icall_functions [] = {
8181 #include "metadata/icall-def.h"
8185 #ifdef ENABLE_ICALL_SYMBOL_MAP
8188 #define ICALL_TYPE(id,name,first)
8189 #define ICALL(id,name,func) #func,
8190 static const gconstpointer
8191 icall_symbols [] = {
8192 #include "metadata/icall-def.h"
8197 #endif /* DISABLE_ICALL_TABLES */
8199 static mono_mutex_t icall_mutex;
8200 static GHashTable *icall_hash = NULL;
8201 static GHashTable *jit_icall_hash_name = NULL;
8202 static GHashTable *jit_icall_hash_addr = NULL;
8205 mono_icall_init (void)
8207 #ifndef DISABLE_ICALL_TABLES
8210 /* check that tables are sorted: disable in release */
8213 const char *prev_class = NULL;
8214 const char *prev_method;
8216 for (i = 0; i < Icall_type_num; ++i) {
8217 const IcallTypeDesc *desc;
8220 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8221 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8222 prev_class = icall_type_name_get (i);
8223 desc = &icall_type_descs [i];
8224 num_icalls = icall_desc_num_icalls (desc);
8225 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8226 for (j = 0; j < num_icalls; ++j) {
8227 const char *methodn = icall_name_get (desc->first_icall + j);
8228 if (prev_method && strcmp (prev_method, methodn) >= 0)
8229 g_print ("method %s should come before method %s\n", methodn, prev_method);
8230 prev_method = methodn;
8236 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8237 mono_os_mutex_init (&icall_mutex);
8241 mono_icall_lock (void)
8243 mono_locks_os_acquire (&icall_mutex, IcallLock);
8247 mono_icall_unlock (void)
8249 mono_locks_os_release (&icall_mutex, IcallLock);
8253 mono_icall_cleanup (void)
8255 g_hash_table_destroy (icall_hash);
8256 g_hash_table_destroy (jit_icall_hash_name);
8257 g_hash_table_destroy (jit_icall_hash_addr);
8258 mono_os_mutex_destroy (&icall_mutex);
8262 * mono_add_internal_call:
8263 * @name: method specification to surface to the managed world
8264 * @method: pointer to a C method to invoke when the method is called
8266 * This method surfaces the C function pointed by @method as a method
8267 * that has been surfaced in managed code with the method specified in
8268 * @name as an internal call.
8270 * Internal calls are surfaced to all app domains loaded and they are
8271 * accessibly by a type with the specified name.
8273 * You must provide a fully qualified type name, that is namespaces
8274 * and type name, followed by a colon and the method name, with an
8275 * optional signature to bind.
8277 * For example, the following are all valid declarations:
8279 * "MyApp.Services.ScriptService:Accelerate"
8280 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8282 * You use method parameters in cases where there might be more than
8283 * one surface method to managed code. That way you can register different
8284 * internal calls for different method overloads.
8286 * The internal calls are invoked with no marshalling. This means that .NET
8287 * types like System.String are exposed as `MonoString *` parameters. This is
8288 * different than the way that strings are surfaced in P/Invoke.
8290 * For more information on how the parameters are marshalled, see the
8291 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8294 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8295 * reference for more information on the format of method descriptions.
8298 mono_add_internal_call (const char *name, gconstpointer method)
8302 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8304 mono_icall_unlock ();
8307 #ifndef DISABLE_ICALL_TABLES
8309 #ifdef HAVE_ARRAY_ELEM_INIT
8311 compare_method_imap (const void *key, const void *elem)
8313 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8314 return strcmp (key, method_name);
8318 find_method_icall (const IcallTypeDesc *imap, const char *name)
8320 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);
8323 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8327 compare_class_imap (const void *key, const void *elem)
8329 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8330 return strcmp (key, class_name);
8333 static const IcallTypeDesc*
8334 find_class_icalls (const char *name)
8336 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);
8339 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8342 #else /* HAVE_ARRAY_ELEM_INIT */
8345 compare_method_imap (const void *key, const void *elem)
8347 const char** method_name = (const char**)elem;
8348 return strcmp (key, *method_name);
8352 find_method_icall (const IcallTypeDesc *imap, const char *name)
8354 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8357 return (gpointer)icall_functions [(nameslot - icall_names)];
8361 compare_class_imap (const void *key, const void *elem)
8363 const char** class_name = (const char**)elem;
8364 return strcmp (key, *class_name);
8367 static const IcallTypeDesc*
8368 find_class_icalls (const char *name)
8370 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8373 return &icall_type_descs [nameslot - icall_type_names];
8376 #endif /* HAVE_ARRAY_ELEM_INIT */
8378 #endif /* DISABLE_ICALL_TABLES */
8381 * we should probably export this as an helper (handle nested types).
8382 * Returns the number of chars written in buf.
8385 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8387 int nspacelen, cnamelen;
8388 nspacelen = strlen (klass->name_space);
8389 cnamelen = strlen (klass->name);
8390 if (nspacelen + cnamelen + 2 > bufsize)
8393 memcpy (buf, klass->name_space, nspacelen);
8394 buf [nspacelen ++] = '.';
8396 memcpy (buf + nspacelen, klass->name, cnamelen);
8397 buf [nspacelen + cnamelen] = 0;
8398 return nspacelen + cnamelen;
8401 #ifdef DISABLE_ICALL_TABLES
8403 no_icall_table (void)
8405 g_assert_not_reached ();
8410 mono_lookup_internal_call (MonoMethod *method)
8415 int typelen = 0, mlen, siglen;
8417 #ifndef DISABLE_ICALL_TABLES
8418 const IcallTypeDesc *imap = NULL;
8421 g_assert (method != NULL);
8423 if (method->is_inflated)
8424 method = ((MonoMethodInflated *) method)->declaring;
8426 if (method->klass->nested_in) {
8427 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8431 mname [pos++] = '/';
8434 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8440 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8445 #ifndef DISABLE_ICALL_TABLES
8446 imap = find_class_icalls (mname);
8449 mname [typelen] = ':';
8450 mname [typelen + 1] = ':';
8452 mlen = strlen (method->name);
8453 memcpy (mname + typelen + 2, method->name, mlen);
8454 sigstart = mname + typelen + 2 + mlen;
8457 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8458 siglen = strlen (tmpsig);
8459 if (typelen + mlen + siglen + 6 > sizeof (mname))
8462 memcpy (sigstart + 1, tmpsig, siglen);
8463 sigstart [siglen + 1] = ')';
8464 sigstart [siglen + 2] = 0;
8469 res = g_hash_table_lookup (icall_hash, mname);
8471 mono_icall_unlock ();;
8474 /* try without signature */
8476 res = g_hash_table_lookup (icall_hash, mname);
8478 mono_icall_unlock ();
8482 #ifdef DISABLE_ICALL_TABLES
8483 mono_icall_unlock ();
8484 /* Fail only when the result is actually used */
8485 /* mono_marshal_get_native_wrapper () depends on this */
8486 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8487 return ves_icall_System_String_ctor_RedirectToCreateString;
8489 return no_icall_table;
8491 /* it wasn't found in the static call tables */
8493 mono_icall_unlock ();
8496 res = find_method_icall (imap, sigstart - mlen);
8498 mono_icall_unlock ();
8501 /* try _with_ signature */
8503 res = find_method_icall (imap, sigstart - mlen);
8505 mono_icall_unlock ();
8509 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8510 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8511 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8512 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8513 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");
8514 g_print ("If you see other errors or faults after this message they are probably related\n");
8515 g_print ("and you need to fix your mono install first.\n");
8517 mono_icall_unlock ();
8523 #ifdef ENABLE_ICALL_SYMBOL_MAP
8525 func_cmp (gconstpointer key, gconstpointer p)
8527 return (gsize)key - (gsize)*(gsize*)p;
8532 * mono_lookup_icall_symbol:
8534 * Given the icall METHOD, returns its C symbol.
8537 mono_lookup_icall_symbol (MonoMethod *m)
8539 #ifdef DISABLE_ICALL_TABLES
8540 g_assert_not_reached ();
8543 #ifdef ENABLE_ICALL_SYMBOL_MAP
8547 static gconstpointer *functions_sorted;
8548 static const char**symbols_sorted;
8549 static gboolean inited;
8554 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8555 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8556 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8557 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8558 /* Bubble sort the two arrays */
8562 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8563 if (functions_sorted [i] > functions_sorted [i + 1]) {
8566 tmp = functions_sorted [i];
8567 functions_sorted [i] = functions_sorted [i + 1];
8568 functions_sorted [i + 1] = tmp;
8569 tmp = symbols_sorted [i];
8570 symbols_sorted [i] = symbols_sorted [i + 1];
8571 symbols_sorted [i + 1] = tmp;
8578 func = mono_lookup_internal_call (m);
8581 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8585 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8587 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8588 g_assert_not_reached ();
8595 type_from_typename (char *type_name)
8597 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8599 if (!strcmp (type_name, "int"))
8600 klass = mono_defaults.int_class;
8601 else if (!strcmp (type_name, "ptr"))
8602 klass = mono_defaults.int_class;
8603 else if (!strcmp (type_name, "void"))
8604 klass = mono_defaults.void_class;
8605 else if (!strcmp (type_name, "int32"))
8606 klass = mono_defaults.int32_class;
8607 else if (!strcmp (type_name, "uint32"))
8608 klass = mono_defaults.uint32_class;
8609 else if (!strcmp (type_name, "int8"))
8610 klass = mono_defaults.sbyte_class;
8611 else if (!strcmp (type_name, "uint8"))
8612 klass = mono_defaults.byte_class;
8613 else if (!strcmp (type_name, "int16"))
8614 klass = mono_defaults.int16_class;
8615 else if (!strcmp (type_name, "uint16"))
8616 klass = mono_defaults.uint16_class;
8617 else if (!strcmp (type_name, "long"))
8618 klass = mono_defaults.int64_class;
8619 else if (!strcmp (type_name, "ulong"))
8620 klass = mono_defaults.uint64_class;
8621 else if (!strcmp (type_name, "float"))
8622 klass = mono_defaults.single_class;
8623 else if (!strcmp (type_name, "double"))
8624 klass = mono_defaults.double_class;
8625 else if (!strcmp (type_name, "object"))
8626 klass = mono_defaults.object_class;
8627 else if (!strcmp (type_name, "obj"))
8628 klass = mono_defaults.object_class;
8629 else if (!strcmp (type_name, "string"))
8630 klass = mono_defaults.string_class;
8631 else if (!strcmp (type_name, "bool"))
8632 klass = mono_defaults.boolean_class;
8633 else if (!strcmp (type_name, "boolean"))
8634 klass = mono_defaults.boolean_class;
8636 g_error ("%s", type_name);
8637 g_assert_not_reached ();
8639 return &klass->byval_arg;
8643 * LOCKING: Take the corlib image lock.
8645 MonoMethodSignature*
8646 mono_create_icall_signature (const char *sigstr)
8651 MonoMethodSignature *res, *res2;
8652 MonoImage *corlib = mono_defaults.corlib;
8654 mono_image_lock (corlib);
8655 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8656 mono_image_unlock (corlib);
8661 parts = g_strsplit (sigstr, " ", 256);
8670 res = mono_metadata_signature_alloc (corlib, len - 1);
8675 * Under windows, the default pinvoke calling convention is STDCALL but
8678 res->call_convention = MONO_CALL_C;
8681 res->ret = type_from_typename (parts [0]);
8682 for (i = 1; i < len; ++i) {
8683 res->params [i - 1] = type_from_typename (parts [i]);
8688 mono_image_lock (corlib);
8689 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8691 res = res2; /*Value is allocated in the image pool*/
8693 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8694 mono_image_unlock (corlib);
8700 mono_find_jit_icall_by_name (const char *name)
8702 MonoJitICallInfo *info;
8703 g_assert (jit_icall_hash_name);
8706 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8707 mono_icall_unlock ();
8712 mono_find_jit_icall_by_addr (gconstpointer addr)
8714 MonoJitICallInfo *info;
8715 g_assert (jit_icall_hash_addr);
8718 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8719 mono_icall_unlock ();
8725 * mono_get_jit_icall_info:
8727 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8728 * caller should access it while holding the icall lock.
8731 mono_get_jit_icall_info (void)
8733 return jit_icall_hash_name;
8737 * mono_lookup_jit_icall_symbol:
8739 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8742 mono_lookup_jit_icall_symbol (const char *name)
8744 MonoJitICallInfo *info;
8745 const char *res = NULL;
8748 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8750 res = info->c_symbol;
8751 mono_icall_unlock ();
8756 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8759 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8760 mono_icall_unlock ();
8764 * 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
8765 * icalls without wrappers in some cases.
8768 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8770 MonoJitICallInfo *info;
8777 if (!jit_icall_hash_name) {
8778 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8779 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8782 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8783 g_warning ("jit icall already defined \"%s\"\n", name);
8784 g_assert_not_reached ();
8787 info = g_new0 (MonoJitICallInfo, 1);
8792 info->c_symbol = c_symbol;
8793 info->no_raise = no_raise;
8796 info->wrapper = func;
8798 info->wrapper = NULL;
8801 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8802 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8804 mono_icall_unlock ();
8809 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8811 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);