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);
4382 ICALL_EXPORT MonoReflectionType*
4383 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4386 MonoReflectionType *ret;
4388 MonoType *type = NULL;
4389 MonoTypeNameParse info;
4390 gboolean type_resolve;
4392 /* On MS.NET, this does not fire a TypeResolve event */
4393 type_resolve = TRUE;
4394 str = mono_string_to_utf8 (name);
4395 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4396 if (!mono_reflection_parse_type (str, &info)) {
4398 mono_reflection_free_type_info (&info);
4400 mono_set_pending_exception (mono_get_exception_argument("name", "failed parse"));
4403 /*g_print ("failed parse\n");*/
4407 if (info.assembly.name) {
4409 mono_reflection_free_type_info (&info);
4411 /* 1.0 and 2.0 throw different exceptions */
4412 if (mono_defaults.generic_ilist_class)
4413 mono_set_pending_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4415 mono_set_pending_exception (mono_get_exception_type_load (name, NULL));
4421 if (module != NULL) {
4422 if (module->image) {
4423 type = mono_reflection_get_type_checked (module->image, &info, ignoreCase, &type_resolve, &error);
4424 if (!is_ok (&error)) {
4426 mono_reflection_free_type_info (&info);
4427 mono_error_set_pending_exception (&error);
4434 if (assembly_is_dynamic (assembly->assembly)) {
4435 /* Enumerate all modules */
4436 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4440 if (abuilder->modules) {
4441 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4442 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4443 type = mono_reflection_get_type_checked (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve, &error);
4444 if (!is_ok (&error)) {
4446 mono_reflection_free_type_info (&info);
4447 mono_error_set_pending_exception (&error);
4455 if (!type && abuilder->loaded_modules) {
4456 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4457 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4458 type = mono_reflection_get_type_checked (mod->image, &info, ignoreCase, &type_resolve, &error);
4459 if (!is_ok (&error)) {
4461 mono_reflection_free_type_info (&info);
4462 mono_error_set_pending_exception (&error);
4471 type = mono_reflection_get_type_checked (assembly->assembly->image, &info, ignoreCase, &type_resolve, &error);
4472 if (!is_ok (&error)) {
4474 mono_reflection_free_type_info (&info);
4475 mono_error_set_pending_exception (&error);
4480 mono_reflection_free_type_info (&info);
4482 MonoException *e = NULL;
4485 e = mono_get_exception_type_load (name, NULL);
4487 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4488 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4490 mono_loader_clear_error ();
4493 mono_set_pending_exception (e);
4495 } else if (mono_loader_get_last_error ()) {
4497 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4500 mono_loader_clear_error ();
4503 if (type->type == MONO_TYPE_CLASS) {
4504 MonoClass *klass = mono_type_get_class (type);
4506 /* need to report exceptions ? */
4507 if (throwOnError && mono_class_has_failure (klass)) {
4508 /* report SecurityException (or others) that occured when loading the assembly */
4509 MonoException *exc = mono_class_get_exception_for_failure (klass);
4510 mono_loader_clear_error ();
4511 mono_set_pending_exception (exc);
4516 /* g_print ("got it\n"); */
4517 ret = mono_type_get_object_checked (mono_object_domain (assembly), type, &error);
4518 mono_error_set_pending_exception (&error);
4524 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4527 gchar *shadow_ini_file;
4530 /* Check for shadow-copied assembly */
4531 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4532 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4534 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4535 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4541 g_free (shadow_ini_file);
4542 if (content != NULL) {
4545 *filename = content;
4552 ICALL_EXPORT MonoString *
4553 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4555 MonoDomain *domain = mono_object_domain (assembly);
4556 MonoAssembly *mass = assembly->assembly;
4557 MonoString *res = NULL;
4562 if (g_path_is_absolute (mass->image->name)) {
4563 absolute = g_strdup (mass->image->name);
4564 dirname = g_path_get_dirname (absolute);
4566 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4567 dirname = g_strdup (mass->basedir);
4570 replace_shadow_path (domain, dirname, &absolute);
4575 for (i = strlen (absolute) - 1; i >= 0; i--)
4576 if (absolute [i] == '\\')
4581 uri = g_filename_to_uri (absolute, NULL, NULL);
4583 const char *prepend = "file://";
4585 if (*absolute == '/' && *(absolute + 1) == '/') {
4588 prepend = "file:///";
4591 uri = g_strconcat (prepend, absolute, NULL);
4595 res = mono_string_new (domain, uri);
4602 ICALL_EXPORT MonoBoolean
4603 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4605 MonoAssembly *mass = assembly->assembly;
4607 return mass->in_gac;
4610 ICALL_EXPORT MonoReflectionAssembly*
4611 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4616 MonoImageOpenStatus status;
4617 MonoReflectionAssembly* result = NULL;
4619 name = mono_string_to_utf8 (mname);
4620 res = mono_assembly_load_with_partial_name (name, &status);
4626 result = mono_assembly_get_object_checked (mono_domain_get (), res, &error);
4628 mono_error_set_pending_exception (&error);
4632 ICALL_EXPORT MonoString *
4633 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4635 MonoDomain *domain = mono_object_domain (assembly);
4638 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4643 ICALL_EXPORT MonoBoolean
4644 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4646 return assembly->assembly->ref_only;
4649 ICALL_EXPORT MonoString *
4650 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4652 MonoDomain *domain = mono_object_domain (assembly);
4654 return mono_string_new (domain, assembly->assembly->image->version);
4657 ICALL_EXPORT MonoReflectionMethod*
4658 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4661 MonoReflectionMethod *res = NULL;
4664 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4668 method = mono_get_method_checked (assembly->assembly->image, token, NULL, NULL, &error);
4669 if (!mono_error_ok (&error))
4672 res = mono_method_get_object_checked (mono_object_domain (assembly), method, NULL, &error);
4675 if (!mono_error_ok (&error))
4676 mono_error_set_pending_exception (&error);
4680 ICALL_EXPORT MonoReflectionModule*
4681 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4684 MonoReflectionModule *result = NULL;
4685 result = mono_module_get_object_checked (mono_object_domain (assembly), assembly->assembly->image, &error);
4686 if (!mono_error_ok (&error))
4687 mono_error_set_pending_exception (&error);
4691 ICALL_EXPORT MonoArray*
4692 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4694 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4695 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4699 for (i = 0; i < table->rows; ++i) {
4700 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4701 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4707 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision, MonoError *error)
4709 static MonoMethod *create_version = NULL;
4713 mono_error_init (error);
4716 if (!create_version) {
4717 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4718 create_version = mono_method_desc_search_in_class (desc, mono_class_get_system_version_class ());
4719 g_assert (create_version);
4720 mono_method_desc_free (desc);
4726 args [3] = &revision;
4727 result = mono_object_new_checked (domain, mono_class_get_system_version_class (), error);
4728 return_val_if_nok (error, NULL);
4730 mono_runtime_invoke_checked (create_version, result, args, error);
4731 return_val_if_nok (error, NULL);
4736 ICALL_EXPORT MonoArray*
4737 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4741 MonoDomain *domain = mono_object_domain (assembly);
4743 static MonoMethod *create_culture = NULL;
4744 MonoImage *image = assembly->assembly->image;
4748 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4751 result = mono_array_new (domain, mono_class_get_assembly_name_class (), count);
4753 if (count > 0 && !create_culture) {
4754 MonoMethodDesc *desc = mono_method_desc_new (
4755 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4756 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4757 g_assert (create_culture);
4758 mono_method_desc_free (desc);
4761 for (i = 0; i < count; i++) {
4762 MonoObject *version;
4763 MonoReflectionAssemblyName *aname;
4764 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4766 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4768 aname = (MonoReflectionAssemblyName *) mono_object_new_checked (
4769 domain, mono_class_get_assembly_name_class (), &error);
4770 mono_error_raise_exception (&error);
4772 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4774 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4775 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4776 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4777 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4778 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4779 aname->versioncompat = 1; /* SameMachine (default) */
4780 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4782 version = create_version (domain, aname->major, aname->minor, aname->build, aname->revision, &error);
4783 mono_error_raise_exception (&error);
4785 MONO_OBJECT_SETREF (aname, version, version);
4787 if (create_culture) {
4789 MonoBoolean assembly_ref = 1;
4790 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4791 args [1] = &assembly_ref;
4793 o = mono_runtime_invoke_checked (create_culture, NULL, args, &error);
4794 mono_error_raise_exception (&error);
4796 MONO_OBJECT_SETREF (aname, cultureInfo, o);
4799 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4800 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4801 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4803 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4804 /* public key token isn't copied - the class library will
4805 automatically generate it from the public key if required */
4806 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4807 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4809 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4810 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4813 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4816 /* note: this function doesn't return the codebase on purpose (i.e. it can
4817 be used under partial trust as path information isn't present). */
4819 mono_array_setref (result, i, aname);
4824 /* move this in some file in mono/util/ */
4826 g_concat_dir_and_file (const char *dir, const char *file)
4828 g_return_val_if_fail (dir != NULL, NULL);
4829 g_return_val_if_fail (file != NULL, NULL);
4832 * If the directory name doesn't have a / on the end, we need
4833 * to add one so we get a proper path to the file
4835 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4836 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4838 return g_strconcat (dir, file, NULL);
4842 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4845 char *n = mono_string_to_utf8 (name);
4846 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4848 guint32 cols [MONO_MANIFEST_SIZE];
4849 guint32 impl, file_idx;
4853 for (i = 0; i < table->rows; ++i) {
4854 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4855 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4856 if (strcmp (val, n) == 0)
4860 if (i == table->rows)
4863 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4866 * this code should only be called after obtaining the
4867 * ResourceInfo and handling the other cases.
4869 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4870 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4872 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4877 module = assembly->assembly->image;
4880 MonoReflectionModule *rm = mono_module_get_object_checked (mono_domain_get (), module, &error);
4881 mono_error_raise_exception (&error);
4882 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) rm);
4884 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4887 ICALL_EXPORT gboolean
4888 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4891 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4893 guint32 cols [MONO_MANIFEST_SIZE];
4894 guint32 file_cols [MONO_FILE_SIZE];
4898 n = mono_string_to_utf8 (name);
4899 for (i = 0; i < table->rows; ++i) {
4900 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4901 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4902 if (strcmp (val, n) == 0)
4906 if (i == table->rows)
4909 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4910 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4913 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4914 case MONO_IMPLEMENTATION_FILE:
4915 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4916 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4917 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4918 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4919 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4920 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4923 info->location = RESOURCE_LOCATION_EMBEDDED;
4926 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4927 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4928 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4929 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4930 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4931 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4933 mono_set_pending_exception (ex);
4936 MonoReflectionAssembly *assm_obj;
4937 assm_obj = mono_assembly_get_object_checked (mono_domain_get (), assembly->assembly->image->references [i - 1], &error);
4939 mono_error_set_pending_exception (&error);
4942 MONO_OBJECT_SETREF (info, assembly, assm_obj);
4944 /* Obtain info recursively */
4945 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4946 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4949 case MONO_IMPLEMENTATION_EXP_TYPE:
4950 g_assert_not_reached ();
4958 ICALL_EXPORT MonoObject*
4959 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4961 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4962 MonoArray *result = NULL;
4967 /* check hash if needed */
4969 n = mono_string_to_utf8 (name);
4970 for (i = 0; i < table->rows; ++i) {
4971 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4972 if (strcmp (val, n) == 0) {
4975 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4976 fn = mono_string_new (mono_object_domain (assembly), n);
4978 return (MonoObject*)fn;
4986 for (i = 0; i < table->rows; ++i) {
4987 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4991 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4994 for (i = 0; i < table->rows; ++i) {
4995 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4996 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4997 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4998 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
5003 return (MonoObject*)result;
5006 ICALL_EXPORT MonoArray*
5007 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
5010 MonoDomain *domain = mono_domain_get();
5013 int i, j, file_count = 0;
5014 MonoImage **modules;
5015 guint32 module_count, real_module_count;
5016 MonoTableInfo *table;
5017 guint32 cols [MONO_FILE_SIZE];
5018 MonoImage *image = assembly->assembly->image;
5020 g_assert (image != NULL);
5021 g_assert (!assembly_is_dynamic (assembly->assembly));
5023 table = &image->tables [MONO_TABLE_FILE];
5024 file_count = table->rows;
5026 modules = image->modules;
5027 module_count = image->module_count;
5029 real_module_count = 0;
5030 for (i = 0; i < module_count; ++i)
5032 real_module_count ++;
5034 klass = mono_class_get_module_class ();
5035 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5037 MonoReflectionModule *image_obj = mono_module_get_object_checked (domain, image, &error);
5038 mono_error_raise_exception (&error);
5039 mono_array_setref (res, 0, image_obj);
5041 for (i = 0; i < module_count; ++i)
5043 MonoReflectionModule *rm = mono_module_get_object_checked (domain, modules[i], &error);
5044 mono_error_raise_exception (&error);
5045 mono_array_setref (res, j, rm);
5049 for (i = 0; i < file_count; ++i, ++j) {
5050 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5051 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA) {
5052 MonoReflectionModule *rm = mono_module_file_get_object_checked (domain, image, i, &error);
5053 mono_error_raise_exception (&error);
5054 mono_array_setref (res, j, rm);
5057 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5059 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5060 mono_set_pending_exception (mono_get_exception_file_not_found2 (NULL, fname));
5063 MonoReflectionModule *rm = mono_module_get_object_checked (domain, m, &error);
5064 mono_error_raise_exception (&error);
5065 mono_array_setref (res, j, rm);
5072 ICALL_EXPORT MonoReflectionMethod*
5073 ves_icall_GetCurrentMethod (void)
5075 MonoReflectionMethod *res = NULL;
5078 MonoMethod *m = mono_method_get_last_managed ();
5081 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5085 while (m->is_inflated)
5086 m = ((MonoMethodInflated*)m)->declaring;
5088 res = mono_method_get_object_checked (mono_domain_get (), m, NULL, &error);
5089 mono_error_raise_exception (&error);
5095 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5098 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5101 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5102 //method is inflated, we should inflate it on the other class
5103 MonoGenericContext ctx;
5104 ctx.method_inst = inflated->context.method_inst;
5105 ctx.class_inst = inflated->context.class_inst;
5106 if (klass->generic_class)
5107 ctx.class_inst = klass->generic_class->context.class_inst;
5108 else if (klass->generic_container)
5109 ctx.class_inst = klass->generic_container->context.class_inst;
5110 result = mono_class_inflate_generic_method_full_checked (inflated->declaring, klass, &ctx, &error);
5111 g_assert (mono_error_ok (&error)); /* FIXME don't swallow the error */
5115 mono_class_setup_methods (method->klass);
5116 if (mono_class_has_failure (method->klass))
5118 for (i = 0; i < method->klass->method.count; ++i) {
5119 if (method->klass->methods [i] == method) {
5124 mono_class_setup_methods (klass);
5125 if (mono_class_has_failure (klass))
5127 g_assert (offset >= 0 && offset < klass->method.count);
5128 return klass->methods [offset];
5131 ICALL_EXPORT MonoReflectionMethod*
5132 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5134 MonoReflectionMethod *res = NULL;
5138 klass = mono_class_from_mono_type (type);
5139 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5141 if (method->klass != klass) {
5142 method = mono_method_get_equivalent_method (method, klass);
5147 klass = method->klass;
5148 res = mono_method_get_object_checked (mono_domain_get (), method, klass, &error);
5149 mono_error_raise_exception (&error);
5153 ICALL_EXPORT MonoReflectionMethodBody*
5154 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5157 MonoReflectionMethodBody *result = mono_method_body_get_object_checked (mono_domain_get (), method, &error);
5158 mono_error_set_pending_exception (&error);
5162 ICALL_EXPORT MonoReflectionAssembly*
5163 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5166 MonoReflectionAssembly *result;
5167 MonoMethod *dest = NULL;
5169 mono_stack_walk_no_il (get_executing, &dest);
5171 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5173 mono_error_set_pending_exception (&error);
5178 ICALL_EXPORT MonoReflectionAssembly*
5179 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5182 MonoReflectionAssembly *result;
5183 MonoDomain* domain = mono_domain_get ();
5185 if (!domain->entry_assembly)
5188 result = mono_assembly_get_object_checked (domain, domain->entry_assembly, &error);
5190 mono_error_set_pending_exception (&error);
5194 ICALL_EXPORT MonoReflectionAssembly*
5195 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5200 MonoReflectionAssembly *result;
5203 mono_stack_walk_no_il (get_executing, &dest);
5205 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
5209 mono_set_pending_exception (mono_get_exception_not_supported ("Stack walks are not supported on this platform."));
5212 result = mono_assembly_get_object_checked (mono_domain_get (), dest->klass->image->assembly, &error);
5214 mono_error_set_pending_exception (&error);
5218 ICALL_EXPORT MonoString *
5219 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5220 gboolean assembly_qualified)
5222 MonoDomain *domain = mono_object_domain (object);
5223 MonoTypeNameFormat format;
5228 format = assembly_qualified ?
5229 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5230 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5232 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5234 name = mono_type_get_name_full (object->type, format);
5238 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5243 res = mono_string_new (domain, name);
5250 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *rfield)
5253 MonoClass *klass = mono_class_from_mono_type (rfield->type);
5255 mono_class_init_checked (klass, &error);
5256 mono_error_raise_exception (&error);
5257 return mono_security_core_clr_class_level (klass);
5261 ves_icall_MonoField_get_core_clr_security_level (MonoReflectionField *rfield)
5263 MonoClassField *field = rfield->field;
5264 return mono_security_core_clr_field_level (field, TRUE);
5268 ves_icall_MonoMethod_get_core_clr_security_level (MonoReflectionMethod *rfield)
5270 MonoMethod *method = rfield->method;
5271 return mono_security_core_clr_method_level (method, TRUE);
5275 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)
5277 static MonoMethod *create_culture = NULL;
5281 const char *pkey_ptr;
5283 MonoBoolean assembly_ref = 0;
5285 mono_error_init (error);
5287 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5288 aname->major = name->major;
5289 aname->minor = name->minor;
5290 aname->build = name->build;
5291 aname->flags = name->flags;
5292 aname->revision = name->revision;
5293 aname->hashalg = name->hash_alg;
5294 aname->versioncompat = 1; /* SameMachine (default) */
5295 aname->processor_architecture = name->arch;
5297 if (by_default_version) {
5298 MonoObject *version;
5300 version = create_version (domain, name->major, name->minor, name->build, name->revision, error);
5301 return_if_nok (error);
5303 MONO_OBJECT_SETREF (aname, version, version);
5307 if (absolute != NULL && *absolute != '\0') {
5308 const gchar *prepend = "file://";
5311 codebase = g_strdup (absolute);
5316 for (i = strlen (codebase) - 1; i >= 0; i--)
5317 if (codebase [i] == '\\')
5320 if (*codebase == '/' && *(codebase + 1) == '/') {
5323 prepend = "file:///";
5327 result = g_strconcat (prepend, codebase, NULL);
5333 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5337 if (!create_culture) {
5338 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5339 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5340 g_assert (create_culture);
5341 mono_method_desc_free (desc);
5344 if (name->culture) {
5345 args [0] = mono_string_new (domain, name->culture);
5346 args [1] = &assembly_ref;
5348 obj = mono_runtime_invoke_checked (create_culture, NULL, args, error);
5349 return_if_nok (error);
5351 MONO_OBJECT_SETREF (aname, cultureInfo, obj);
5354 if (name->public_key) {
5355 pkey_ptr = (char*)name->public_key;
5356 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5358 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5359 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5360 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5361 } else if (default_publickey) {
5362 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5363 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5366 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5367 if (name->public_key_token [0]) {
5371 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5372 p = mono_array_addr (aname->keyToken, char, 0);
5374 for (i = 0, j = 0; i < 8; i++) {
5375 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5376 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5379 } else if (default_token) {
5380 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5384 ICALL_EXPORT MonoString *
5385 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5387 MonoDomain *domain = mono_object_domain (assembly);
5388 MonoAssembly *mass = assembly->assembly;
5392 name = mono_stringify_assembly_name (&mass->aname);
5393 res = mono_string_new (domain, name);
5400 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5404 MonoAssembly *mass = assembly->assembly;
5406 if (g_path_is_absolute (mass->image->name)) {
5407 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, mass->image->name, TRUE, TRUE, TRUE, &error);
5408 mono_error_set_pending_exception (&error);
5411 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5413 fill_reflection_assembly_name (mono_object_domain (assembly), aname, &mass->aname, absolute, TRUE, TRUE, TRUE, &error);
5414 mono_error_set_pending_exception (&error);
5420 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5424 MonoImageOpenStatus status = MONO_IMAGE_OK;
5427 MonoAssemblyName name;
5430 filename = mono_string_to_utf8 (fname);
5432 dirname = g_path_get_dirname (filename);
5433 replace_shadow_path (mono_domain_get (), dirname, &filename);
5436 image = mono_image_open (filename, &status);
5442 if (status == MONO_IMAGE_IMAGE_INVALID)
5443 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5445 exc = mono_get_exception_file_not_found2 (NULL, fname);
5446 mono_set_pending_exception (exc);
5450 res = mono_assembly_fill_assembly_name (image, &name);
5452 mono_image_close (image);
5454 mono_set_pending_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5458 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename, TRUE, FALSE, TRUE, &error);
5459 mono_error_set_pending_exception (&error);
5461 mono_image_close (image);
5465 ICALL_EXPORT MonoBoolean
5466 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5467 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5469 MonoBoolean result = FALSE;
5470 MonoDeclSecurityEntry entry;
5472 /* SecurityAction.RequestMinimum */
5473 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5474 *minimum = entry.blob;
5475 *minLength = entry.size;
5478 /* SecurityAction.RequestOptional */
5479 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5480 *optional = entry.blob;
5481 *optLength = entry.size;
5484 /* SecurityAction.RequestRefuse */
5485 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5486 *refused = entry.blob;
5487 *refLength = entry.size;
5495 mono_module_type_is_visible (MonoTableInfo *tdef, MonoImage *image, int type)
5497 guint32 attrs, visibility;
5499 attrs = mono_metadata_decode_row_col (tdef, type - 1, MONO_TYPEDEF_FLAGS);
5500 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5501 if (visibility != TYPE_ATTRIBUTE_PUBLIC && visibility != TYPE_ATTRIBUTE_NESTED_PUBLIC)
5504 } while ((type = mono_metadata_token_index (mono_metadata_nested_in_typedef (image, type))));
5510 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly, MonoError *error)
5512 MonoReflectionType *rt;
5515 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5518 mono_error_init (error);
5520 /* we start the count from 1 because we skip the special type <Module> */
5523 for (i = 1; i < tdef->rows; ++i) {
5524 if (mono_module_type_is_visible (tdef, image, i + 1))
5528 count = tdef->rows - 1;
5530 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5531 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5533 for (i = 1; i < tdef->rows; ++i) {
5534 if (!exportedOnly || mono_module_type_is_visible (tdef, image, i + 1)) {
5535 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, error);
5536 mono_loader_assert_no_error (); /* Plug any leaks */
5539 rt = mono_type_get_object_checked (domain, &klass->byval_arg, error);
5540 return_val_if_nok (error, NULL);
5542 mono_array_setref (res, count, rt);
5544 MonoException *ex = mono_error_convert_to_exception (error);
5545 mono_array_setref (*exceptions, count, ex);
5554 ICALL_EXPORT MonoArray*
5555 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5558 MonoArray *res = NULL;
5559 MonoArray *exceptions = NULL;
5560 MonoImage *image = NULL;
5561 MonoTableInfo *table = NULL;
5564 int i, len, ex_count;
5566 domain = mono_object_domain (assembly);
5568 g_assert (!assembly_is_dynamic (assembly->assembly));
5569 image = assembly->assembly->image;
5570 table = &image->tables [MONO_TABLE_FILE];
5571 res = mono_module_get_types (domain, image, &exceptions, exportedOnly, &error);
5572 mono_error_raise_exception (&error);
5574 /* Append data from all modules in the assembly */
5575 for (i = 0; i < table->rows; ++i) {
5576 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5577 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5582 res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly, &error);
5583 mono_error_raise_exception (&error);
5585 /* Append the new types to the end of the array */
5586 if (mono_array_length (res2) > 0) {
5588 MonoArray *res3, *ex3;
5590 len1 = mono_array_length (res);
5591 len2 = mono_array_length (res2);
5593 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5594 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5595 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5598 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5599 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5600 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5607 /* the ReflectionTypeLoadException must have all the types (Types property),
5608 * NULL replacing types which throws an exception. The LoaderException must
5609 * contain all exceptions for NULL items.
5612 len = mono_array_length (res);
5615 for (i = 0; i < len; i++) {
5616 MonoReflectionType *t = (MonoReflectionType *)mono_array_get (res, gpointer, i);
5620 klass = mono_type_get_class (t->type);
5621 if ((klass != NULL) && mono_class_has_failure (klass)) {
5622 /* keep the class in the list */
5623 list = g_list_append (list, klass);
5624 /* and replace Type with NULL */
5625 mono_array_setref (res, i, NULL);
5632 if (list || ex_count) {
5634 MonoException *exc = NULL;
5635 MonoArray *exl = NULL;
5636 int j, length = g_list_length (list) + ex_count;
5638 mono_loader_clear_error ();
5640 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5641 /* Types for which mono_class_get_checked () succeeded */
5642 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5643 MonoException *exc = mono_class_get_exception_for_failure ((MonoClass *)tmp->data);
5644 mono_array_setref (exl, i, exc);
5646 /* Types for which it don't */
5647 for (j = 0; j < mono_array_length (exceptions); ++j) {
5648 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5650 g_assert (i < length);
5651 mono_array_setref (exl, i, exc);
5658 exc = mono_get_exception_reflection_type_load_checked (res, exl, &error);
5659 if (!is_ok (&error)) {
5660 mono_error_set_pending_exception (&error);
5663 mono_loader_clear_error ();
5664 mono_set_pending_exception (exc);
5671 ICALL_EXPORT gboolean
5672 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5675 MonoAssemblyName aname;
5676 MonoDomain *domain = mono_object_domain (name);
5678 gboolean is_version_defined;
5679 gboolean is_token_defined;
5681 aname.public_key = NULL;
5682 val = mono_string_to_utf8 (assname);
5683 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5684 g_free ((guint8*) aname.public_key);
5689 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined, FALSE, is_token_defined, &error);
5690 mono_error_set_pending_exception (&error);
5692 mono_assembly_name_free (&aname);
5693 g_free ((guint8*) aname.public_key);
5699 ICALL_EXPORT MonoReflectionType*
5700 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5703 MonoReflectionType *ret;
5704 MonoDomain *domain = mono_object_domain (module);
5707 g_assert (module->image);
5709 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5710 /* These images do not have a global type */
5713 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5714 if (!mono_error_ok (&error)) {
5715 mono_error_set_pending_exception (&error);
5719 ret = mono_type_get_object_checked (domain, &klass->byval_arg, &error);
5720 if (!mono_error_ok (&error)) {
5721 mono_error_set_pending_exception (&error);
5729 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5731 /*if (module->image)
5732 mono_image_close (module->image);*/
5735 ICALL_EXPORT MonoString*
5736 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5738 MonoDomain *domain = mono_object_domain (module);
5740 g_assert (module->image);
5741 return mono_string_new (domain, module->image->guid);
5744 ICALL_EXPORT gpointer
5745 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5748 if (module->image && module->image->is_module_handle)
5749 return module->image->raw_data;
5752 return (gpointer) (-1);
5756 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5758 if (image_is_dynamic (image)) {
5759 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5760 *pe_kind = dyn->pe_kind;
5761 *machine = dyn->machine;
5764 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5765 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5770 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5772 return (image->md_version_major << 16) | (image->md_version_minor);
5775 ICALL_EXPORT MonoArray*
5776 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5779 MonoArray *exceptions;
5783 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5787 res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE, &error);
5788 mono_error_raise_exception (&error);
5790 for (i = 0; i < mono_array_length (exceptions); ++i) {
5791 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5793 mono_set_pending_exception (ex);
5802 mono_memberref_is_method (MonoImage *image, guint32 token)
5804 if (!image_is_dynamic (image)) {
5805 guint32 cols [MONO_MEMBERREF_SIZE];
5807 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5808 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5809 mono_metadata_decode_blob_size (sig, &sig);
5810 return (*sig != 0x6);
5812 MonoClass *handle_class;
5814 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5817 return mono_defaults.methodhandle_class == handle_class;
5822 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5825 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5826 mono_array_addr (type_args, MonoType*, 0));
5828 context->class_inst = NULL;
5830 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5831 mono_array_addr (method_args, MonoType*, 0));
5833 context->method_inst = NULL;
5836 ICALL_EXPORT MonoType*
5837 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5840 int table = mono_metadata_token_table (token);
5841 int index = mono_metadata_token_index (token);
5842 MonoGenericContext context;
5845 *resolve_error = ResolveTokenError_Other;
5847 /* Validate token */
5848 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5849 (table != MONO_TABLE_TYPESPEC)) {
5850 *resolve_error = ResolveTokenError_BadTable;
5854 if (image_is_dynamic (image)) {
5855 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5856 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5857 return klass ? &klass->byval_arg : NULL;
5860 init_generic_context_from_args (&context, type_args, method_args);
5861 klass = (MonoClass *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5862 return klass ? &klass->byval_arg : NULL;
5865 if ((index <= 0) || (index > image->tables [table].rows)) {
5866 *resolve_error = ResolveTokenError_OutOfRange;
5870 init_generic_context_from_args (&context, type_args, method_args);
5871 klass = mono_class_get_checked (image, token, &error);
5873 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5874 if (!mono_error_ok (&error)) {
5875 mono_error_set_pending_exception (&error);
5880 return &klass->byval_arg;
5885 ICALL_EXPORT MonoMethod*
5886 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5889 int table = mono_metadata_token_table (token);
5890 int index = mono_metadata_token_index (token);
5891 MonoGenericContext context;
5894 *resolve_error = ResolveTokenError_Other;
5896 /* Validate token */
5897 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5898 (table != MONO_TABLE_MEMBERREF)) {
5899 *resolve_error = ResolveTokenError_BadTable;
5903 if (image_is_dynamic (image)) {
5904 if (table == MONO_TABLE_METHOD)
5905 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5907 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5908 *resolve_error = ResolveTokenError_BadTable;
5912 init_generic_context_from_args (&context, type_args, method_args);
5913 return (MonoMethod *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5916 if ((index <= 0) || (index > image->tables [table].rows)) {
5917 *resolve_error = ResolveTokenError_OutOfRange;
5920 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5921 *resolve_error = ResolveTokenError_BadTable;
5925 init_generic_context_from_args (&context, type_args, method_args);
5926 method = mono_get_method_checked (image, token, NULL, &context, &error);
5927 mono_error_set_pending_exception (&error);
5932 ICALL_EXPORT MonoString*
5933 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5935 int index = mono_metadata_token_index (token);
5937 *error = ResolveTokenError_Other;
5939 /* Validate token */
5940 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5941 *error = ResolveTokenError_BadTable;
5945 if (image_is_dynamic (image))
5946 return (MonoString *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5948 if ((index <= 0) || (index >= image->heap_us.size)) {
5949 *error = ResolveTokenError_OutOfRange;
5953 /* FIXME: What to do if the index points into the middle of a string ? */
5955 return mono_ldstr (mono_domain_get (), image, index);
5958 ICALL_EXPORT MonoClassField*
5959 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5963 int table = mono_metadata_token_table (token);
5964 int index = mono_metadata_token_index (token);
5965 MonoGenericContext context;
5966 MonoClassField *field;
5968 *resolve_error = ResolveTokenError_Other;
5970 /* Validate token */
5971 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5972 *resolve_error = ResolveTokenError_BadTable;
5976 if (image_is_dynamic (image)) {
5977 if (table == MONO_TABLE_FIELD)
5978 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5980 if (mono_memberref_is_method (image, token)) {
5981 *resolve_error = ResolveTokenError_BadTable;
5985 init_generic_context_from_args (&context, type_args, method_args);
5986 return (MonoClassField *)mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5989 if ((index <= 0) || (index > image->tables [table].rows)) {
5990 *resolve_error = ResolveTokenError_OutOfRange;
5993 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5994 *resolve_error = ResolveTokenError_BadTable;
5998 init_generic_context_from_args (&context, type_args, method_args);
5999 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
6000 mono_error_set_pending_exception (&error);
6006 ICALL_EXPORT MonoObject*
6007 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
6011 int table = mono_metadata_token_table (token);
6013 *error = ResolveTokenError_Other;
6016 case MONO_TABLE_TYPEDEF:
6017 case MONO_TABLE_TYPEREF:
6018 case MONO_TABLE_TYPESPEC: {
6019 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
6021 ret = (MonoObject*) mono_type_get_object_checked (mono_domain_get (), t, &merror);
6022 mono_error_raise_exception (&merror);
6029 case MONO_TABLE_METHOD:
6030 case MONO_TABLE_METHODSPEC: {
6031 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6033 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6034 mono_error_raise_exception (&merror);
6040 case MONO_TABLE_FIELD: {
6041 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6043 ret =(MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6044 mono_error_raise_exception (&merror);
6050 case MONO_TABLE_MEMBERREF:
6051 if (mono_memberref_is_method (image, token)) {
6052 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
6054 ret = (MonoObject*)mono_method_get_object_checked (mono_domain_get (), m, m->klass, &merror);
6055 mono_error_raise_exception (&merror);
6062 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
6064 ret = (MonoObject*)mono_field_get_object_checked (mono_domain_get (), f->parent, f, &merror);
6065 mono_error_raise_exception (&merror);
6074 *error = ResolveTokenError_BadTable;
6080 ICALL_EXPORT MonoArray*
6081 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
6083 int table = mono_metadata_token_table (token);
6084 int idx = mono_metadata_token_index (token);
6085 MonoTableInfo *tables = image->tables;
6090 *error = ResolveTokenError_OutOfRange;
6092 /* FIXME: Support other tables ? */
6093 if (table != MONO_TABLE_STANDALONESIG)
6096 if (image_is_dynamic (image))
6099 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
6102 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
6104 ptr = mono_metadata_blob_heap (image, sig);
6105 len = mono_metadata_decode_blob_size (ptr, &ptr);
6107 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
6108 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
6112 ICALL_EXPORT MonoReflectionType*
6113 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
6116 MonoReflectionType *ret;
6118 int isbyref = 0, rank;
6119 char *str = mono_string_to_utf8 (smodifiers);
6122 klass = mono_class_from_mono_type (tb->type.type);
6124 /* logic taken from mono_reflection_parse_type(): keep in sync */
6128 if (isbyref) { /* only one level allowed by the spec */
6137 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->this_arg, &error);
6138 mono_error_raise_exception (&error);
6142 klass = mono_ptr_class_get (&klass->byval_arg);
6143 mono_class_init (klass);
6154 else if (*p != '*') { /* '*' means unknown lower bound */
6165 klass = mono_array_class_get (klass, rank);
6166 mono_class_init (klass);
6175 ret = mono_type_get_object_checked (mono_object_domain (tb), &klass->byval_arg, &error);
6176 mono_error_raise_exception (&error);
6181 ICALL_EXPORT MonoBoolean
6182 ves_icall_RuntimeTypeHandle_IsArray (MonoReflectionType *t)
6188 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6194 check_for_invalid_type (MonoClass *klass, MonoError *error)
6199 mono_error_init (error);
6201 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
6204 name = mono_type_get_full_name (klass);
6205 str = mono_string_new (mono_domain_get (), name);
6207 mono_error_set_exception_instance (error, mono_get_exception_type_load (str, NULL));
6210 ICALL_EXPORT MonoReflectionType *
6211 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6214 MonoReflectionType *ret;
6215 MonoClass *klass, *aklass;
6217 klass = mono_class_from_mono_type (type->type);
6218 check_for_invalid_type (klass, &error);
6219 mono_error_raise_exception (&error);
6221 if (rank == 0) //single dimentional array
6222 aklass = mono_array_class_get (klass, 1);
6224 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6226 ret = mono_type_get_object_checked (mono_object_domain (type), &aklass->byval_arg, &error);
6227 mono_error_raise_exception (&error);
6232 ICALL_EXPORT MonoReflectionType *
6233 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6236 MonoReflectionType *ret;
6239 klass = mono_class_from_mono_type (type->type);
6240 mono_class_init_checked (klass, &error);
6241 mono_error_raise_exception (&error);
6242 check_for_invalid_type (klass, &error);
6243 mono_error_raise_exception (&error);
6245 ret = mono_type_get_object_checked (mono_object_domain (type), &klass->this_arg, &error);
6246 mono_error_raise_exception (&error);
6251 ICALL_EXPORT MonoReflectionType *
6252 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6255 MonoReflectionType *ret;
6256 MonoClass *klass, *pklass;
6258 klass = mono_class_from_mono_type (type->type);
6259 mono_class_init_checked (klass, &error);
6260 mono_error_raise_exception (&error);
6261 check_for_invalid_type (klass, &error);
6262 mono_error_raise_exception (&error);
6264 pklass = mono_ptr_class_get (type->type);
6266 ret = mono_type_get_object_checked (mono_object_domain (type), &pklass->byval_arg, &error);
6267 mono_error_raise_exception (&error);
6272 ICALL_EXPORT MonoObject *
6273 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6274 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6277 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6278 MonoObject *delegate;
6280 MonoMethod *method = info->method;
6282 mono_class_init_checked (delegate_class, &error);
6283 mono_error_raise_exception (&error);
6285 if (!(delegate_class->parent == mono_defaults.multicastdelegate_class)) {
6286 /* FIXME improve this exception message */
6287 mono_error_set_execution_engine (&error, "file %s: line %d (%s): assertion failed: (%s)", __FILE__, __LINE__,
6289 "delegate_class->parent == mono_defaults.multicastdelegate_class");
6290 mono_error_set_pending_exception (&error);
6294 if (mono_security_core_clr_enabled ()) {
6295 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6299 delegate = mono_object_new_checked (mono_object_domain (type), delegate_class, &error);
6300 mono_error_raise_exception (&error);
6302 if (method_is_dynamic (method)) {
6303 /* Creating a trampoline would leak memory */
6304 func = mono_compile_method (method);
6306 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
6307 method = mono_object_get_virtual_method (target, method);
6308 func = mono_create_ftnptr (mono_domain_get (),
6309 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6312 mono_delegate_ctor_with_method (delegate, target, func, method);
6317 ICALL_EXPORT MonoMulticastDelegate *
6318 ves_icall_System_Delegate_AllocDelegateLike_internal (MonoDelegate *delegate)
6321 MonoMulticastDelegate *ret;
6323 g_assert (mono_class_has_parent (mono_object_class (delegate), mono_defaults.multicastdelegate_class));
6325 ret = (MonoMulticastDelegate*) mono_object_new_checked (mono_object_domain (delegate), mono_object_class (delegate), &error);
6326 mono_error_raise_exception (&error);
6327 ret->delegate.invoke_impl = mono_runtime_create_delegate_trampoline (mono_object_class (delegate));
6332 ICALL_EXPORT MonoReflectionMethod*
6333 ves_icall_System_Delegate_GetVirtualMethod_internal (MonoDelegate *delegate)
6335 MonoReflectionMethod *ret = NULL;
6337 ret = mono_method_get_object_checked (mono_domain_get (), mono_object_get_virtual_method (delegate->target, delegate->method), mono_object_class (delegate->target), &error);
6338 mono_error_raise_exception (&error);
6344 static inline gint32
6345 mono_array_get_byte_length (MonoArray *array)
6351 klass = array->obj.vtable->klass;
6353 if (array->bounds == NULL)
6354 length = array->max_length;
6357 for (i = 0; i < klass->rank; ++ i)
6358 length *= array->bounds [i].length;
6361 switch (klass->element_class->byval_arg.type) {
6364 case MONO_TYPE_BOOLEAN:
6368 case MONO_TYPE_CHAR:
6376 return length * sizeof (gpointer);
6387 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6389 return mono_array_get_byte_length (array);
6393 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6395 return mono_array_get (array, gint8, idx);
6399 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6401 mono_array_set (array, gint8, idx, value);
6404 ICALL_EXPORT MonoBoolean
6405 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6407 guint8 *src_buf, *dest_buf;
6410 mono_set_pending_exception (mono_get_exception_argument ("count", "is negative"));
6414 g_assert (count >= 0);
6416 /* This is called directly from the class libraries without going through the managed wrapper */
6417 MONO_CHECK_ARG_NULL (src, FALSE);
6418 MONO_CHECK_ARG_NULL (dest, FALSE);
6420 /* watch out for integer overflow */
6421 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6424 src_buf = (guint8 *)src->vector + src_offset;
6425 dest_buf = (guint8 *)dest->vector + dest_offset;
6428 memcpy (dest_buf, src_buf, count);
6430 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6435 #ifndef DISABLE_REMOTING
6436 ICALL_EXPORT MonoObject *
6437 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this_obj, MonoString *class_name)
6440 MonoDomain *domain = mono_object_domain (this_obj);
6442 MonoRealProxy *rp = ((MonoRealProxy *)this_obj);
6443 MonoTransparentProxy *tp;
6447 res = mono_object_new_checked (domain, mono_defaults.transparent_proxy_class, &error);
6448 mono_error_raise_exception (&error);
6449 tp = (MonoTransparentProxy*) res;
6451 MONO_OBJECT_SETREF (tp, rp, rp);
6452 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6453 klass = mono_class_from_mono_type (type);
6455 // mono_remote_class_vtable cannot handle errors well, so force any loading error to occur early
6456 mono_class_setup_vtable (klass);
6457 if (mono_class_has_failure (klass)) {
6458 mono_set_pending_exception (mono_class_get_exception_for_failure (klass));
6462 tp->custom_type_info = (mono_object_isinst (this_obj, mono_defaults.iremotingtypeinfo_class) != NULL);
6463 tp->remote_class = mono_remote_class (domain, class_name, klass, &error);
6464 if (!is_ok (&error)) {
6465 mono_error_set_pending_exception (&error);
6469 res->vtable = (MonoVTable *)mono_remote_class_vtable (domain, tp->remote_class, rp);
6473 ICALL_EXPORT MonoReflectionType *
6474 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6477 MonoReflectionType *ret = mono_type_get_object_checked (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg, &error);
6478 mono_error_raise_exception (&error);
6484 /* System.Environment */
6487 ves_icall_System_Environment_get_UserName (void)
6489 /* using glib is more portable */
6490 return mono_string_new (mono_domain_get (), g_get_user_name ());
6494 ICALL_EXPORT MonoString *
6495 ves_icall_System_Environment_get_MachineName (void)
6497 #if defined (HOST_WIN32)
6502 len = MAX_COMPUTERNAME_LENGTH + 1;
6503 buf = g_new (gunichar2, len);
6506 if (GetComputerName (buf, (PDWORD) &len)) {
6508 result = mono_string_new_utf16_checked (mono_domain_get (), buf, len, &error);
6509 mono_error_raise_exception (&error);
6514 #elif !defined(DISABLE_SOCKETS)
6518 #if defined _SC_HOST_NAME_MAX
6519 n = sysconf (_SC_HOST_NAME_MAX);
6523 buf = g_malloc (n+1);
6525 if (gethostname (buf, n) == 0){
6527 result = mono_string_new (mono_domain_get (), buf);
6534 return mono_string_new (mono_domain_get (), "mono");
6539 ves_icall_System_Environment_get_Platform (void)
6541 #if defined (TARGET_WIN32)
6544 #elif defined(__MACH__)
6547 // Notice that the value is hidden from user code, and only exposed
6548 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6549 // define and making assumptions based on Unix/128/4 values before there
6550 // was a MacOS define. Lots of code would assume that not-Unix meant
6551 // Windows, but in this case, it would be OSX.
6560 ICALL_EXPORT MonoString *
6561 ves_icall_System_Environment_get_NewLine (void)
6563 #if defined (HOST_WIN32)
6564 return mono_string_new (mono_domain_get (), "\r\n");
6566 return mono_string_new (mono_domain_get (), "\n");
6570 ICALL_EXPORT MonoBoolean
6571 ves_icall_System_Environment_GetIs64BitOperatingSystem (void)
6573 #if SIZEOF_VOID_P == 8
6577 gboolean isWow64Process = FALSE;
6578 if (IsWow64Process (GetCurrentProcess (), &isWow64Process)) {
6579 return (MonoBoolean)isWow64Process;
6581 #elif defined(HAVE_SYS_UTSNAME_H)
6582 struct utsname name;
6584 if (uname (&name) >= 0) {
6585 return strcmp (name.machine, "x86_64") == 0 || strncmp (name.machine, "aarch64", 7) == 0 || strncmp (name.machine, "ppc64", 5) == 0;
6592 ICALL_EXPORT MonoString *
6593 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6601 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6602 value = g_getenv (utf8_name);
6609 return mono_string_new (mono_domain_get (), value);
6613 * There is no standard way to get at environ.
6616 #ifndef __MINGW32_VERSION
6617 #if defined(__APPLE__)
6618 #if defined (TARGET_OSX)
6619 /* Apple defines this in crt_externs.h but doesn't provide that header for
6620 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6621 * in fact exist on all implementations (so far)
6623 gchar ***_NSGetEnviron(void);
6624 #define environ (*_NSGetEnviron())
6626 static char *mono_environ[1] = { NULL };
6627 #define environ mono_environ
6628 #endif /* defined (TARGET_OSX) */
6636 ICALL_EXPORT MonoArray *
6637 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6648 env_strings = GetEnvironmentStrings();
6651 env_string = env_strings;
6652 while (*env_string != '\0') {
6653 /* weird case that MS seems to skip */
6654 if (*env_string != '=')
6656 while (*env_string != '\0')
6662 domain = mono_domain_get ();
6663 names = mono_array_new (domain, mono_defaults.string_class, n);
6667 env_string = env_strings;
6668 while (*env_string != '\0') {
6669 /* weird case that MS seems to skip */
6670 if (*env_string != '=') {
6671 equal_str = wcschr(env_string, '=');
6672 g_assert(equal_str);
6674 str = mono_string_new_utf16_checked (domain, env_string, equal_str-env_string, &error);
6675 mono_error_raise_exception (&error);
6676 mono_array_setref (names, n, str);
6679 while (*env_string != '\0')
6684 FreeEnvironmentStrings (env_strings);
6697 for (e = environ; *e != 0; ++ e)
6700 domain = mono_domain_get ();
6701 names = mono_array_new (domain, mono_defaults.string_class, n);
6704 for (e = environ; *e != 0; ++ e) {
6705 parts = g_strsplit (*e, "=", 2);
6707 str = mono_string_new (domain, *parts);
6708 mono_array_setref (names, n, str);
6721 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6723 #if !GLIB_CHECK_VERSION(2,4,0)
6724 #define g_setenv(a,b,c) setenv(a,b,c)
6725 #define g_unsetenv(a) unsetenv(a)
6729 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6732 gunichar2 *utf16_name, *utf16_value;
6734 gchar *utf8_name, *utf8_value;
6739 utf16_name = mono_string_to_utf16 (name);
6740 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6741 SetEnvironmentVariable (utf16_name, NULL);
6742 g_free (utf16_name);
6746 utf16_value = mono_string_to_utf16 (value);
6748 SetEnvironmentVariable (utf16_name, utf16_value);
6750 g_free (utf16_name);
6751 g_free (utf16_value);
6753 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6755 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6756 g_unsetenv (utf8_name);
6761 utf8_value = mono_string_to_utf8_checked (value, &error);
6762 if (!mono_error_ok (&error)) {
6764 mono_error_set_pending_exception (&error);
6767 g_setenv (utf8_name, utf8_value, TRUE);
6770 g_free (utf8_value);
6775 ves_icall_System_Environment_Exit (int result)
6777 mono_environment_exitcode_set (result);
6779 /* FIXME: There are some cleanup hangs that should be worked out, but
6780 * if the program is going to exit, everything will be cleaned up when
6781 * NaCl exits anyway.
6783 #ifndef __native_client__
6784 if (!mono_runtime_try_shutdown ())
6785 mono_thread_exit ();
6787 /* Suspend all managed threads since the runtime is going away */
6788 mono_thread_suspend_all_other_threads ();
6790 mono_runtime_quit ();
6793 /* we may need to do some cleanup here... */
6797 ICALL_EXPORT MonoString*
6798 ves_icall_System_Environment_GetGacPath (void)
6800 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6803 ICALL_EXPORT MonoString*
6804 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6806 #if defined (HOST_WIN32)
6807 #ifndef CSIDL_FLAG_CREATE
6808 #define CSIDL_FLAG_CREATE 0x8000
6811 WCHAR path [MAX_PATH];
6812 /* Create directory if no existing */
6813 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6818 MonoString *res = mono_string_new_utf16_checked (mono_domain_get (), path, len, &error);
6819 mono_error_raise_exception (&error);
6823 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6825 return mono_string_new (mono_domain_get (), "");
6828 ICALL_EXPORT MonoArray *
6829 ves_icall_System_Environment_GetLogicalDrives (void)
6832 gunichar2 buf [256], *ptr, *dname;
6834 guint initial_size = 127, size = 128;
6837 MonoString *drivestr;
6838 MonoDomain *domain = mono_domain_get ();
6844 while (size > initial_size) {
6845 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6846 if (size > initial_size) {
6849 ptr = (gunichar2 *)g_malloc0 ((size + 1) * sizeof (gunichar2));
6850 initial_size = size;
6864 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6869 while (*u16) { u16++; len ++; }
6870 drivestr = mono_string_new_utf16_checked (domain, dname, len, &error);
6871 mono_error_raise_exception (&error);
6872 mono_array_setref (result, ndrives++, drivestr);
6882 ICALL_EXPORT MonoString *
6883 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6885 gunichar2 volume_name [MAX_PATH + 1];
6887 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6889 return mono_string_from_utf16 (volume_name);
6892 ICALL_EXPORT MonoString *
6893 ves_icall_System_Environment_InternalGetHome (void)
6895 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6898 static const char *encodings [] = {
6900 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6901 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6902 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6904 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6905 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6906 "x_unicode_2_0_utf_7",
6908 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6909 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6911 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6914 "unicodefffe", "utf_16be",
6921 * Returns the internal codepage, if the value of "int_code_page" is
6922 * 1 at entry, and we can not compute a suitable code page number,
6923 * returns the code page as a string
6925 ICALL_EXPORT MonoString*
6926 ves_icall_System_Text_EncodingHelper_InternalCodePage (gint32 *int_code_page)
6931 char *codepage = NULL;
6933 int want_name = *int_code_page;
6936 *int_code_page = -1;
6938 g_get_charset (&cset);
6939 c = codepage = strdup (cset);
6940 for (c = codepage; *c; c++){
6941 if (isascii (*c) && isalpha (*c))
6946 /* g_print ("charset: %s\n", cset); */
6948 /* handle some common aliases */
6951 for (i = 0; p != 0; ){
6954 p = encodings [++i];
6957 if (strcmp (p, codepage) == 0){
6958 *int_code_page = code;
6961 p = encodings [++i];
6964 if (strstr (codepage, "utf_8") != NULL)
6965 *int_code_page |= 0x10000000;
6968 if (want_name && *int_code_page == -1)
6969 return mono_string_new (mono_domain_get (), cset);
6974 ICALL_EXPORT MonoBoolean
6975 ves_icall_System_Environment_get_HasShutdownStarted (void)
6977 if (mono_runtime_is_shutting_down ())
6980 if (mono_domain_is_unloading (mono_domain_get ()))
6987 ves_icall_System_Environment_BroadcastSettingChange (void)
6990 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6995 ves_icall_System_Runtime_Versioning_VersioningHelper_GetRuntimeId (void)
7001 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this_obj,
7002 MonoReflectionMethod *method,
7003 MonoArray *out_args)
7005 mono_message_init (mono_object_domain (this_obj), this_obj, method, out_args);
7008 #ifndef DISABLE_REMOTING
7009 ICALL_EXPORT MonoBoolean
7010 ves_icall_IsTransparentProxy (MonoObject *proxy)
7015 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
7021 ICALL_EXPORT MonoReflectionMethod *
7022 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
7023 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
7025 MonoReflectionMethod *ret = NULL;
7030 MonoMethod **vtable;
7031 MonoMethod *res = NULL;
7033 MONO_CHECK_ARG_NULL (rtype, NULL);
7034 MONO_CHECK_ARG_NULL (rmethod, NULL);
7036 method = rmethod->method;
7037 klass = mono_class_from_mono_type (rtype->type);
7038 mono_class_init_checked (klass, &error);
7039 mono_error_raise_exception (&error);
7041 if (MONO_CLASS_IS_INTERFACE (klass))
7044 if (method->flags & METHOD_ATTRIBUTE_STATIC)
7047 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
7048 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
7054 mono_class_setup_vtable (klass);
7055 vtable = klass->vtable;
7057 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
7058 gboolean variance_used = FALSE;
7059 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
7060 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
7062 res = vtable [offs + method->slot];
7064 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
7067 if (method->slot != -1)
7068 res = vtable [method->slot];
7074 ret = mono_method_get_object_checked (mono_domain_get (), res, NULL, &error);
7075 mono_error_raise_exception (&error);
7080 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7086 klass = mono_class_from_mono_type (type->type);
7087 vtable = mono_class_vtable_full (mono_domain_get (), klass, &error);
7088 if (!is_ok (&error)) {
7089 mono_error_set_pending_exception (&error);
7093 mono_vtable_set_is_remote (vtable, enable);
7096 #else /* DISABLE_REMOTING */
7099 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7101 g_assert_not_reached ();
7106 ICALL_EXPORT MonoObject *
7107 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7114 domain = mono_object_domain (type);
7115 klass = mono_class_from_mono_type (type->type);
7116 mono_class_init_checked (klass, &error);
7117 mono_error_raise_exception (&error);
7119 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT)) {
7120 mono_set_pending_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
7124 if (klass->rank >= 1) {
7125 g_assert (klass->rank == 1);
7126 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7128 MonoVTable *vtable = mono_class_vtable_full (domain, klass, &error);
7129 if (!is_ok (&error)) {
7130 mono_error_set_pending_exception (&error);
7133 /* Bypass remoting object creation check */
7134 ret = mono_object_new_alloc_specific_checked (vtable, &error);
7135 mono_error_set_pending_exception (&error);
7141 ICALL_EXPORT MonoString *
7142 ves_icall_System_IO_get_temp_path (void)
7144 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7147 #ifndef PLATFORM_NO_DRIVEINFO
7148 ICALL_EXPORT MonoBoolean
7149 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7150 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7154 ULARGE_INTEGER wapi_free_bytes_avail;
7155 ULARGE_INTEGER wapi_total_number_of_bytes;
7156 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7158 *error = ERROR_SUCCESS;
7159 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7160 &wapi_total_number_of_free_bytes);
7163 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7164 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7165 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7167 *free_bytes_avail = 0;
7168 *total_number_of_bytes = 0;
7169 *total_number_of_free_bytes = 0;
7170 *error = GetLastError ();
7176 ICALL_EXPORT guint32
7177 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7179 return GetDriveType (mono_string_chars (root_path_name));
7183 ICALL_EXPORT gpointer
7184 ves_icall_RuntimeMethodHandle_GetFunctionPointer (MonoMethod *method)
7186 return mono_compile_method (method);
7189 ICALL_EXPORT MonoString *
7190 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7195 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7197 #if defined (HOST_WIN32)
7198 /* Avoid mixing '/' and '\\' */
7201 for (i = strlen (path) - 1; i >= 0; i--)
7202 if (path [i] == '/')
7206 mcpath = mono_string_new (mono_domain_get (), path);
7213 get_bundled_app_config (void)
7215 const gchar *app_config;
7218 gchar *config_file_name, *config_file_path;
7219 gsize len, config_file_path_length, config_ext_length;
7222 domain = mono_domain_get ();
7223 file = domain->setup->configuration_file;
7224 if (!file || file->length == 0)
7227 // Retrieve config file and remove the extension
7228 config_file_name = mono_string_to_utf8 (file);
7229 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7230 if (!config_file_path)
7231 config_file_path = config_file_name;
7233 config_file_path_length = strlen (config_file_path);
7234 config_ext_length = strlen (".config");
7235 if (config_file_path_length <= config_ext_length)
7238 len = config_file_path_length - config_ext_length;
7239 module = (gchar *)g_malloc0 (len + 1);
7240 memcpy (module, config_file_path, len);
7241 // Get the config file from the module name
7242 app_config = mono_config_string_for_assembly_file (module);
7245 if (config_file_name != config_file_path)
7246 g_free (config_file_name);
7247 g_free (config_file_path);
7252 return mono_string_new (mono_domain_get (), app_config);
7256 get_bundled_machine_config (void)
7258 const gchar *machine_config;
7260 machine_config = mono_get_machine_config ();
7262 if (!machine_config)
7265 return mono_string_new (mono_domain_get (), machine_config);
7268 ICALL_EXPORT MonoString *
7269 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7274 path = g_path_get_dirname (mono_get_config_dir ());
7276 #if defined (HOST_WIN32)
7277 /* Avoid mixing '/' and '\\' */
7280 for (i = strlen (path) - 1; i >= 0; i--)
7281 if (path [i] == '/')
7285 ipath = mono_string_new (mono_domain_get (), path);
7291 ICALL_EXPORT gboolean
7292 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7294 MonoPEResourceDataEntry *entry;
7297 if (!assembly || !result || !size)
7302 image = assembly->assembly->image;
7303 entry = (MonoPEResourceDataEntry *)mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7307 *result = mono_image_rva_map (image, entry->rde_data_offset);
7312 *size = entry->rde_size;
7317 ICALL_EXPORT MonoBoolean
7318 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7320 return mono_is_debugger_attached ();
7323 ICALL_EXPORT MonoBoolean
7324 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7326 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7327 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7333 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7335 if (mono_get_runtime_callbacks ()->debug_log)
7336 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7340 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7342 #if defined (HOST_WIN32)
7343 OutputDebugString (mono_string_chars (message));
7345 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7349 /* Only used for value types */
7350 ICALL_EXPORT MonoObject *
7351 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7358 domain = mono_object_domain (type);
7359 klass = mono_class_from_mono_type (type->type);
7360 mono_class_init_checked (klass, &error);
7361 mono_error_raise_exception (&error);
7363 if (mono_class_is_nullable (klass))
7364 /* No arguments -> null */
7367 result = mono_object_new_checked (domain, klass, &error);
7368 mono_error_raise_exception (&error);
7372 ICALL_EXPORT MonoReflectionMethod *
7373 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7375 MonoReflectionMethod *ret = NULL;
7378 MonoClass *klass, *parent;
7379 MonoGenericContext *generic_inst = NULL;
7380 MonoMethod *method = m->method;
7381 MonoMethod *result = NULL;
7384 if (method->klass == NULL)
7387 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7388 MONO_CLASS_IS_INTERFACE (method->klass) ||
7389 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7392 slot = mono_method_get_vtable_slot (method);
7396 klass = method->klass;
7397 if (klass->generic_class) {
7398 generic_inst = mono_class_get_context (klass);
7399 klass = klass->generic_class->container_class;
7403 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7404 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7405 /* on entry, klass is either a plain old non-generic class and generic_inst == NULL
7406 or klass is the generic container class and generic_inst is the instantiation.
7408 when we go to the parent, if the parent is an open constructed type, we need to
7409 replace the type parameters by the definitions from the generic_inst, and then take it
7410 apart again into the klass and the generic_inst.
7412 For cases like this:
7413 class C<T> : B<T, int> {
7414 public override void Foo () { ... }
7416 class B<U,V> : A<HashMap<U,V>> {
7417 public override void Foo () { ... }
7420 public virtual void Foo () { ... }
7423 if at each iteration the parent isn't open, we can skip inflating it. if at some
7424 iteration the parent isn't generic (after possible inflation), we set generic_inst to
7427 MonoGenericContext *parent_inst = NULL;
7428 if (mono_class_is_open_constructed_type (mono_class_get_type (parent))) {
7430 parent = mono_class_inflate_generic_class_checked (parent, generic_inst, &error);
7431 if (!mono_error_ok (&error)) {
7432 mono_error_set_pending_exception (&error);
7436 if (parent->generic_class) {
7437 parent_inst = mono_class_get_context (parent);
7438 parent = parent->generic_class->container_class;
7441 mono_class_setup_vtable (parent);
7442 if (parent->vtable_size <= slot)
7445 generic_inst = parent_inst;
7448 klass = klass->parent;
7451 if (mono_class_is_open_constructed_type (mono_class_get_type (klass))) {
7452 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7453 if (!mono_error_ok (&error)) {
7454 mono_error_set_pending_exception (&error);
7458 generic_inst = NULL;
7460 if (klass->generic_class) {
7461 generic_inst = mono_class_get_context (klass);
7462 klass = klass->generic_class->container_class;
7468 klass = mono_class_inflate_generic_class_checked (klass, generic_inst, &error);
7469 if (!mono_error_ok (&error)) {
7470 mono_error_set_pending_exception (&error);
7475 if (klass == method->klass)
7478 /*This is possible if definition == FALSE.
7479 * Do it here to be really sure we don't read invalid memory.
7481 if (slot >= klass->vtable_size)
7484 mono_class_setup_vtable (klass);
7486 result = klass->vtable [slot];
7487 if (result == NULL) {
7488 /* It is an abstract method */
7489 gpointer iter = NULL;
7490 while ((result = mono_class_get_methods (klass, &iter)))
7491 if (result->slot == slot)
7498 ret = mono_method_get_object_checked (mono_domain_get (), result, NULL, &error);
7499 mono_error_raise_exception (&error);
7503 ICALL_EXPORT MonoString*
7504 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7506 MonoMethod *method = m->method;
7508 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7513 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7515 iter->sig = *(MonoMethodSignature**)argsp;
7517 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7518 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7521 /* FIXME: it's not documented what start is exactly... */
7525 iter->args = argsp + sizeof (gpointer);
7527 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7529 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7532 ICALL_EXPORT MonoTypedRef
7533 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7535 guint32 i, arg_size;
7539 i = iter->sig->sentinelpos + iter->next_arg;
7541 g_assert (i < iter->sig->param_count);
7543 res.type = iter->sig->params [i];
7544 res.klass = mono_class_from_mono_type (res.type);
7545 arg_size = mono_type_stack_size (res.type, &align);
7546 #if defined(__arm__) || defined(__mips__)
7547 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7549 res.value = iter->args;
7550 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7551 /* Values are stored as 8 byte register sized objects, but 'value'
7552 * is dereferenced as a pointer in other routines.
7554 res.value = (char*)res.value + 4;
7556 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7557 if (arg_size <= sizeof (gpointer)) {
7559 int padding = arg_size - mono_type_size (res.type, &dummy);
7560 res.value = (guint8*)res.value + padding;
7563 iter->args = (char*)iter->args + arg_size;
7566 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7571 ICALL_EXPORT MonoTypedRef
7572 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7574 guint32 i, arg_size;
7578 i = iter->sig->sentinelpos + iter->next_arg;
7580 g_assert (i < iter->sig->param_count);
7582 while (i < iter->sig->param_count) {
7583 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7585 res.type = iter->sig->params [i];
7586 res.klass = mono_class_from_mono_type (res.type);
7587 /* FIXME: endianess issue... */
7588 arg_size = mono_type_stack_size (res.type, &align);
7589 #if defined(__arm__) || defined(__mips__)
7590 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7592 res.value = iter->args;
7593 iter->args = (char*)iter->args + arg_size;
7595 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7598 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7606 ICALL_EXPORT MonoType*
7607 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7611 i = iter->sig->sentinelpos + iter->next_arg;
7613 g_assert (i < iter->sig->param_count);
7615 return iter->sig->params [i];
7618 ICALL_EXPORT MonoObject*
7619 mono_TypedReference_ToObject (MonoTypedRef* tref)
7622 MonoObject *result = NULL;
7623 if (MONO_TYPE_IS_REFERENCE (tref->type)) {
7624 MonoObject** objp = (MonoObject **)tref->value;
7628 result = mono_value_box_checked (mono_domain_get (), tref->klass, tref->value, &error);
7629 mono_error_set_pending_exception (&error);
7633 ICALL_EXPORT MonoTypedRef
7634 mono_TypedReference_MakeTypedReferenceInternal (MonoObject *target, MonoArray *fields)
7637 MonoReflectionField *f;
7639 MonoType *ftype = NULL;
7643 memset (&res, 0, sizeof (res));
7646 g_assert (mono_array_length (fields) > 0);
7648 klass = target->vtable->klass;
7650 for (i = 0; i < mono_array_length (fields); ++i) {
7651 f = mono_array_get (fields, MonoReflectionField*, i);
7653 mono_set_pending_exception (mono_get_exception_argument_null ("field"));
7656 if (f->field->parent != klass) {
7657 mono_set_pending_exception (mono_get_exception_argument ("field", ""));
7661 p = (guint8*)target + f->field->offset;
7663 p += f->field->offset - sizeof (MonoObject);
7664 klass = mono_class_from_mono_type (f->field->type);
7665 ftype = f->field->type;
7669 res.klass = mono_class_from_mono_type (ftype);
7676 prelink_method (MonoMethod *method, MonoError *error)
7678 const char *exc_class, *exc_arg;
7680 mono_error_init (error);
7681 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7683 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7685 mono_error_set_exception_instance (error,
7686 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg));
7689 /* create the wrapper, too? */
7693 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7697 prelink_method (method->method, &error);
7698 mono_error_raise_exception (&error);
7702 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7705 MonoClass *klass = mono_class_from_mono_type (type->type);
7707 gpointer iter = NULL;
7709 mono_class_init_checked (klass, &error);
7710 mono_error_raise_exception (&error);
7712 while ((m = mono_class_get_methods (klass, &iter))) {
7713 prelink_method (m, &error);
7714 mono_error_raise_exception (&error);
7718 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7720 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7721 gint32 const **exponents,
7722 gunichar2 const **digitLowerTable,
7723 gunichar2 const **digitUpperTable,
7724 gint64 const **tenPowersList,
7725 gint32 const **decHexDigits)
7727 *mantissas = Formatter_MantissaBitsTable;
7728 *exponents = Formatter_TensExponentTable;
7729 *digitLowerTable = Formatter_DigitLowerTable;
7730 *digitUpperTable = Formatter_DigitUpperTable;
7731 *tenPowersList = Formatter_TenPowersList;
7732 *decHexDigits = Formatter_DecHexDigits;
7736 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7737 * and avoid useless allocations.
7740 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional, MonoError *error)
7742 MonoReflectionType *rt;
7746 mono_error_init (error);
7747 for (i = 0; i < type->num_mods; ++i) {
7748 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7753 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7755 for (i = 0; i < type->num_mods; ++i) {
7756 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7757 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, error);
7758 return_val_if_nok (error, NULL);
7760 rt = mono_type_get_object_checked (mono_domain_get (), &klass->byval_arg, error);
7761 return_val_if_nok (error, NULL);
7763 mono_array_setref (res, count, rt);
7770 ICALL_EXPORT MonoArray*
7771 ves_icall_ParameterInfo_GetTypeModifiers (MonoReflectionParameter *param, MonoBoolean optional)
7774 MonoType *type = param->ClassImpl->type;
7775 MonoClass *member_class = mono_object_class (param->MemberImpl);
7776 MonoMethod *method = NULL;
7779 MonoMethodSignature *sig;
7782 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7783 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7784 method = rmethod->method;
7785 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7786 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7787 if (!(method = prop->property->get))
7788 method = prop->property->set;
7791 char *type_name = mono_type_get_full_name (member_class);
7792 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7793 MonoException *ex = mono_get_exception_not_supported (msg);
7796 mono_set_pending_exception (ex);
7800 image = method->klass->image;
7801 pos = param->PositionImpl;
7802 sig = mono_method_signature (method);
7806 type = sig->params [pos];
7808 res = type_array_from_modifiers (image, type, optional, &error);
7809 mono_error_raise_exception (&error);
7814 get_property_type (MonoProperty *prop)
7816 MonoMethodSignature *sig;
7818 sig = mono_method_signature (prop->get);
7820 } else if (prop->set) {
7821 sig = mono_method_signature (prop->set);
7822 return sig->params [sig->param_count - 1];
7827 ICALL_EXPORT MonoArray*
7828 ves_icall_MonoPropertyInfo_GetTypeModifiers (MonoReflectionProperty *property, MonoBoolean optional)
7831 MonoType *type = get_property_type (property->property);
7832 MonoImage *image = property->klass->image;
7837 res = type_array_from_modifiers (image, type, optional, &error);
7838 mono_error_raise_exception (&error);
7843 *Construct a MonoType suited to be used to decode a constant blob object.
7845 * @type is the target type which will be constructed
7846 * @blob_type is the blob type, for example, that comes from the constant table
7847 * @real_type is the expected constructed type.
7850 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7852 type->type = blob_type;
7853 type->data.klass = NULL;
7854 if (blob_type == MONO_TYPE_CLASS)
7855 type->data.klass = mono_defaults.object_class;
7856 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7857 /* For enums, we need to use the base type */
7858 type->type = MONO_TYPE_VALUETYPE;
7859 type->data.klass = mono_class_from_mono_type (real_type);
7861 type->data.klass = mono_class_from_mono_type (real_type);
7864 ICALL_EXPORT MonoObject*
7865 property_info_get_default_value (MonoReflectionProperty *property)
7869 MonoProperty *prop = property->property;
7870 MonoType *type = get_property_type (prop);
7871 MonoDomain *domain = mono_object_domain (property);
7872 MonoTypeEnum def_type;
7873 const char *def_value;
7876 mono_class_init (prop->parent);
7878 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT)) {
7879 mono_set_pending_exception (mono_get_exception_invalid_operation (NULL));
7883 def_value = mono_class_get_property_default_value (prop, &def_type);
7885 mono_type_from_blob_type (&blob_type, def_type, type);
7886 o = mono_get_object_from_blob (domain, &blob_type, def_value, &error);
7888 mono_error_set_pending_exception (&error);
7892 ICALL_EXPORT MonoBoolean
7893 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7896 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7897 MonoCustomAttrInfo *cinfo;
7900 mono_class_init_checked (attr_class, &error);
7901 mono_error_raise_exception (&error);
7903 cinfo = mono_reflection_get_custom_attrs_info_checked (obj, &error);
7904 if (!is_ok (&error)) {
7905 mono_error_set_pending_exception (&error);
7910 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7912 mono_custom_attrs_free (cinfo);
7916 ICALL_EXPORT MonoArray*
7917 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7919 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7924 mono_class_init_checked (attr_class, &error);
7925 mono_error_raise_exception (&error);
7928 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7929 if (!mono_error_ok (&error)) {
7930 mono_error_set_pending_exception (&error);
7934 if (mono_loader_get_last_error ()) {
7935 mono_set_pending_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7942 ICALL_EXPORT MonoArray*
7943 ves_icall_MonoCustomAttrs_GetCustomAttributesDataInternal (MonoObject *obj)
7947 result = mono_reflection_get_custom_attrs_data_checked (obj, &error);
7948 mono_error_set_pending_exception (&error);
7953 ICALL_EXPORT MonoString*
7954 ves_icall_Mono_Runtime_GetDisplayName (void)
7957 MonoString *display_name;
7959 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7960 display_name = mono_string_new (mono_domain_get (), info);
7962 return display_name;
7965 ICALL_EXPORT MonoString*
7966 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7969 MonoString *message;
7973 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7974 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7977 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7979 message = mono_string_new_utf16_checked (mono_domain_get (), buf, ret, &error);
7980 mono_error_raise_exception (&error);
7987 ves_icall_System_StackFrame_GetILOffsetFromFile (MonoString *path, guint32 method_token, guint32 method_index, int native_offset)
7990 char *path_str = mono_string_to_utf8 (path);
7992 if (!mono_seq_point_data_get_il_offset (path_str, method_token, method_index, native_offset, &il_offset))
8000 ICALL_EXPORT gpointer
8001 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcess (void)
8003 return GetCurrentProcess ();
8006 ICALL_EXPORT MonoBoolean
8007 ves_icall_Microsoft_Win32_NativeMethods_GetExitCodeProcess (gpointer handle, gint32 *exitcode)
8009 return GetExitCodeProcess (handle, (guint32*) exitcode);
8012 ICALL_EXPORT MonoBoolean
8013 ves_icall_Microsoft_Win32_NativeMethods_CloseProcess (gpointer handle)
8015 #if defined(TARGET_WIN32) || defined(HOST_WIN32)
8016 return CloseHandle (handle);
8018 return CloseProcess (handle);
8022 ICALL_EXPORT MonoBoolean
8023 ves_icall_Microsoft_Win32_NativeMethods_TerminateProcess (gpointer handle, gint32 exitcode)
8025 return TerminateProcess (handle, exitcode);
8029 ves_icall_Microsoft_Win32_NativeMethods_WaitForInputIdle (gpointer handle, gint32 milliseconds)
8031 return WaitForInputIdle (handle, milliseconds);
8034 ICALL_EXPORT MonoBoolean
8035 ves_icall_Microsoft_Win32_NativeMethods_GetProcessWorkingSetSize (gpointer handle, gsize *min, gsize *max)
8037 return GetProcessWorkingSetSize (handle, min, max);
8040 ICALL_EXPORT MonoBoolean
8041 ves_icall_Microsoft_Win32_NativeMethods_SetProcessWorkingSetSize (gpointer handle, gsize min, gsize max)
8043 return SetProcessWorkingSetSize (handle, min, max);
8046 ICALL_EXPORT MonoBoolean
8047 ves_icall_Microsoft_Win32_NativeMethods_GetProcessTimes (gpointer handle, gint64 *creationtime, gint64 *exittime, gint64 *kerneltime, gint64 *usertime)
8049 return GetProcessTimes (handle, (LPFILETIME) creationtime, (LPFILETIME) exittime, (LPFILETIME) kerneltime, (LPFILETIME) usertime);
8053 ves_icall_Microsoft_Win32_NativeMethods_GetCurrentProcessId (void)
8055 return mono_process_current_pid ();
8059 ves_icall_Microsoft_Win32_NativeMethods_GetPriorityClass (gpointer handle)
8061 return GetPriorityClass (handle);
8064 ICALL_EXPORT MonoBoolean
8065 ves_icall_Microsoft_Win32_NativeMethods_SetPriorityClass (gpointer handle, gint32 priorityClass)
8067 return SetPriorityClass (handle, priorityClass);
8070 #ifndef DISABLE_ICALL_TABLES
8072 #define ICALL_TYPE(id,name,first)
8073 #define ICALL(id,name,func) Icall_ ## id,
8076 #include "metadata/icall-def.h"
8082 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
8083 #define ICALL(id,name,func)
8085 #include "metadata/icall-def.h"
8091 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
8092 #define ICALL(id,name,func)
8094 guint16 first_icall;
8097 static const IcallTypeDesc
8098 icall_type_descs [] = {
8099 #include "metadata/icall-def.h"
8103 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
8106 #define ICALL_TYPE(id,name,first)
8109 #ifdef HAVE_ARRAY_ELEM_INIT
8110 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
8111 #define MSGSTRFIELD1(line) str##line
8113 static const struct msgstrtn_t {
8114 #define ICALL(id,name,func)
8116 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8117 #include "metadata/icall-def.h"
8119 } icall_type_names_str = {
8120 #define ICALL_TYPE(id,name,first) (name),
8121 #include "metadata/icall-def.h"
8124 static const guint16 icall_type_names_idx [] = {
8125 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
8126 #include "metadata/icall-def.h"
8129 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
8131 static const struct msgstr_t {
8133 #define ICALL_TYPE(id,name,first)
8134 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
8135 #include "metadata/icall-def.h"
8137 } icall_names_str = {
8138 #define ICALL(id,name,func) (name),
8139 #include "metadata/icall-def.h"
8142 static const guint16 icall_names_idx [] = {
8143 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
8144 #include "metadata/icall-def.h"
8147 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
8153 #define ICALL_TYPE(id,name,first) name,
8154 #define ICALL(id,name,func)
8155 static const char* const
8156 icall_type_names [] = {
8157 #include "metadata/icall-def.h"
8161 #define icall_type_name_get(id) (icall_type_names [(id)])
8165 #define ICALL_TYPE(id,name,first)
8166 #define ICALL(id,name,func) name,
8167 static const char* const
8169 #include "metadata/icall-def.h"
8172 #define icall_name_get(id) icall_names [(id)]
8174 #endif /* !HAVE_ARRAY_ELEM_INIT */
8178 #define ICALL_TYPE(id,name,first)
8179 #define ICALL(id,name,func) func,
8180 static const gconstpointer
8181 icall_functions [] = {
8182 #include "metadata/icall-def.h"
8186 #ifdef ENABLE_ICALL_SYMBOL_MAP
8189 #define ICALL_TYPE(id,name,first)
8190 #define ICALL(id,name,func) #func,
8191 static const gconstpointer
8192 icall_symbols [] = {
8193 #include "metadata/icall-def.h"
8198 #endif /* DISABLE_ICALL_TABLES */
8200 static mono_mutex_t icall_mutex;
8201 static GHashTable *icall_hash = NULL;
8202 static GHashTable *jit_icall_hash_name = NULL;
8203 static GHashTable *jit_icall_hash_addr = NULL;
8206 mono_icall_init (void)
8208 #ifndef DISABLE_ICALL_TABLES
8211 /* check that tables are sorted: disable in release */
8214 const char *prev_class = NULL;
8215 const char *prev_method;
8217 for (i = 0; i < Icall_type_num; ++i) {
8218 const IcallTypeDesc *desc;
8221 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
8222 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
8223 prev_class = icall_type_name_get (i);
8224 desc = &icall_type_descs [i];
8225 num_icalls = icall_desc_num_icalls (desc);
8226 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
8227 for (j = 0; j < num_icalls; ++j) {
8228 const char *methodn = icall_name_get (desc->first_icall + j);
8229 if (prev_method && strcmp (prev_method, methodn) >= 0)
8230 g_print ("method %s should come before method %s\n", methodn, prev_method);
8231 prev_method = methodn;
8237 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
8238 mono_os_mutex_init (&icall_mutex);
8242 mono_icall_lock (void)
8244 mono_locks_os_acquire (&icall_mutex, IcallLock);
8248 mono_icall_unlock (void)
8250 mono_locks_os_release (&icall_mutex, IcallLock);
8254 mono_icall_cleanup (void)
8256 g_hash_table_destroy (icall_hash);
8257 g_hash_table_destroy (jit_icall_hash_name);
8258 g_hash_table_destroy (jit_icall_hash_addr);
8259 mono_os_mutex_destroy (&icall_mutex);
8263 * mono_add_internal_call:
8264 * @name: method specification to surface to the managed world
8265 * @method: pointer to a C method to invoke when the method is called
8267 * This method surfaces the C function pointed by @method as a method
8268 * that has been surfaced in managed code with the method specified in
8269 * @name as an internal call.
8271 * Internal calls are surfaced to all app domains loaded and they are
8272 * accessibly by a type with the specified name.
8274 * You must provide a fully qualified type name, that is namespaces
8275 * and type name, followed by a colon and the method name, with an
8276 * optional signature to bind.
8278 * For example, the following are all valid declarations:
8280 * "MyApp.Services.ScriptService:Accelerate"
8281 * "MyApp.Services.ScriptService:Slowdown(int,bool)"
8283 * You use method parameters in cases where there might be more than
8284 * one surface method to managed code. That way you can register different
8285 * internal calls for different method overloads.
8287 * The internal calls are invoked with no marshalling. This means that .NET
8288 * types like System.String are exposed as `MonoString *` parameters. This is
8289 * different than the way that strings are surfaced in P/Invoke.
8291 * For more information on how the parameters are marshalled, see the
8292 * <a href="http://www.mono-project.com/docs/advanced/embedding/">Mono Embedding</a>
8295 * See the <a href="mono-api-methods.html#method-desc">Method Description</a>
8296 * reference for more information on the format of method descriptions.
8299 mono_add_internal_call (const char *name, gconstpointer method)
8303 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
8305 mono_icall_unlock ();
8308 #ifndef DISABLE_ICALL_TABLES
8310 #ifdef HAVE_ARRAY_ELEM_INIT
8312 compare_method_imap (const void *key, const void *elem)
8314 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
8315 return strcmp (key, method_name);
8319 find_method_icall (const IcallTypeDesc *imap, const char *name)
8321 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);
8324 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
8328 compare_class_imap (const void *key, const void *elem)
8330 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8331 return strcmp (key, class_name);
8334 static const IcallTypeDesc*
8335 find_class_icalls (const char *name)
8337 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);
8340 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8343 #else /* HAVE_ARRAY_ELEM_INIT */
8346 compare_method_imap (const void *key, const void *elem)
8348 const char** method_name = (const char**)elem;
8349 return strcmp (key, *method_name);
8353 find_method_icall (const IcallTypeDesc *imap, const char *name)
8355 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8358 return (gpointer)icall_functions [(nameslot - icall_names)];
8362 compare_class_imap (const void *key, const void *elem)
8364 const char** class_name = (const char**)elem;
8365 return strcmp (key, *class_name);
8368 static const IcallTypeDesc*
8369 find_class_icalls (const char *name)
8371 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8374 return &icall_type_descs [nameslot - icall_type_names];
8377 #endif /* HAVE_ARRAY_ELEM_INIT */
8379 #endif /* DISABLE_ICALL_TABLES */
8382 * we should probably export this as an helper (handle nested types).
8383 * Returns the number of chars written in buf.
8386 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8388 int nspacelen, cnamelen;
8389 nspacelen = strlen (klass->name_space);
8390 cnamelen = strlen (klass->name);
8391 if (nspacelen + cnamelen + 2 > bufsize)
8394 memcpy (buf, klass->name_space, nspacelen);
8395 buf [nspacelen ++] = '.';
8397 memcpy (buf + nspacelen, klass->name, cnamelen);
8398 buf [nspacelen + cnamelen] = 0;
8399 return nspacelen + cnamelen;
8402 #ifdef DISABLE_ICALL_TABLES
8404 no_icall_table (void)
8406 g_assert_not_reached ();
8411 mono_lookup_internal_call (MonoMethod *method)
8416 int typelen = 0, mlen, siglen;
8418 #ifndef DISABLE_ICALL_TABLES
8419 const IcallTypeDesc *imap = NULL;
8422 g_assert (method != NULL);
8424 if (method->is_inflated)
8425 method = ((MonoMethodInflated *) method)->declaring;
8427 if (method->klass->nested_in) {
8428 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8432 mname [pos++] = '/';
8435 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8441 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8446 #ifndef DISABLE_ICALL_TABLES
8447 imap = find_class_icalls (mname);
8450 mname [typelen] = ':';
8451 mname [typelen + 1] = ':';
8453 mlen = strlen (method->name);
8454 memcpy (mname + typelen + 2, method->name, mlen);
8455 sigstart = mname + typelen + 2 + mlen;
8458 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8459 siglen = strlen (tmpsig);
8460 if (typelen + mlen + siglen + 6 > sizeof (mname))
8463 memcpy (sigstart + 1, tmpsig, siglen);
8464 sigstart [siglen + 1] = ')';
8465 sigstart [siglen + 2] = 0;
8470 res = g_hash_table_lookup (icall_hash, mname);
8472 mono_icall_unlock ();;
8475 /* try without signature */
8477 res = g_hash_table_lookup (icall_hash, mname);
8479 mono_icall_unlock ();
8483 #ifdef DISABLE_ICALL_TABLES
8484 mono_icall_unlock ();
8485 /* Fail only when the result is actually used */
8486 /* mono_marshal_get_native_wrapper () depends on this */
8487 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8488 return ves_icall_System_String_ctor_RedirectToCreateString;
8490 return no_icall_table;
8492 /* it wasn't found in the static call tables */
8494 mono_icall_unlock ();
8497 res = find_method_icall (imap, sigstart - mlen);
8499 mono_icall_unlock ();
8502 /* try _with_ signature */
8504 res = find_method_icall (imap, sigstart - mlen);
8506 mono_icall_unlock ();
8510 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8511 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8512 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8513 g_print ("\nWhen you update one from git you need to update, compile and install\nthe other too.\n");
8514 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");
8515 g_print ("If you see other errors or faults after this message they are probably related\n");
8516 g_print ("and you need to fix your mono install first.\n");
8518 mono_icall_unlock ();
8524 #ifdef ENABLE_ICALL_SYMBOL_MAP
8526 func_cmp (gconstpointer key, gconstpointer p)
8528 return (gsize)key - (gsize)*(gsize*)p;
8533 * mono_lookup_icall_symbol:
8535 * Given the icall METHOD, returns its C symbol.
8538 mono_lookup_icall_symbol (MonoMethod *m)
8540 #ifdef DISABLE_ICALL_TABLES
8541 g_assert_not_reached ();
8544 #ifdef ENABLE_ICALL_SYMBOL_MAP
8548 static gconstpointer *functions_sorted;
8549 static const char**symbols_sorted;
8550 static gboolean inited;
8555 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8556 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8557 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8558 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8559 /* Bubble sort the two arrays */
8563 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8564 if (functions_sorted [i] > functions_sorted [i + 1]) {
8567 tmp = functions_sorted [i];
8568 functions_sorted [i] = functions_sorted [i + 1];
8569 functions_sorted [i + 1] = tmp;
8570 tmp = symbols_sorted [i];
8571 symbols_sorted [i] = symbols_sorted [i + 1];
8572 symbols_sorted [i + 1] = tmp;
8579 func = mono_lookup_internal_call (m);
8582 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8586 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8588 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8589 g_assert_not_reached ();
8596 type_from_typename (char *type_name)
8598 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8600 if (!strcmp (type_name, "int"))
8601 klass = mono_defaults.int_class;
8602 else if (!strcmp (type_name, "ptr"))
8603 klass = mono_defaults.int_class;
8604 else if (!strcmp (type_name, "void"))
8605 klass = mono_defaults.void_class;
8606 else if (!strcmp (type_name, "int32"))
8607 klass = mono_defaults.int32_class;
8608 else if (!strcmp (type_name, "uint32"))
8609 klass = mono_defaults.uint32_class;
8610 else if (!strcmp (type_name, "int8"))
8611 klass = mono_defaults.sbyte_class;
8612 else if (!strcmp (type_name, "uint8"))
8613 klass = mono_defaults.byte_class;
8614 else if (!strcmp (type_name, "int16"))
8615 klass = mono_defaults.int16_class;
8616 else if (!strcmp (type_name, "uint16"))
8617 klass = mono_defaults.uint16_class;
8618 else if (!strcmp (type_name, "long"))
8619 klass = mono_defaults.int64_class;
8620 else if (!strcmp (type_name, "ulong"))
8621 klass = mono_defaults.uint64_class;
8622 else if (!strcmp (type_name, "float"))
8623 klass = mono_defaults.single_class;
8624 else if (!strcmp (type_name, "double"))
8625 klass = mono_defaults.double_class;
8626 else if (!strcmp (type_name, "object"))
8627 klass = mono_defaults.object_class;
8628 else if (!strcmp (type_name, "obj"))
8629 klass = mono_defaults.object_class;
8630 else if (!strcmp (type_name, "string"))
8631 klass = mono_defaults.string_class;
8632 else if (!strcmp (type_name, "bool"))
8633 klass = mono_defaults.boolean_class;
8634 else if (!strcmp (type_name, "boolean"))
8635 klass = mono_defaults.boolean_class;
8637 g_error ("%s", type_name);
8638 g_assert_not_reached ();
8640 return &klass->byval_arg;
8644 * LOCKING: Take the corlib image lock.
8646 MonoMethodSignature*
8647 mono_create_icall_signature (const char *sigstr)
8652 MonoMethodSignature *res, *res2;
8653 MonoImage *corlib = mono_defaults.corlib;
8655 mono_image_lock (corlib);
8656 res = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8657 mono_image_unlock (corlib);
8662 parts = g_strsplit (sigstr, " ", 256);
8671 res = mono_metadata_signature_alloc (corlib, len - 1);
8676 * Under windows, the default pinvoke calling convention is STDCALL but
8679 res->call_convention = MONO_CALL_C;
8682 res->ret = type_from_typename (parts [0]);
8683 for (i = 1; i < len; ++i) {
8684 res->params [i - 1] = type_from_typename (parts [i]);
8689 mono_image_lock (corlib);
8690 res2 = (MonoMethodSignature *)g_hash_table_lookup (corlib->helper_signatures, sigstr);
8692 res = res2; /*Value is allocated in the image pool*/
8694 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8695 mono_image_unlock (corlib);
8701 mono_find_jit_icall_by_name (const char *name)
8703 MonoJitICallInfo *info;
8704 g_assert (jit_icall_hash_name);
8707 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8708 mono_icall_unlock ();
8713 mono_find_jit_icall_by_addr (gconstpointer addr)
8715 MonoJitICallInfo *info;
8716 g_assert (jit_icall_hash_addr);
8719 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8720 mono_icall_unlock ();
8726 * mono_get_jit_icall_info:
8728 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8729 * caller should access it while holding the icall lock.
8732 mono_get_jit_icall_info (void)
8734 return jit_icall_hash_name;
8738 * mono_lookup_jit_icall_symbol:
8740 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8743 mono_lookup_jit_icall_symbol (const char *name)
8745 MonoJitICallInfo *info;
8746 const char *res = NULL;
8749 info = (MonoJitICallInfo *)g_hash_table_lookup (jit_icall_hash_name, name);
8751 res = info->c_symbol;
8752 mono_icall_unlock ();
8757 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8760 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8761 mono_icall_unlock ();
8765 * 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
8766 * icalls without wrappers in some cases.
8769 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, gboolean no_raise, const char *c_symbol)
8771 MonoJitICallInfo *info;
8778 if (!jit_icall_hash_name) {
8779 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8780 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8783 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8784 g_warning ("jit icall already defined \"%s\"\n", name);
8785 g_assert_not_reached ();
8788 info = g_new0 (MonoJitICallInfo, 1);
8793 info->c_symbol = c_symbol;
8794 info->no_raise = no_raise;
8797 info->wrapper = func;
8799 info->wrapper = NULL;
8802 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8803 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8805 mono_icall_unlock ();
8810 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8812 return mono_register_jit_icall_full (func, name, sig, is_save, FALSE, NULL);