5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
11 * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
22 #ifdef HAVE_SYS_TIME_H
28 #if defined (HOST_WIN32)
31 #if defined (HAVE_WCHAR_H)
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool.h>
40 #include <mono/metadata/monitor.h>
41 #include <mono/metadata/reflection.h>
42 #include <mono/metadata/assembly.h>
43 #include <mono/metadata/tabledefs.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/file-io.h>
46 #include <mono/metadata/console-io.h>
47 #include <mono/metadata/socket-io.h>
48 #include <mono/metadata/mono-endian.h>
49 #include <mono/metadata/tokentype.h>
50 #include <mono/metadata/domain-internals.h>
51 #include <mono/metadata/metadata-internals.h>
52 #include <mono/metadata/class-internals.h>
53 #include <mono/metadata/marshal.h>
54 #include <mono/metadata/gc-internal.h>
55 #include <mono/metadata/mono-gc.h>
56 #include <mono/metadata/rand.h>
57 #include <mono/metadata/sysmath.h>
58 #include <mono/metadata/string-icalls.h>
59 #include <mono/metadata/debug-helpers.h>
60 #include <mono/metadata/process.h>
61 #include <mono/metadata/environment.h>
62 #include <mono/metadata/profiler-private.h>
63 #include <mono/metadata/locales.h>
64 #include <mono/metadata/filewatcher.h>
65 #include <mono/metadata/char-conversions.h>
66 #include <mono/metadata/security.h>
67 #include <mono/metadata/mono-config.h>
68 #include <mono/metadata/cil-coff.h>
69 #include <mono/metadata/number-formatter.h>
70 #include <mono/metadata/security-manager.h>
71 #include <mono/metadata/security-core-clr.h>
72 #include <mono/metadata/mono-perfcounters.h>
73 #include <mono/metadata/mono-debug.h>
74 #include <mono/metadata/mono-ptr-array.h>
75 #include <mono/metadata/verify-internals.h>
76 #include <mono/io-layer/io-layer.h>
77 #include <mono/utils/strtod.h>
78 #include <mono/utils/monobitset.h>
79 #include <mono/utils/mono-time.h>
80 #include <mono/utils/mono-proclib.h>
81 #include <mono/utils/mono-string.h>
82 #include <mono/utils/mono-error-internals.h>
83 #include <mono/utils/mono-mmap.h>
84 #include <mono/utils/mono-io-portability.h>
86 #if defined (HOST_WIN32)
92 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
94 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
97 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
99 static inline MonoBoolean
100 is_generic_parameter (MonoType *type)
102 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
106 mono_class_init_or_throw (MonoClass *klass)
108 if (!mono_class_init (klass))
109 mono_raise_exception (mono_class_get_exception_for_failure (klass));
113 * We expect a pointer to a char, not a string
115 ICALL_EXPORT gboolean
116 mono_double_ParseImpl (char *ptr, double *result)
118 gchar *endptr = NULL;
125 *result = strtod (ptr, &endptr);
128 /* mono_strtod () is not thread-safe */
129 EnterCriticalSection (&mono_strtod_mutex);
130 *result = mono_strtod (ptr, &endptr);
131 LeaveCriticalSection (&mono_strtod_mutex);
135 if (!*ptr || (endptr && *endptr))
141 ICALL_EXPORT MonoObject *
142 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
151 ao = (MonoArray *)this;
152 ac = (MonoClass *)ao->obj.vtable->klass;
154 esize = mono_array_element_size (ac);
155 ea = (gpointer*)((char*)ao->vector + (pos * esize));
157 if (ac->element_class->valuetype)
158 return mono_value_box (this->vtable->domain, ac->element_class, ea);
163 ICALL_EXPORT MonoObject *
164 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
172 MONO_CHECK_ARG_NULL (idxs);
174 io = (MonoArray *)idxs;
175 ic = (MonoClass *)io->obj.vtable->klass;
177 ao = (MonoArray *)this;
178 ac = (MonoClass *)ao->obj.vtable->klass;
180 g_assert (ic->rank == 1);
181 if (io->bounds != NULL || io->max_length != ac->rank)
182 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
184 ind = (gint32 *)io->vector;
186 if (ao->bounds == NULL) {
187 if (*ind < 0 || *ind >= ao->max_length)
188 mono_raise_exception (mono_get_exception_index_out_of_range ());
190 return ves_icall_System_Array_GetValueImpl (this, *ind);
193 for (i = 0; i < ac->rank; i++)
194 if ((ind [i] < ao->bounds [i].lower_bound) ||
195 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
196 mono_raise_exception (mono_get_exception_index_out_of_range ());
198 pos = ind [0] - ao->bounds [0].lower_bound;
199 for (i = 1; i < ac->rank; i++)
200 pos = pos*ao->bounds [i].length + ind [i] -
201 ao->bounds [i].lower_bound;
203 return ves_icall_System_Array_GetValueImpl (this, pos);
207 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
209 MonoClass *ac, *vc, *ec;
221 vc = value->vtable->klass;
225 ac = this->obj.vtable->klass;
226 ec = ac->element_class;
228 esize = mono_array_element_size (ac);
229 ea = (gpointer*)((char*)this->vector + (pos * esize));
230 va = (gpointer*)((char*)value + sizeof (MonoObject));
232 if (mono_class_is_nullable (ec)) {
233 mono_nullable_init ((guint8*)ea, value, ec);
238 mono_gc_bzero (ea, esize);
242 #define NO_WIDENING_CONVERSION G_STMT_START{\
243 mono_raise_exception (mono_get_exception_argument ( \
244 "value", "not a widening conversion")); \
247 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
248 if (esize < vsize + (extra)) \
249 mono_raise_exception (mono_get_exception_argument ( \
250 "value", "not a widening conversion")); \
253 #define INVALID_CAST G_STMT_START{ \
254 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
255 mono_raise_exception (mono_get_exception_invalid_cast ()); \
258 /* Check element (destination) type. */
259 switch (ec->byval_arg.type) {
260 case MONO_TYPE_STRING:
261 switch (vc->byval_arg.type) {
262 case MONO_TYPE_STRING:
268 case MONO_TYPE_BOOLEAN:
269 switch (vc->byval_arg.type) {
270 case MONO_TYPE_BOOLEAN:
283 NO_WIDENING_CONVERSION;
290 if (!ec->valuetype) {
291 if (!mono_object_isinst (value, ec))
293 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
297 if (mono_object_isinst (value, ec)) {
298 if (ec->has_references)
299 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
301 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
308 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
310 et = ec->byval_arg.type;
311 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
312 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
314 vt = vc->byval_arg.type;
315 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
316 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
318 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
324 case MONO_TYPE_CHAR: \
325 CHECK_WIDENING_CONVERSION(0); \
326 *(etype *) ea = (etype) u64; \
328 /* You can't assign a signed value to an unsigned array. */ \
333 /* You can't assign a floating point number to an integer array. */ \
336 NO_WIDENING_CONVERSION; \
340 #define ASSIGN_SIGNED(etype) G_STMT_START{\
346 CHECK_WIDENING_CONVERSION(0); \
347 *(etype *) ea = (etype) i64; \
349 /* You can assign an unsigned value to a signed array if the array's */ \
350 /* element size is larger than the value size. */ \
355 case MONO_TYPE_CHAR: \
356 CHECK_WIDENING_CONVERSION(1); \
357 *(etype *) ea = (etype) u64; \
359 /* You can't assign a floating point number to an integer array. */ \
362 NO_WIDENING_CONVERSION; \
366 #define ASSIGN_REAL(etype) G_STMT_START{\
370 CHECK_WIDENING_CONVERSION(0); \
371 *(etype *) ea = (etype) r64; \
373 /* All integer values fit into a floating point array, so we don't */ \
374 /* need to CHECK_WIDENING_CONVERSION here. */ \
379 *(etype *) ea = (etype) i64; \
385 case MONO_TYPE_CHAR: \
386 *(etype *) ea = (etype) u64; \
393 u64 = *(guint8 *) va;
396 u64 = *(guint16 *) va;
399 u64 = *(guint32 *) va;
402 u64 = *(guint64 *) va;
408 i64 = *(gint16 *) va;
411 i64 = *(gint32 *) va;
414 i64 = *(gint64 *) va;
417 r64 = *(gfloat *) va;
420 r64 = *(gdouble *) va;
423 u64 = *(guint16 *) va;
425 case MONO_TYPE_BOOLEAN:
426 /* Boolean is only compatible with itself. */
439 NO_WIDENING_CONVERSION;
446 /* If we can't do a direct copy, let's try a widening conversion. */
449 ASSIGN_UNSIGNED (guint16);
451 ASSIGN_UNSIGNED (guint8);
453 ASSIGN_UNSIGNED (guint16);
455 ASSIGN_UNSIGNED (guint32);
457 ASSIGN_UNSIGNED (guint64);
459 ASSIGN_SIGNED (gint8);
461 ASSIGN_SIGNED (gint16);
463 ASSIGN_SIGNED (gint32);
465 ASSIGN_SIGNED (gint64);
467 ASSIGN_REAL (gfloat);
469 ASSIGN_REAL (gdouble);
473 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
477 #undef NO_WIDENING_CONVERSION
478 #undef CHECK_WIDENING_CONVERSION
479 #undef ASSIGN_UNSIGNED
485 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
493 MONO_CHECK_ARG_NULL (idxs);
495 ic = idxs->obj.vtable->klass;
496 ac = this->obj.vtable->klass;
498 g_assert (ic->rank == 1);
499 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
500 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
502 ind = (gint32 *)idxs->vector;
504 if (this->bounds == NULL) {
505 if (*ind < 0 || *ind >= this->max_length)
506 mono_raise_exception (mono_get_exception_index_out_of_range ());
508 ves_icall_System_Array_SetValueImpl (this, value, *ind);
512 for (i = 0; i < ac->rank; i++)
513 if ((ind [i] < this->bounds [i].lower_bound) ||
514 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
515 mono_raise_exception (mono_get_exception_index_out_of_range ());
517 pos = ind [0] - this->bounds [0].lower_bound;
518 for (i = 1; i < ac->rank; i++)
519 pos = pos * this->bounds [i].length + ind [i] -
520 this->bounds [i].lower_bound;
522 ves_icall_System_Array_SetValueImpl (this, value, pos);
525 ICALL_EXPORT MonoArray *
526 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
528 MonoClass *aklass, *klass;
531 gboolean bounded = FALSE;
535 MONO_CHECK_ARG_NULL (type);
536 MONO_CHECK_ARG_NULL (lengths);
538 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
540 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
542 for (i = 0; i < mono_array_length (lengths); i++)
543 if (mono_array_get (lengths, gint32, i) < 0)
544 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
546 klass = mono_class_from_mono_type (type->type);
547 mono_class_init_or_throw (klass);
549 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
550 /* vectors are not the same as one dimensional arrays with no-zero bounds */
555 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
557 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
558 for (i = 0; i < aklass->rank; ++i) {
559 sizes [i] = mono_array_get (lengths, guint32, i);
561 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
563 sizes [i + aklass->rank] = 0;
566 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
571 ICALL_EXPORT MonoArray *
572 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
574 MonoClass *aklass, *klass;
577 gboolean bounded = FALSE;
581 MONO_CHECK_ARG_NULL (type);
582 MONO_CHECK_ARG_NULL (lengths);
584 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
586 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
588 for (i = 0; i < mono_array_length (lengths); i++)
589 if ((mono_array_get (lengths, gint64, i) < 0) ||
590 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
591 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
593 klass = mono_class_from_mono_type (type->type);
594 mono_class_init_or_throw (klass);
596 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
597 /* vectors are not the same as one dimensional arrays with no-zero bounds */
602 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
604 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
605 for (i = 0; i < aklass->rank; ++i) {
606 sizes [i] = mono_array_get (lengths, guint64, i);
608 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
610 sizes [i + aklass->rank] = 0;
613 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
619 ves_icall_System_Array_GetRank (MonoObject *this)
623 return this->vtable->klass->rank;
627 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
629 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
634 if ((dimension < 0) || (dimension >= rank))
635 mono_raise_exception (mono_get_exception_index_out_of_range ());
637 if (this->bounds == NULL)
638 length = this->max_length;
640 length = this->bounds [dimension].length;
642 #ifdef MONO_BIG_ARRAYS
643 if (length > G_MAXINT32)
644 mono_raise_exception (mono_get_exception_overflow ());
650 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
652 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
656 if ((dimension < 0) || (dimension >= rank))
657 mono_raise_exception (mono_get_exception_index_out_of_range ());
659 if (this->bounds == NULL)
660 return this->max_length;
662 return this->bounds [dimension].length;
666 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
668 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
672 if ((dimension < 0) || (dimension >= rank))
673 mono_raise_exception (mono_get_exception_index_out_of_range ());
675 if (this->bounds == NULL)
678 return this->bounds [dimension].lower_bound;
682 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
684 int sz = mono_array_element_size (mono_object_class (arr));
685 mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
688 ICALL_EXPORT gboolean
689 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
694 MonoClass *src_class;
695 MonoClass *dest_class;
699 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
702 if (source->bounds || dest->bounds)
705 /* there's no integer overflow since mono_array_length returns an unsigned integer */
706 if ((dest_idx + length > mono_array_length (dest)) ||
707 (source_idx + length > mono_array_length (source)))
710 src_class = source->obj.vtable->klass->element_class;
711 dest_class = dest->obj.vtable->klass->element_class;
714 * Handle common cases.
717 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
718 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
719 // FIXME: This is racy
723 int has_refs = dest_class->has_references;
724 for (i = source_idx; i < source_idx + length; ++i) {
725 MonoObject *elem = mono_array_get (source, MonoObject*, i);
726 if (elem && !mono_object_isinst (elem, dest_class))
730 element_size = mono_array_element_size (dest->obj.vtable->klass);
731 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
732 for (i = 0; i < length; ++i) {
733 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
734 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
738 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
740 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
746 /* Check if we're copying a char[] <==> (u)short[] */
747 if (src_class != dest_class) {
748 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
751 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
753 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
754 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
755 // FIXME: This is racy
759 for (i = source_idx; i < source_idx + length; ++i) {
760 MonoObject *elem = mono_array_get (source, MonoObject*, i);
761 if (elem && !mono_object_isinst (elem, dest_class))
769 if (dest_class->valuetype) {
770 element_size = mono_array_element_size (source->obj.vtable->klass);
771 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
772 if (dest_class->has_references) {
773 mono_value_copy_array (dest, dest_idx, source_addr, length);
775 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
776 mono_gc_memmove (dest_addr, source_addr, element_size * length);
779 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
786 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
795 ao = (MonoArray *)this;
796 ac = (MonoClass *)ao->obj.vtable->klass;
798 esize = mono_array_element_size (ac);
799 ea = (gpointer*)((char*)ao->vector + (pos * esize));
801 mono_gc_memmove (value, ea, esize);
805 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
814 ao = (MonoArray *)this;
815 ac = (MonoClass *)ao->obj.vtable->klass;
816 ec = ac->element_class;
818 esize = mono_array_element_size (ac);
819 ea = (gpointer*)((char*)ao->vector + (pos * esize));
821 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
822 g_assert (esize == sizeof (gpointer));
823 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
825 g_assert (ec->inited);
826 g_assert (esize == mono_class_value_size (ec, NULL));
827 if (ec->has_references)
828 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
830 mono_gc_memmove (ea, value, esize);
835 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
837 MonoClass *klass = array->obj.vtable->klass;
838 guint32 size = mono_array_element_size (klass);
839 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
841 const char *field_data;
843 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
844 MonoException *exc = mono_get_exception_argument("array",
845 "Cannot initialize array of non-primitive type.");
846 mono_raise_exception (exc);
849 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
850 MonoException *exc = mono_get_exception_argument("field_handle",
851 "Field doesn't have an RVA");
852 mono_raise_exception (exc);
855 size *= array->max_length;
856 field_data = mono_field_get_data (field_handle);
858 if (size > mono_type_size (field_handle->type, &align)) {
859 MonoException *exc = mono_get_exception_argument("field_handle",
860 "Field not large enough to fill array");
861 mono_raise_exception (exc);
864 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
866 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
867 guint ## n *src = (guint ## n *) field_data; \
868 guint ## n *end = (guint ## n *)((char*)src + size); \
870 for (; src < end; data++, src++) { \
871 *data = read ## n (src); \
875 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
877 switch (type->type) {
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
898 memcpy (mono_array_addr (array, char, 0), field_data, size);
900 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
903 double *data = (double*)mono_array_addr (array, double, 0);
905 for (i = 0; i < size; i++, data++) {
915 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
919 return offsetof (MonoString, chars);
922 ICALL_EXPORT MonoObject *
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
927 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
930 return mono_object_clone (obj);
934 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
939 MONO_CHECK_ARG_NULL (handle);
941 klass = mono_class_from_mono_type (handle);
942 MONO_CHECK_ARG (handle, klass);
944 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
946 /* This will call the type constructor */
947 mono_runtime_class_init (vtable);
951 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
955 mono_image_check_for_module_cctor (image);
956 if (image->has_module_cctor) {
957 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
958 /*It's fine to raise the exception here*/
959 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
963 ICALL_EXPORT MonoBoolean
964 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
969 /* later make this configurable and per-arch */
970 int min_size = 4096 * 4 * sizeof (void*);
971 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
972 /* if we have no info we are optimistic and assume there is enough room */
975 current = (guint8 *)&stack_addr;
976 if (current > stack_addr) {
977 if ((current - stack_addr) < min_size)
980 if (current - (stack_addr - stack_size) < min_size)
986 ICALL_EXPORT MonoObject *
987 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
991 return mono_object_clone (this);
995 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
998 MonoObject **values = NULL;
1002 MonoClassField* field;
1005 MONO_ARCH_SAVE_REGS;
1007 klass = mono_object_class (this);
1009 if (mono_class_num_fields (klass) == 0)
1010 return mono_object_hash (this);
1013 * Compute the starting value of the hashcode for fields of primitive
1014 * types, and return the remaining fields in an array to the managed side.
1015 * This way, we can avoid costly reflection operations in managed code.
1018 while ((field = mono_class_get_fields (klass, &iter))) {
1019 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1021 if (mono_field_is_deleted (field))
1023 /* FIXME: Add more types */
1024 switch (field->type->type) {
1026 result ^= *(gint32*)((guint8*)this + field->offset);
1028 case MONO_TYPE_STRING: {
1030 s = *(MonoString**)((guint8*)this + field->offset);
1032 result ^= mono_string_hash (s);
1037 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1038 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1039 values [count++] = o;
1045 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1046 for (i = 0; i < count; ++i)
1047 mono_array_setref (*fields, i, values [i]);
1054 ICALL_EXPORT MonoBoolean
1055 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1058 MonoObject **values = NULL;
1060 MonoClassField* field;
1064 MONO_ARCH_SAVE_REGS;
1066 MONO_CHECK_ARG_NULL (that);
1068 if (this->vtable != that->vtable)
1071 klass = mono_object_class (this);
1073 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1074 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1077 * Do the comparison for fields of primitive type and return a result if
1078 * possible. Otherwise, return the remaining fields in an array to the
1079 * managed side. This way, we can avoid costly reflection operations in
1084 while ((field = mono_class_get_fields (klass, &iter))) {
1085 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1087 if (mono_field_is_deleted (field))
1089 /* FIXME: Add more types */
1090 switch (field->type->type) {
1093 case MONO_TYPE_BOOLEAN:
1094 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1099 case MONO_TYPE_CHAR:
1100 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1105 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1110 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1114 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1118 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1123 case MONO_TYPE_STRING: {
1124 MonoString *s1, *s2;
1125 guint32 s1len, s2len;
1126 s1 = *(MonoString**)((guint8*)this + field->offset);
1127 s2 = *(MonoString**)((guint8*)that + field->offset);
1130 if ((s1 == NULL) || (s2 == NULL))
1132 s1len = mono_string_length (s1);
1133 s2len = mono_string_length (s2);
1137 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1143 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1144 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1145 values [count++] = o;
1146 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1147 values [count++] = o;
1150 if (klass->enumtype)
1151 /* enums only have one non-static field */
1157 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1158 for (i = 0; i < count; ++i)
1159 mono_array_setref (*fields, i, values [i]);
1166 ICALL_EXPORT MonoReflectionType *
1167 ves_icall_System_Object_GetType (MonoObject *obj)
1169 MONO_ARCH_SAVE_REGS;
1171 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1172 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1174 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1178 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1180 MONO_ARCH_SAVE_REGS;
1182 mtype->type = &obj->vtable->klass->byval_arg;
1183 g_assert (mtype->type->type);
1187 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1189 MONO_ARCH_SAVE_REGS;
1191 MONO_CHECK_ARG_NULL (obj);
1193 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1197 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1198 MonoReflectionMethod *method,
1199 MonoArray *opt_param_types)
1201 MONO_ARCH_SAVE_REGS;
1203 MONO_CHECK_ARG_NULL (method);
1205 return mono_image_create_method_token (
1206 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1210 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1212 MONO_ARCH_SAVE_REGS;
1214 mono_image_create_pefile (mb, file);
1218 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1220 MONO_ARCH_SAVE_REGS;
1222 mono_image_build_metadata (mb);
1226 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1228 MONO_ARCH_SAVE_REGS;
1230 mono_image_register_token (mb->dynamic_image, token, obj);
1234 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1236 MonoMethod **dest = data;
1238 /* skip unmanaged frames */
1254 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1256 MonoMethod **dest = data;
1258 /* skip unmanaged frames */
1263 if (!strcmp (m->klass->name_space, "System.Reflection"))
1272 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1274 MonoMethod **dest = data;
1276 /* skip unmanaged frames */
1280 if (m->wrapper_type != MONO_WRAPPER_NONE)
1283 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1297 static MonoReflectionType *
1298 type_from_name (const char *str, MonoBoolean ignoreCase)
1300 MonoType *type = NULL;
1301 MonoAssembly *assembly = NULL;
1302 MonoTypeNameParse info;
1303 char *temp_str = g_strdup (str);
1304 gboolean type_resolve = FALSE;
1306 MONO_ARCH_SAVE_REGS;
1308 /* mono_reflection_parse_type() mangles the string */
1309 if (!mono_reflection_parse_type (temp_str, &info)) {
1310 mono_reflection_free_type_info (&info);
1315 if (info.assembly.name) {
1316 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1318 MonoMethod *m = mono_method_get_last_managed ();
1319 MonoMethod *dest = m;
1321 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1326 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1327 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1328 * to crash. This only seems to happen in some strange remoting
1329 * scenarios and I was unable to figure out what's happening there.
1330 * Dec 10, 2005 - Martin.
1334 assembly = dest->klass->image->assembly;
1335 type_resolve = TRUE;
1337 g_warning (G_STRLOC);
1342 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1343 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1346 if (!info.assembly.name && !type) /* try mscorlib */
1347 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1349 if (assembly && !type && type_resolve) {
1350 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1351 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1354 mono_reflection_free_type_info (&info);
1360 return mono_type_get_object (mono_domain_get (), type);
1364 MonoReflectionType *
1365 mono_type_get (const char *str)
1367 char *copy = g_strdup (str);
1368 MonoReflectionType *type = type_from_name (copy, FALSE);
1375 ICALL_EXPORT MonoReflectionType*
1376 ves_icall_type_from_name (MonoString *name,
1377 MonoBoolean throwOnError,
1378 MonoBoolean ignoreCase)
1380 char *str = mono_string_to_utf8 (name);
1381 MonoReflectionType *type;
1383 type = type_from_name (str, ignoreCase);
1386 MonoException *e = NULL;
1389 e = mono_get_exception_type_load (name, NULL);
1391 mono_loader_clear_error ();
1393 mono_raise_exception (e);
1400 ICALL_EXPORT MonoReflectionType*
1401 ves_icall_type_from_handle (MonoType *handle)
1403 MonoDomain *domain = mono_domain_get ();
1405 MONO_ARCH_SAVE_REGS;
1407 return mono_type_get_object (domain, handle);
1410 ICALL_EXPORT MonoBoolean
1411 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1413 MONO_ARCH_SAVE_REGS;
1415 if (c && type->type && c->type)
1416 return mono_metadata_type_equal (type->type, c->type);
1418 return (type == c) ? TRUE : FALSE;
1421 /* System.TypeCode */
1440 TYPECODE_STRING = 18
1443 ICALL_EXPORT guint32
1444 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1446 int t = type->type->type;
1448 MONO_ARCH_SAVE_REGS;
1450 if (type->type->byref)
1451 return TYPECODE_OBJECT;
1455 case MONO_TYPE_VOID:
1456 return TYPECODE_OBJECT;
1457 case MONO_TYPE_BOOLEAN:
1458 return TYPECODE_BOOLEAN;
1460 return TYPECODE_BYTE;
1462 return TYPECODE_SBYTE;
1464 return TYPECODE_UINT16;
1466 return TYPECODE_INT16;
1467 case MONO_TYPE_CHAR:
1468 return TYPECODE_CHAR;
1472 return TYPECODE_OBJECT;
1474 return TYPECODE_UINT32;
1476 return TYPECODE_INT32;
1478 return TYPECODE_UINT64;
1480 return TYPECODE_INT64;
1482 return TYPECODE_SINGLE;
1484 return TYPECODE_DOUBLE;
1485 case MONO_TYPE_VALUETYPE: {
1486 MonoClass *klass = type->type->data.klass;
1488 if (klass->enumtype) {
1489 t = mono_class_enum_basetype (klass)->type;
1491 } else if (mono_is_corlib_image (klass->image)) {
1492 if (strcmp (klass->name_space, "System") == 0) {
1493 if (strcmp (klass->name, "Decimal") == 0)
1494 return TYPECODE_DECIMAL;
1495 else if (strcmp (klass->name, "DateTime") == 0)
1496 return TYPECODE_DATETIME;
1499 return TYPECODE_OBJECT;
1501 case MONO_TYPE_STRING:
1502 return TYPECODE_STRING;
1503 case MONO_TYPE_SZARRAY:
1504 case MONO_TYPE_ARRAY:
1505 case MONO_TYPE_OBJECT:
1507 case MONO_TYPE_MVAR:
1508 case MONO_TYPE_TYPEDBYREF:
1509 return TYPECODE_OBJECT;
1510 case MONO_TYPE_CLASS:
1512 MonoClass *klass = type->type->data.klass;
1513 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1514 if (strcmp (klass->name, "DBNull") == 0)
1515 return TYPECODE_DBNULL;
1518 return TYPECODE_OBJECT;
1519 case MONO_TYPE_GENERICINST:
1520 return TYPECODE_OBJECT;
1522 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1527 ICALL_EXPORT guint32
1528 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1534 MONO_ARCH_SAVE_REGS;
1536 g_assert (type != NULL);
1538 domain = ((MonoObject *)type)->vtable->domain;
1540 if (!c) /* FIXME: dont know what do do here */
1543 klass = mono_class_from_mono_type (type->type);
1544 klassc = mono_class_from_mono_type (c->type);
1546 /* Interface check requires a more complex setup so we
1547 * only do for them. Otherwise we simply avoid mono_class_init.
1549 if (check_interfaces) {
1550 mono_class_init_or_throw (klass);
1551 mono_class_init_or_throw (klassc);
1552 } else if (!klass->supertypes || !klassc->supertypes) {
1553 mono_loader_lock ();
1554 mono_class_setup_supertypes (klass);
1555 mono_class_setup_supertypes (klassc);
1556 mono_loader_unlock ();
1559 if (type->type->byref)
1560 return klassc == mono_defaults.object_class;
1562 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1566 mono_type_is_primitive (MonoType *type)
1568 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1569 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1573 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1575 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1576 return mono_class_enum_basetype (type->data.klass);
1577 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1578 return mono_class_enum_basetype (type->data.generic_class->container_class);
1582 ICALL_EXPORT guint32
1583 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1589 MONO_ARCH_SAVE_REGS;
1591 g_assert (type != NULL);
1593 domain = ((MonoObject *)type)->vtable->domain;
1595 klass = mono_class_from_mono_type (type->type);
1596 klassc = mono_class_from_mono_type (c->type);
1598 mono_class_init_or_throw (klass);
1599 mono_class_init_or_throw (klassc);
1601 if (type->type->byref ^ c->type->byref)
1604 if (type->type->byref) {
1605 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1606 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1608 klass = mono_class_from_mono_type (t);
1609 klassc = mono_class_from_mono_type (ot);
1611 if (mono_type_is_primitive (t)) {
1612 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1613 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1614 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1615 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1616 return t->type == ot->type;
1618 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1621 if (klass->valuetype)
1622 return klass == klassc;
1623 return klass->valuetype == klassc->valuetype;
1626 return mono_class_is_assignable_from (klass, klassc);
1629 ICALL_EXPORT guint32
1630 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1632 MonoClass *klass = mono_class_from_mono_type (type->type);
1633 mono_class_init_or_throw (klass);
1634 return mono_object_isinst (obj, klass) != NULL;
1637 ICALL_EXPORT guint32
1638 ves_icall_get_attributes (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)
1647 MonoClass *klass = field->field->parent;
1648 MonoMarshalType *info;
1651 if (klass->generic_container ||
1652 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1655 info = mono_marshal_load_type_info (klass);
1657 for (i = 0; i < info->num_fields; ++i) {
1658 if (info->fields [i].field == field->field) {
1659 if (!info->fields [i].mspec)
1662 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1669 ICALL_EXPORT MonoReflectionField*
1670 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1672 gboolean found = FALSE;
1679 klass = handle->parent;
1681 klass = mono_class_from_mono_type (type);
1683 /* Check that the field belongs to the class */
1684 for (k = klass; k; k = k->parent) {
1685 if (k == handle->parent) {
1692 /* The managed code will throw the exception */
1696 return mono_field_get_object (mono_domain_get (), klass, handle);
1699 ICALL_EXPORT MonoArray*
1700 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1703 MonoType *type = mono_field_get_type_checked (field->field, &error);
1704 if (!mono_error_ok (&error))
1705 mono_error_raise_exception (&error);
1707 return type_array_from_modifiers (field->field->parent->image, type, optional);
1711 vell_icall_get_method_attributes (MonoMethod *method)
1713 return method->flags;
1717 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1720 MonoDomain *domain = mono_domain_get ();
1721 MonoMethodSignature* sig;
1722 MONO_ARCH_SAVE_REGS;
1724 sig = mono_method_signature_checked (method, &error);
1725 if (!mono_error_ok (&error))
1726 mono_error_raise_exception (&error);
1729 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1730 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1731 info->attrs = method->flags;
1732 info->implattrs = method->iflags;
1733 if (sig->call_convention == MONO_CALL_DEFAULT)
1734 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1736 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1741 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1744 ICALL_EXPORT MonoArray*
1745 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1747 MonoDomain *domain = mono_domain_get ();
1749 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1752 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1753 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1755 MonoDomain *domain = mono_domain_get ();
1756 MonoReflectionMarshalAsAttribute* res = NULL;
1757 MonoMarshalSpec **mspecs;
1760 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1761 mono_method_get_marshal_info (method, mspecs);
1764 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1766 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1768 mono_metadata_free_marshal_spec (mspecs [i]);
1775 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1777 MonoClass *parent = field->field->parent;
1778 if (!parent->size_inited)
1779 mono_class_init (parent);
1781 return field->field->offset - sizeof (MonoObject);
1784 ICALL_EXPORT MonoReflectionType*
1785 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1788 MONO_ARCH_SAVE_REGS;
1790 parent = declaring? field->field->parent: field->klass;
1792 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1795 ICALL_EXPORT MonoObject *
1796 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1798 MonoClass *fklass = field->klass;
1799 MonoClassField *cf = field->field;
1800 MonoDomain *domain = mono_object_domain (field);
1802 if (fklass->image->assembly->ref_only)
1803 mono_raise_exception (mono_get_exception_invalid_operation (
1804 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1806 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1807 mono_security_core_clr_ensure_reflection_access_field (cf);
1809 return mono_field_get_value_object (domain, cf, obj);
1813 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1816 MonoClassField *cf = field->field;
1820 MONO_ARCH_SAVE_REGS;
1822 if (field->klass->image->assembly->ref_only)
1823 mono_raise_exception (mono_get_exception_invalid_operation (
1824 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1826 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1827 mono_security_core_clr_ensure_reflection_access_field (cf);
1829 type = mono_field_get_type_checked (cf, &error);
1830 if (!mono_error_ok (&error))
1831 mono_error_raise_exception (&error);
1833 v = (gchar *) value;
1835 switch (type->type) {
1838 case MONO_TYPE_BOOLEAN:
1841 case MONO_TYPE_CHAR:
1850 case MONO_TYPE_VALUETYPE:
1853 v += sizeof (MonoObject);
1855 case MONO_TYPE_STRING:
1856 case MONO_TYPE_OBJECT:
1857 case MONO_TYPE_CLASS:
1858 case MONO_TYPE_ARRAY:
1859 case MONO_TYPE_SZARRAY:
1862 case MONO_TYPE_GENERICINST: {
1863 MonoGenericClass *gclass = type->data.generic_class;
1864 g_assert (!gclass->context.class_inst->is_open);
1866 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1867 MonoClass *nklass = mono_class_from_mono_type (type);
1868 MonoObject *nullable;
1871 * Convert the boxed vtype into a Nullable structure.
1872 * This is complicated by the fact that Nullables have
1873 * a variable structure.
1875 nullable = mono_object_new (mono_domain_get (), nklass);
1877 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1879 v = mono_object_unbox (nullable);
1882 if (gclass->container_class->valuetype && (v != NULL))
1883 v += sizeof (MonoObject);
1887 g_error ("type 0x%x not handled in "
1888 "ves_icall_FieldInfo_SetValueInternal", type->type);
1893 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1894 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1895 if (!vtable->initialized)
1896 mono_runtime_class_init (vtable);
1897 mono_field_static_set_value (vtable, cf, v);
1899 mono_field_set_value (obj, cf, v);
1903 ICALL_EXPORT MonoObject *
1904 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1906 MonoObject *o = NULL;
1907 MonoClassField *field = this->field;
1909 MonoDomain *domain = mono_object_domain (this);
1911 MonoTypeEnum def_type;
1912 const char *def_value;
1916 MONO_ARCH_SAVE_REGS;
1918 mono_class_init (field->parent);
1920 t = mono_field_get_type_checked (field, &error);
1921 if (!mono_error_ok (&error))
1922 mono_error_raise_exception (&error);
1924 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1925 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1927 if (field->parent->image->dynamic) {
1929 g_assert_not_reached ();
1932 def_value = mono_class_get_field_default_value (field, &def_type);
1933 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1934 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1936 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1940 case MONO_TYPE_BOOLEAN:
1943 case MONO_TYPE_CHAR:
1951 case MONO_TYPE_R8: {
1954 /* boxed value type */
1955 t = g_new0 (MonoType, 1);
1957 klass = mono_class_from_mono_type (t);
1959 o = mono_object_new (domain, klass);
1960 v = ((gchar *) o) + sizeof (MonoObject);
1961 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1964 case MONO_TYPE_STRING:
1965 case MONO_TYPE_CLASS:
1966 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1969 g_assert_not_reached ();
1975 ICALL_EXPORT MonoReflectionType*
1976 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1979 MonoClassField *field = ref_field->field;
1980 MonoType *type = mono_field_get_type_checked (field, &error);
1981 if (!mono_error_ok (&error))
1982 mono_error_raise_exception (&error);
1983 return mono_type_get_object (mono_object_domain (ref_field), type);
1986 ICALL_EXPORT MonoReflectionType*
1987 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1989 MonoMethod *method = rmethod->method.method;
1991 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1994 /* From MonoProperty.cs */
1996 PInfo_Attributes = 1,
1997 PInfo_GetMethod = 1 << 1,
1998 PInfo_SetMethod = 1 << 2,
1999 PInfo_ReflectedType = 1 << 3,
2000 PInfo_DeclaringType = 1 << 4,
2005 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2007 MonoDomain *domain = mono_object_domain (property);
2009 MONO_ARCH_SAVE_REGS;
2011 if ((req_info & PInfo_ReflectedType) != 0)
2012 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2013 if ((req_info & PInfo_DeclaringType) != 0)
2014 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2016 if ((req_info & PInfo_Name) != 0)
2017 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2019 if ((req_info & PInfo_Attributes) != 0)
2020 info->attrs = property->property->attrs;
2022 if ((req_info & PInfo_GetMethod) != 0)
2023 MONO_STRUCT_SETREF (info, get, property->property->get ?
2024 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2026 if ((req_info & PInfo_SetMethod) != 0)
2027 MONO_STRUCT_SETREF (info, set, property->property->set ?
2028 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2030 * There may be other methods defined for properties, though, it seems they are not exposed
2031 * in the reflection API
2036 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2038 MonoDomain *domain = mono_object_domain (event);
2040 MONO_ARCH_SAVE_REGS;
2042 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2043 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2045 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2046 info->attrs = event->event->attrs;
2047 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2048 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2049 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2051 #ifndef MONO_SMALL_CONFIG
2052 if (event->event->other) {
2054 while (event->event->other [n])
2056 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2058 for (i = 0; i < n; i++)
2059 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2065 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2070 mono_class_setup_interfaces (klass, error);
2071 if (!mono_error_ok (error))
2074 for (i = 0; i < klass->interface_count; i++) {
2075 ic = klass->interfaces [i];
2076 g_hash_table_insert (ifaces, ic, ic);
2078 collect_interfaces (ic, ifaces, error);
2079 if (!mono_error_ok (error))
2085 MonoArray *iface_array;
2086 MonoGenericContext *context;
2090 } FillIfaceArrayData;
2093 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2095 FillIfaceArrayData *data = user_data;
2096 MonoClass *ic = key;
2097 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2099 if (!mono_error_ok (data->error))
2102 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2103 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2104 if (!mono_error_ok (data->error))
2108 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2111 mono_metadata_free_type (inflated);
2114 ICALL_EXPORT MonoArray*
2115 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2118 MonoClass *class = mono_class_from_mono_type (type->type);
2120 FillIfaceArrayData data = { 0 };
2123 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2125 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2126 data.context = mono_class_get_context (class);
2127 class = class->generic_class->container_class;
2130 for (parent = class; parent; parent = parent->parent) {
2131 mono_class_setup_interfaces (parent, &error);
2132 if (!mono_error_ok (&error))
2134 collect_interfaces (parent, iface_hash, &error);
2135 if (!mono_error_ok (&error))
2139 data.error = &error;
2140 data.domain = mono_object_domain (type);
2142 len = g_hash_table_size (iface_hash);
2144 g_hash_table_destroy (iface_hash);
2145 if (!data.domain->empty_types)
2146 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2147 return data.domain->empty_types;
2150 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2151 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2152 if (!mono_error_ok (&error))
2155 g_hash_table_destroy (iface_hash);
2156 return data.iface_array;
2159 g_hash_table_destroy (iface_hash);
2160 mono_error_raise_exception (&error);
2165 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2167 gboolean variance_used;
2168 MonoClass *class = mono_class_from_mono_type (type->type);
2169 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2170 MonoReflectionMethod *member;
2173 int i = 0, len, ioffset;
2176 MONO_ARCH_SAVE_REGS;
2177 mono_class_init_or_throw (class);
2178 mono_class_init_or_throw (iclass);
2180 mono_class_setup_vtable (class);
2182 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2186 len = mono_class_num_methods (iclass);
2187 domain = mono_object_domain (type);
2188 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2189 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2191 while ((method = mono_class_get_methods (iclass, &iter))) {
2192 member = mono_method_get_object (domain, method, iclass);
2193 mono_array_setref (*methods, i, member);
2194 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2195 mono_array_setref (*targets, i, member);
2202 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2204 MonoClass *klass = mono_class_from_mono_type (type->type);
2205 mono_class_init_or_throw (klass);
2207 if (klass->image->dynamic) {
2208 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2209 *packing = tb->packing_size;
2210 *size = tb->class_size;
2212 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2216 ICALL_EXPORT MonoReflectionType*
2217 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2221 MONO_ARCH_SAVE_REGS;
2223 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2224 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2226 class = mono_class_from_mono_type (type->type);
2227 mono_class_init_or_throw (class);
2229 // GetElementType should only return a type for:
2230 // Array Pointer PassedByRef
2231 if (type->type->byref)
2232 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2233 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2234 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2235 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2236 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2241 ICALL_EXPORT MonoReflectionType*
2242 ves_icall_get_type_parent (MonoReflectionType *type)
2244 MonoClass *class = mono_class_from_mono_type (type->type);
2245 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2248 ICALL_EXPORT MonoBoolean
2249 ves_icall_type_ispointer (MonoReflectionType *type)
2251 MONO_ARCH_SAVE_REGS;
2253 return type->type->type == MONO_TYPE_PTR;
2256 ICALL_EXPORT MonoBoolean
2257 ves_icall_type_isprimitive (MonoReflectionType *type)
2259 MONO_ARCH_SAVE_REGS;
2261 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)));
2264 ICALL_EXPORT MonoBoolean
2265 ves_icall_type_isbyref (MonoReflectionType *type)
2267 MONO_ARCH_SAVE_REGS;
2269 return type->type->byref;
2272 ICALL_EXPORT MonoBoolean
2273 ves_icall_type_iscomobject (MonoReflectionType *type)
2275 MonoClass *klass = mono_class_from_mono_type (type->type);
2276 mono_class_init_or_throw (klass);
2278 return (klass && klass->is_com_object);
2281 ICALL_EXPORT MonoReflectionModule*
2282 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2284 MonoClass *class = mono_class_from_mono_type (type->type);
2285 return mono_module_get_object (mono_object_domain (type), class->image);
2288 ICALL_EXPORT MonoReflectionAssembly*
2289 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2291 MonoDomain *domain = mono_domain_get ();
2292 MonoClass *class = mono_class_from_mono_type (type->type);
2293 return mono_assembly_get_object (domain, class->image->assembly);
2296 ICALL_EXPORT MonoReflectionType*
2297 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2299 MonoDomain *domain = mono_domain_get ();
2302 MONO_ARCH_SAVE_REGS;
2304 if (type->type->byref)
2306 if (type->type->type == MONO_TYPE_VAR)
2307 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2308 else if (type->type->type == MONO_TYPE_MVAR)
2309 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2311 class = mono_class_from_mono_type (type->type)->nested_in;
2313 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2316 ICALL_EXPORT MonoString*
2317 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2319 MonoDomain *domain = mono_domain_get ();
2320 MonoClass *class = mono_class_from_mono_type (type->type);
2322 if (type->type->byref) {
2323 char *n = g_strdup_printf ("%s&", class->name);
2324 MonoString *res = mono_string_new (domain, n);
2330 return mono_string_new (domain, class->name);
2334 ICALL_EXPORT MonoString*
2335 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2337 MonoDomain *domain = mono_domain_get ();
2338 MonoClass *class = mono_class_from_mono_type (type->type);
2340 while (class->nested_in)
2341 class = class->nested_in;
2343 if (class->name_space [0] == '\0')
2346 return mono_string_new (domain, class->name_space);
2350 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2354 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2355 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2357 class = mono_class_from_mono_type (type->type);
2362 ICALL_EXPORT MonoArray*
2363 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2366 MonoClass *klass, *pklass;
2367 MonoDomain *domain = mono_object_domain (type);
2368 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2370 MONO_ARCH_SAVE_REGS;
2372 klass = mono_class_from_mono_type (type->type);
2374 if (klass->generic_container) {
2375 MonoGenericContainer *container = klass->generic_container;
2376 res = mono_array_new_specific (array_vtable, container->type_argc);
2377 for (i = 0; i < container->type_argc; ++i) {
2378 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2379 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2381 } else if (klass->generic_class) {
2382 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2383 res = mono_array_new_specific (array_vtable, inst->type_argc);
2384 for (i = 0; i < inst->type_argc; ++i)
2385 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2387 res = mono_array_new_specific (array_vtable, 0);
2392 ICALL_EXPORT gboolean
2393 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2396 MONO_ARCH_SAVE_REGS;
2398 if (!IS_MONOTYPE (type))
2401 if (type->type->byref)
2404 klass = mono_class_from_mono_type (type->type);
2405 return klass->generic_container != NULL;
2408 ICALL_EXPORT MonoReflectionType*
2409 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2412 MONO_ARCH_SAVE_REGS;
2414 if (type->type->byref)
2417 klass = mono_class_from_mono_type (type->type);
2419 if (klass->generic_container) {
2420 return type; /* check this one */
2422 if (klass->generic_class) {
2423 MonoClass *generic_class = klass->generic_class->container_class;
2426 tb = mono_class_get_ref_info (generic_class);
2428 if (generic_class->wastypebuilder && tb)
2431 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2436 ICALL_EXPORT MonoReflectionType*
2437 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2440 MonoType *geninst, **types;
2443 g_assert (IS_MONOTYPE (type));
2444 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2446 count = mono_array_length (type_array);
2447 types = g_new0 (MonoType *, count);
2449 for (i = 0; i < count; i++) {
2450 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2451 types [i] = t->type;
2454 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2459 class = mono_class_from_mono_type (geninst);
2461 /*we might inflate to the GTD*/
2462 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2463 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2465 return mono_type_get_object (mono_object_domain (type), geninst);
2468 ICALL_EXPORT gboolean
2469 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2472 MONO_ARCH_SAVE_REGS;
2474 if (type->type->byref)
2477 klass = mono_class_from_mono_type (type->type);
2479 return klass->generic_class != NULL;
2482 ICALL_EXPORT gboolean
2483 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2486 MONO_ARCH_SAVE_REGS;
2488 if (!IS_MONOTYPE (type))
2491 if (type->type->byref)
2494 klass = mono_class_from_mono_type (type->type);
2495 return klass->generic_class != NULL || klass->generic_container != NULL;
2499 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2501 MONO_ARCH_SAVE_REGS;
2503 if (!IS_MONOTYPE (type))
2506 if (is_generic_parameter (type->type))
2507 return mono_type_get_generic_param_num (type->type);
2511 ICALL_EXPORT GenericParameterAttributes
2512 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2514 MONO_ARCH_SAVE_REGS;
2516 g_assert (IS_MONOTYPE (type));
2517 g_assert (is_generic_parameter (type->type));
2518 return mono_generic_param_info (type->type->data.generic_param)->flags;
2521 ICALL_EXPORT MonoArray *
2522 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2524 MonoGenericParamInfo *param_info;
2530 MONO_ARCH_SAVE_REGS;
2532 g_assert (IS_MONOTYPE (type));
2534 domain = mono_object_domain (type);
2535 param_info = mono_generic_param_info (type->type->data.generic_param);
2536 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2539 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2540 for (i = 0; i < count; i++)
2541 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2547 ICALL_EXPORT MonoBoolean
2548 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2550 MONO_ARCH_SAVE_REGS;
2551 return is_generic_parameter (type->type);
2554 ICALL_EXPORT MonoBoolean
2555 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2557 MONO_ARCH_SAVE_REGS;
2558 return is_generic_parameter (tb->type.type);
2562 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2563 MonoReflectionType *t)
2565 enumtype->type = t->type;
2568 ICALL_EXPORT MonoReflectionMethod*
2569 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2570 MonoReflectionMethod* generic)
2577 MONO_ARCH_SAVE_REGS;
2579 domain = ((MonoObject *)type)->vtable->domain;
2581 klass = mono_class_from_mono_type (type->type);
2582 mono_class_init_or_throw (klass);
2585 while ((method = mono_class_get_methods (klass, &iter))) {
2586 if (method->token == generic->method->token)
2587 return mono_method_get_object (domain, method, klass);
2595 ICALL_EXPORT MonoReflectionMethod *
2596 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2599 MonoType *type = ref_type->type;
2601 MONO_ARCH_SAVE_REGS;
2603 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2604 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2605 if (type->type == MONO_TYPE_VAR)
2608 method = mono_type_get_generic_param_owner (type)->owner.method;
2610 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2613 ICALL_EXPORT MonoReflectionDllImportAttribute*
2614 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2616 static MonoClass *DllImportAttributeClass = NULL;
2617 MonoDomain *domain = mono_domain_get ();
2618 MonoReflectionDllImportAttribute *attr;
2619 MonoImage *image = method->klass->image;
2620 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2621 MonoTableInfo *tables = image->tables;
2622 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2623 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2624 guint32 im_cols [MONO_IMPLMAP_SIZE];
2625 guint32 scope_token;
2626 const char *import = NULL;
2627 const char *scope = NULL;
2630 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2633 if (!DllImportAttributeClass) {
2634 DllImportAttributeClass =
2635 mono_class_from_name (mono_defaults.corlib,
2636 "System.Runtime.InteropServices", "DllImportAttribute");
2637 g_assert (DllImportAttributeClass);
2640 if (method->klass->image->dynamic) {
2641 MonoReflectionMethodAux *method_aux =
2642 g_hash_table_lookup (
2643 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2645 import = method_aux->dllentry;
2646 scope = method_aux->dll;
2649 if (!import || !scope) {
2650 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2655 if (piinfo->implmap_idx) {
2656 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2658 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2659 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2660 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2661 scope = mono_metadata_string_heap (image, scope_token);
2664 flags = piinfo->piflags;
2666 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2668 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2669 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2670 attr->call_conv = (flags & 0x700) >> 8;
2671 attr->charset = ((flags & 0x6) >> 1) + 1;
2672 if (attr->charset == 1)
2674 attr->exact_spelling = (flags & 0x1) != 0;
2675 attr->set_last_error = (flags & 0x40) != 0;
2676 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2677 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2678 attr->preserve_sig = FALSE;
2683 ICALL_EXPORT MonoReflectionMethod *
2684 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2686 MonoMethodInflated *imethod;
2689 MONO_ARCH_SAVE_REGS;
2691 if (method->method->is_generic)
2694 if (!method->method->is_inflated)
2697 imethod = (MonoMethodInflated *) method->method;
2699 result = imethod->declaring;
2700 /* Not a generic method. */
2701 if (!result->is_generic)
2704 if (method->method->klass->image->dynamic) {
2705 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2706 MonoReflectionMethod *res;
2709 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2710 * the dynamic case as well ?
2712 mono_loader_lock ();
2713 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2714 mono_loader_unlock ();
2720 if (imethod->context.class_inst) {
2721 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2722 /*Generic methods gets the context of the GTD.*/
2723 if (mono_class_get_context (klass))
2724 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2727 return mono_method_get_object (mono_object_domain (method), result, NULL);
2730 ICALL_EXPORT gboolean
2731 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2733 MONO_ARCH_SAVE_REGS;
2735 return mono_method_signature (method->method)->generic_param_count != 0;
2738 ICALL_EXPORT gboolean
2739 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2741 MONO_ARCH_SAVE_REGS;
2743 return method->method->is_generic;
2746 ICALL_EXPORT MonoArray*
2747 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2752 MONO_ARCH_SAVE_REGS;
2754 domain = mono_object_domain (method);
2756 if (method->method->is_inflated) {
2757 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2760 count = inst->type_argc;
2761 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2763 for (i = 0; i < count; i++)
2764 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2770 count = mono_method_signature (method->method)->generic_param_count;
2771 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2773 for (i = 0; i < count; i++) {
2774 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2775 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2776 MonoClass *pklass = mono_class_from_generic_parameter (
2777 param, method->method->klass->image, TRUE);
2778 mono_array_setref (res, i,
2779 mono_type_get_object (domain, &pklass->byval_arg));
2785 ICALL_EXPORT MonoObject *
2786 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2789 * Invoke from reflection is supposed to always be a virtual call (the API
2790 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2791 * greater flexibility.
2793 MonoMethod *m = method->method;
2794 MonoMethodSignature *sig = mono_method_signature (m);
2798 MONO_ARCH_SAVE_REGS;
2802 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2803 mono_security_core_clr_ensure_reflection_access_method (m);
2805 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2806 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2807 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2812 if (!mono_object_isinst (this, m->klass)) {
2813 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2814 char *target_name = mono_type_get_full_name (m->klass);
2815 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2816 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2818 g_free (target_name);
2822 m = mono_object_get_virtual_method (this, m);
2823 /* must pass the pointer to the value for valuetype methods */
2824 if (m->klass->valuetype)
2825 obj = mono_object_unbox (this);
2826 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2827 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2832 if (sig->ret->byref) {
2833 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"));
2837 pcount = params? mono_array_length (params): 0;
2838 if (pcount != sig->param_count) {
2839 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2843 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2844 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."));
2848 if (m->klass->image->assembly->ref_only) {
2849 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."));
2853 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2856 intptr_t *lower_bounds;
2857 pcount = mono_array_length (params);
2858 lengths = alloca (sizeof (uintptr_t) * pcount);
2859 /* Note: the synthetized array .ctors have int32 as argument type */
2860 for (i = 0; i < pcount; ++i)
2861 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2863 if (m->klass->rank == pcount) {
2864 /* Only lengths provided. */
2865 lower_bounds = NULL;
2867 g_assert (pcount == (m->klass->rank * 2));
2868 /* lower bounds are first. */
2869 lower_bounds = (intptr_t*)lengths;
2870 lengths += m->klass->rank;
2873 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2875 return mono_runtime_invoke_array (m, obj, params, NULL);
2878 ICALL_EXPORT MonoObject *
2879 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2881 MonoDomain *domain = mono_object_domain (method);
2882 MonoMethod *m = method->method;
2883 MonoMethodSignature *sig = mono_method_signature (m);
2884 MonoArray *out_args;
2886 int i, j, outarg_count = 0;
2888 MONO_ARCH_SAVE_REGS;
2890 if (m->klass == mono_defaults.object_class) {
2892 if (!strcmp (m->name, "FieldGetter")) {
2893 MonoClass *k = this->vtable->klass;
2897 /* If this is a proxy, then it must be a CBO */
2898 if (k == mono_defaults.transparent_proxy_class) {
2899 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2900 this = tp->rp->unwrapped_server;
2902 k = this->vtable->klass;
2905 name = mono_array_get (params, MonoString *, 1);
2906 str = mono_string_to_utf8 (name);
2909 MonoClassField* field = mono_class_get_field_from_name (k, str);
2911 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2912 if (field_klass->valuetype)
2913 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2915 result = *((gpointer *)((char *)this + field->offset));
2917 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2918 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2919 mono_array_setref (out_args, 0, result);
2927 g_assert_not_reached ();
2929 } else if (!strcmp (m->name, "FieldSetter")) {
2930 MonoClass *k = this->vtable->klass;
2936 /* If this is a proxy, then it must be a CBO */
2937 if (k == mono_defaults.transparent_proxy_class) {
2938 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2939 this = tp->rp->unwrapped_server;
2941 k = this->vtable->klass;
2944 name = mono_array_get (params, MonoString *, 1);
2945 str = mono_string_to_utf8 (name);
2948 MonoClassField* field = mono_class_get_field_from_name (k, str);
2950 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2951 MonoObject *val = mono_array_get (params, gpointer, 2);
2953 if (field_klass->valuetype) {
2954 size = mono_type_size (field->type, &align);
2955 g_assert (size == mono_class_value_size (field_klass, NULL));
2956 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2958 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2961 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2962 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2972 g_assert_not_reached ();
2977 for (i = 0; i < mono_array_length (params); i++) {
2978 if (sig->params [i]->byref)
2982 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2984 /* handle constructors only for objects already allocated */
2985 if (!strcmp (method->method->name, ".ctor"))
2988 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2989 g_assert (!method->method->klass->valuetype);
2990 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2992 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2993 if (sig->params [i]->byref) {
2995 arg = mono_array_get (params, gpointer, i);
2996 mono_array_setref (out_args, j, arg);
3001 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3007 read_enum_value (char *mem, int type)
3011 return *(guint8*)mem;
3013 return *(gint8*)mem;
3015 return *(guint16*)mem;
3017 return *(gint16*)mem;
3019 return *(guint32*)mem;
3021 return *(gint32*)mem;
3023 return *(guint64*)mem;
3025 return *(gint64*)mem;
3027 g_assert_not_reached ();
3033 write_enum_value (char *mem, int type, guint64 value)
3037 case MONO_TYPE_I1: {
3038 guint8 *p = (guint8*)mem;
3043 case MONO_TYPE_I2: {
3044 guint16 *p = (void*)mem;
3049 case MONO_TYPE_I4: {
3050 guint32 *p = (void*)mem;
3055 case MONO_TYPE_I8: {
3056 guint64 *p = (void*)mem;
3061 g_assert_not_reached ();
3066 ICALL_EXPORT MonoObject *
3067 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3070 MonoClass *enumc, *objc;
3075 MONO_ARCH_SAVE_REGS;
3077 MONO_CHECK_ARG_NULL (enumType);
3078 MONO_CHECK_ARG_NULL (value);
3080 domain = mono_object_domain (enumType);
3081 enumc = mono_class_from_mono_type (enumType->type);
3083 mono_class_init_or_throw (enumc);
3085 objc = value->vtable->klass;
3087 if (!enumc->enumtype)
3088 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3089 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3090 mono_raise_exception (mono_get_exception_argument ("value", "The value passed in must be an enum base or an underlying type for an enum, such as an Int32."));
3092 etype = mono_class_enum_basetype (enumc);
3094 /* MS throws this for typebuilders */
3095 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3097 res = mono_object_new (domain, enumc);
3098 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3099 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3104 ICALL_EXPORT MonoObject *
3105 ves_icall_System_Enum_get_value (MonoObject *this)
3113 MONO_ARCH_SAVE_REGS;
3118 g_assert (this->vtable->klass->enumtype);
3120 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3121 res = mono_object_new (mono_object_domain (this), enumc);
3122 dst = (char *)res + sizeof (MonoObject);
3123 src = (char *)this + sizeof (MonoObject);
3124 size = mono_class_value_size (enumc, NULL);
3126 memcpy (dst, src, size);
3131 ICALL_EXPORT MonoReflectionType *
3132 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3137 MONO_ARCH_SAVE_REGS;
3139 klass = mono_class_from_mono_type (type->type);
3140 mono_class_init_or_throw (klass);
3142 etype = mono_class_enum_basetype (klass);
3144 /* MS throws this for typebuilders */
3145 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3147 return mono_type_get_object (mono_object_domain (type), etype);
3151 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3153 gpointer tdata = (char *)this + sizeof (MonoObject);
3154 gpointer odata = (char *)other + sizeof (MonoObject);
3155 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3156 g_assert (basetype);
3158 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3159 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3160 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3163 return me > other ? 1 : -1; \
3166 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3167 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3168 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3171 return me - other; \
3174 switch (basetype->type) {
3176 COMPARE_ENUM_VALUES (guint8);
3178 COMPARE_ENUM_VALUES (gint8);
3179 case MONO_TYPE_CHAR:
3181 COMPARE_ENUM_VALUES_RANGE (guint16);
3183 COMPARE_ENUM_VALUES (gint16);
3185 COMPARE_ENUM_VALUES (guint32);
3187 COMPARE_ENUM_VALUES (gint32);
3189 COMPARE_ENUM_VALUES (guint64);
3191 COMPARE_ENUM_VALUES (gint64);
3193 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3195 #undef COMPARE_ENUM_VALUES_RANGE
3196 #undef COMPARE_ENUM_VALUES
3201 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3203 gpointer data = (char *)this + sizeof (MonoObject);
3204 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3205 g_assert (basetype);
3207 switch (basetype->type) {
3209 return *((gint8*)data);
3211 return *((guint8*)data);
3212 case MONO_TYPE_CHAR:
3214 return *((guint16*)data);
3217 return *((gint16*)data);
3219 return *((guint32*)data);
3221 return *((gint32*)data);
3223 case MONO_TYPE_I8: {
3224 gint64 value = *((gint64*)data);
3225 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3228 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3234 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3236 MonoDomain *domain = mono_object_domain (type);
3237 MonoClass *enumc = mono_class_from_mono_type (type->type);
3238 guint j = 0, nvalues, crow;
3240 MonoClassField *field;
3242 MONO_ARCH_SAVE_REGS;
3244 mono_class_init_or_throw (enumc);
3246 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3247 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3248 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3249 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3253 while ((field = mono_class_get_fields (enumc, &iter))) {
3256 MonoTypeEnum def_type;
3258 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3260 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3262 if (mono_field_is_deleted (field))
3264 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3266 p = mono_class_get_field_default_value (field, &def_type);
3267 len = mono_metadata_decode_blob_size (p, &p);
3268 switch (mono_class_enum_basetype (enumc)->type) {
3271 mono_array_set (info->values, gchar, j, *p);
3273 case MONO_TYPE_CHAR:
3276 mono_array_set (info->values, gint16, j, read16 (p));
3280 mono_array_set (info->values, gint32, j, read32 (p));
3284 mono_array_set (info->values, gint64, j, read64 (p));
3287 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3294 BFLAGS_IgnoreCase = 1,
3295 BFLAGS_DeclaredOnly = 2,
3296 BFLAGS_Instance = 4,
3298 BFLAGS_Public = 0x10,
3299 BFLAGS_NonPublic = 0x20,
3300 BFLAGS_FlattenHierarchy = 0x40,
3301 BFLAGS_InvokeMethod = 0x100,
3302 BFLAGS_CreateInstance = 0x200,
3303 BFLAGS_GetField = 0x400,
3304 BFLAGS_SetField = 0x800,
3305 BFLAGS_GetProperty = 0x1000,
3306 BFLAGS_SetProperty = 0x2000,
3307 BFLAGS_ExactBinding = 0x10000,
3308 BFLAGS_SuppressChangeType = 0x20000,
3309 BFLAGS_OptionalParamBinding = 0x40000
3312 ICALL_EXPORT MonoReflectionField *
3313 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3316 MonoClass *startklass, *klass;
3318 MonoClassField *field;
3321 int (*compare_func) (const char *s1, const char *s2) = NULL;
3322 domain = ((MonoObject *)type)->vtable->domain;
3323 klass = startklass = mono_class_from_mono_type (type->type);
3326 mono_raise_exception (mono_get_exception_argument_null ("name"));
3327 if (type->type->byref)
3330 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3333 if (klass->exception_type != MONO_EXCEPTION_NONE)
3334 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3337 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3338 guint32 flags = mono_field_get_flags (field);
3341 if (mono_field_is_deleted_with_flags (field, flags))
3343 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3344 if (bflags & BFLAGS_Public)
3346 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3347 if (bflags & BFLAGS_NonPublic) {
3354 if (flags & FIELD_ATTRIBUTE_STATIC) {
3355 if (bflags & BFLAGS_Static)
3356 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3359 if (bflags & BFLAGS_Instance)
3366 utf8_name = mono_string_to_utf8 (name);
3368 if (compare_func (mono_field_get_name (field), utf8_name)) {
3374 return mono_field_get_object (domain, klass, field);
3376 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3382 ICALL_EXPORT MonoArray*
3383 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3386 MonoClass *startklass, *klass, *refklass;
3391 MonoClassField *field;
3392 MonoPtrArray tmp_array;
3394 MONO_ARCH_SAVE_REGS;
3396 domain = ((MonoObject *)type)->vtable->domain;
3397 if (type->type->byref)
3398 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3399 klass = startklass = mono_class_from_mono_type (type->type);
3400 refklass = mono_class_from_mono_type (reftype->type);
3402 mono_ptr_array_init (tmp_array, 2);
3405 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3406 mono_ptr_array_destroy (tmp_array);
3407 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3411 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3412 guint32 flags = mono_field_get_flags (field);
3414 if (mono_field_is_deleted_with_flags (field, flags))
3416 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3417 if (bflags & BFLAGS_Public)
3419 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3420 if (bflags & BFLAGS_NonPublic) {
3427 if (flags & FIELD_ATTRIBUTE_STATIC) {
3428 if (bflags & BFLAGS_Static)
3429 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3432 if (bflags & BFLAGS_Instance)
3438 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3439 mono_ptr_array_append (tmp_array, member);
3441 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3444 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3446 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3447 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3449 mono_ptr_array_destroy (tmp_array);
3455 method_nonpublic (MonoMethod* method, gboolean start_klass)
3457 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3458 case METHOD_ATTRIBUTE_ASSEM:
3459 return (start_klass || mono_defaults.generic_ilist_class);
3460 case METHOD_ATTRIBUTE_PRIVATE:
3462 case METHOD_ATTRIBUTE_PUBLIC:
3470 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3473 MonoClass *startklass;
3476 int len, match, nslots;
3477 /*FIXME, use MonoBitSet*/
3478 guint32 method_slots_default [8];
3479 guint32 *method_slots = NULL;
3480 int (*compare_func) (const char *s1, const char *s2) = NULL;
3482 array = g_ptr_array_new ();
3488 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3490 /* An optimization for calls made from Delegate:CreateDelegate () */
3491 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3492 method = mono_get_delegate_invoke (klass);
3493 if (mono_loader_get_last_error ())
3496 g_ptr_array_add (array, method);
3500 mono_class_setup_vtable (klass);
3501 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3504 if (is_generic_parameter (&klass->byval_arg))
3505 nslots = mono_class_get_vtable_size (klass->parent);
3507 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3508 if (nslots >= sizeof (method_slots_default) * 8) {
3509 method_slots = g_new0 (guint32, nslots / 32 + 1);
3511 method_slots = method_slots_default;
3512 memset (method_slots, 0, sizeof (method_slots_default));
3515 mono_class_setup_vtable (klass);
3516 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3520 while ((method = mono_class_get_methods (klass, &iter))) {
3522 if (method->slot != -1) {
3523 g_assert (method->slot < nslots);
3524 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3526 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3527 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3530 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3532 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3533 if (bflags & BFLAGS_Public)
3535 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3541 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3542 if (bflags & BFLAGS_Static)
3543 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3546 if (bflags & BFLAGS_Instance)
3554 if (compare_func (name, method->name))
3559 g_ptr_array_add (array, method);
3561 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3563 if (method_slots != method_slots_default)
3564 g_free (method_slots);
3569 if (method_slots != method_slots_default)
3570 g_free (method_slots);
3571 g_ptr_array_free (array, TRUE);
3573 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3574 *ex = mono_class_get_exception_for_failure (klass);
3576 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3577 mono_loader_clear_error ();
3582 ICALL_EXPORT MonoArray*
3583 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3585 static MonoClass *MethodInfo_array;
3588 MonoVTable *array_vtable;
3589 MonoException *ex = NULL;
3590 const char *mname = NULL;
3591 GPtrArray *method_array;
3592 MonoClass *klass, *refklass;
3595 if (!MethodInfo_array) {
3596 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3597 mono_memory_barrier ();
3598 MethodInfo_array = klass;
3601 klass = mono_class_from_mono_type (type->type);
3602 refklass = mono_class_from_mono_type (reftype->type);
3603 domain = ((MonoObject *)type)->vtable->domain;
3604 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3605 if (type->type->byref)
3606 return mono_array_new_specific (array_vtable, 0);
3609 mname = mono_string_to_utf8 (name);
3611 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3612 g_free ((char*)mname);
3614 mono_raise_exception (ex);
3616 res = mono_array_new_specific (array_vtable, method_array->len);
3619 for (i = 0; i < method_array->len; ++i) {
3620 MonoMethod *method = g_ptr_array_index (method_array, i);
3621 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3624 g_ptr_array_free (method_array, TRUE);
3628 ICALL_EXPORT MonoArray*
3629 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3632 static MonoClass *System_Reflection_ConstructorInfo;
3633 MonoClass *startklass, *klass, *refklass;
3638 gpointer iter = NULL;
3639 MonoPtrArray tmp_array;
3641 MONO_ARCH_SAVE_REGS;
3643 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3645 domain = ((MonoObject *)type)->vtable->domain;
3646 if (type->type->byref)
3647 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3648 klass = startklass = mono_class_from_mono_type (type->type);
3649 refklass = mono_class_from_mono_type (reftype->type);
3651 if (!System_Reflection_ConstructorInfo)
3652 System_Reflection_ConstructorInfo = mono_class_from_name (
3653 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3656 while ((method = mono_class_get_methods (klass, &iter))) {
3658 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3660 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3661 if (bflags & BFLAGS_Public)
3664 if (bflags & BFLAGS_NonPublic)
3670 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3671 if (bflags & BFLAGS_Static)
3672 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3675 if (bflags & BFLAGS_Instance)
3681 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3683 mono_ptr_array_append (tmp_array, member);
3686 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3688 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3689 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3691 mono_ptr_array_destroy (tmp_array);
3697 property_hash (gconstpointer data)
3699 MonoProperty *prop = (MonoProperty*)data;
3701 return g_str_hash (prop->name);
3705 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3707 // Properties are hide-by-name-and-signature
3708 if (!g_str_equal (prop1->name, prop2->name))
3711 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3713 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3719 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3724 return method_nonpublic (accessor, start_klass);
3727 ICALL_EXPORT MonoArray*
3728 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3732 static MonoClass *System_Reflection_PropertyInfo;
3733 MonoClass *startklass, *klass;
3739 gchar *propname = NULL;
3740 int (*compare_func) (const char *s1, const char *s2) = NULL;
3742 GHashTable *properties = NULL;
3743 MonoPtrArray tmp_array;
3745 MONO_ARCH_SAVE_REGS;
3747 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3749 if (!System_Reflection_PropertyInfo)
3750 System_Reflection_PropertyInfo = mono_class_from_name (
3751 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3753 domain = ((MonoObject *)type)->vtable->domain;
3754 if (type->type->byref)
3755 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3756 klass = startklass = mono_class_from_mono_type (type->type);
3759 propname = mono_string_to_utf8 (name);
3760 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3763 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3765 mono_class_setup_vtable (klass);
3766 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3770 while ((prop = mono_class_get_properties (klass, &iter))) {
3776 flags = method->flags;
3779 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3780 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3781 if (bflags & BFLAGS_Public)
3783 } else if (bflags & BFLAGS_NonPublic) {
3784 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3785 property_accessor_nonpublic(prop->set, startklass == klass)) {
3792 if (flags & METHOD_ATTRIBUTE_STATIC) {
3793 if (bflags & BFLAGS_Static)
3794 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3797 if (bflags & BFLAGS_Instance)
3806 if (compare_func (propname, prop->name))
3810 if (g_hash_table_lookup (properties, prop))
3813 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3815 g_hash_table_insert (properties, prop, prop);
3817 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3820 g_hash_table_destroy (properties);
3823 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3824 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3825 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3827 mono_ptr_array_destroy (tmp_array);
3833 g_hash_table_destroy (properties);
3836 mono_ptr_array_destroy (tmp_array);
3838 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3839 ex = mono_class_get_exception_for_failure (klass);
3841 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3842 mono_loader_clear_error ();
3844 mono_raise_exception (ex);
3848 ICALL_EXPORT MonoReflectionEvent *
3849 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3852 MonoClass *klass, *startklass;
3857 int (*compare_func) (const char *s1, const char *s2);
3859 MONO_ARCH_SAVE_REGS;
3861 event_name = mono_string_to_utf8 (name);
3862 if (type->type->byref)
3864 klass = startklass = mono_class_from_mono_type (type->type);
3865 domain = mono_object_domain (type);
3867 mono_class_init_or_throw (klass);
3869 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3871 if (klass->exception_type != MONO_EXCEPTION_NONE)
3872 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3875 while ((event = mono_class_get_events (klass, &iter))) {
3876 if (compare_func (event->name, event_name))
3879 method = event->add;
3881 method = event->remove;
3883 method = event->raise;
3885 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3886 if (!(bflags & BFLAGS_Public))
3889 if (!(bflags & BFLAGS_NonPublic))
3891 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3895 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3896 if (!(bflags & BFLAGS_Static))
3898 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3901 if (!(bflags & BFLAGS_Instance))
3905 if (!(bflags & BFLAGS_NonPublic))
3908 g_free (event_name);
3909 return mono_event_get_object (domain, startklass, event);
3912 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3915 g_free (event_name);
3919 ICALL_EXPORT MonoArray*
3920 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3924 static MonoClass *System_Reflection_EventInfo;
3925 MonoClass *startklass, *klass;
3932 MonoPtrArray tmp_array;
3934 MONO_ARCH_SAVE_REGS;
3936 mono_ptr_array_init (tmp_array, 4);
3938 if (!System_Reflection_EventInfo)
3939 System_Reflection_EventInfo = mono_class_from_name (
3940 mono_defaults.corlib, "System.Reflection", "EventInfo");
3942 domain = mono_object_domain (type);
3943 if (type->type->byref)
3944 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3945 klass = startklass = mono_class_from_mono_type (type->type);
3948 mono_class_setup_vtable (klass);
3949 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3953 while ((event = mono_class_get_events (klass, &iter))) {
3955 method = event->add;
3957 method = event->remove;
3959 method = event->raise;
3961 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3962 if (bflags & BFLAGS_Public)
3964 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3965 if (bflags & BFLAGS_NonPublic)
3970 if (bflags & BFLAGS_NonPublic)
3976 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3977 if (bflags & BFLAGS_Static)
3978 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3981 if (bflags & BFLAGS_Instance)
3986 if (bflags & BFLAGS_Instance)
3990 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3992 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3995 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3997 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3998 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4000 mono_ptr_array_destroy (tmp_array);
4005 mono_ptr_array_destroy (tmp_array);
4006 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4007 ex = mono_class_get_exception_for_failure (klass);
4009 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4010 mono_loader_clear_error ();
4012 mono_raise_exception (ex);
4016 ICALL_EXPORT MonoReflectionType *
4017 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4025 MONO_ARCH_SAVE_REGS;
4028 mono_raise_exception (mono_get_exception_argument_null ("name"));
4030 domain = ((MonoObject *)type)->vtable->domain;
4031 if (type->type->byref)
4033 klass = mono_class_from_mono_type (type->type);
4035 str = mono_string_to_utf8 (name);
4038 if (klass->exception_type != MONO_EXCEPTION_NONE)
4039 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4042 * If a nested type is generic, return its generic type definition.
4043 * Note that this means that the return value is essentially a
4044 * nested type of the generic type definition of @klass.
4046 * A note in MSDN claims that a generic type definition can have
4047 * nested types that aren't generic. In any case, the container of that
4048 * nested type would be the generic type definition.
4050 if (klass->generic_class)
4051 klass = klass->generic_class->container_class;
4054 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4056 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4057 if (bflags & BFLAGS_Public)
4060 if (bflags & BFLAGS_NonPublic)
4065 if (strcmp (nested->name, str) == 0){
4067 return mono_type_get_object (domain, &nested->byval_arg);
4070 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4076 ICALL_EXPORT MonoArray*
4077 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4086 MonoPtrArray tmp_array;
4088 MONO_ARCH_SAVE_REGS;
4090 domain = ((MonoObject *)type)->vtable->domain;
4091 if (type->type->byref)
4092 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4093 klass = mono_class_from_mono_type (type->type);
4096 * If a nested type is generic, return its generic type definition.
4097 * Note that this means that the return value is essentially the set
4098 * of nested types of the generic type definition of @klass.
4100 * A note in MSDN claims that a generic type definition can have
4101 * nested types that aren't generic. In any case, the container of that
4102 * nested type would be the generic type definition.
4104 if (klass->generic_class)
4105 klass = klass->generic_class->container_class;
4107 mono_ptr_array_init (tmp_array, 1);
4109 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4111 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4112 if (bflags & BFLAGS_Public)
4115 if (bflags & BFLAGS_NonPublic)
4120 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4121 mono_ptr_array_append (tmp_array, member);
4124 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4126 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4127 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4129 mono_ptr_array_destroy (tmp_array);
4134 ICALL_EXPORT MonoReflectionType*
4135 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4138 MonoType *type = NULL;
4139 MonoTypeNameParse info;
4140 gboolean type_resolve;
4142 MONO_ARCH_SAVE_REGS;
4144 /* On MS.NET, this does not fire a TypeResolve event */
4145 type_resolve = TRUE;
4146 str = mono_string_to_utf8 (name);
4147 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4148 if (!mono_reflection_parse_type (str, &info)) {
4150 mono_reflection_free_type_info (&info);
4151 if (throwOnError) /* uhm: this is a parse error, though... */
4152 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4153 /*g_print ("failed parse\n");*/
4157 if (info.assembly.name) {
4159 mono_reflection_free_type_info (&info);
4161 /* 1.0 and 2.0 throw different exceptions */
4162 if (mono_defaults.generic_ilist_class)
4163 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4165 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4170 if (module != NULL) {
4172 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4177 if (assembly->assembly->dynamic) {
4178 /* Enumerate all modules */
4179 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4183 if (abuilder->modules) {
4184 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4185 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4186 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4192 if (!type && abuilder->loaded_modules) {
4193 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4194 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4195 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4202 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4204 mono_reflection_free_type_info (&info);
4206 MonoException *e = NULL;
4209 e = mono_get_exception_type_load (name, NULL);
4211 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4212 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4214 mono_loader_clear_error ();
4217 mono_raise_exception (e);
4220 } else if (mono_loader_get_last_error ()) {
4222 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4223 mono_loader_clear_error ();
4226 if (type->type == MONO_TYPE_CLASS) {
4227 MonoClass *klass = mono_type_get_class (type);
4229 if (mono_is_security_manager_active () && !klass->exception_type)
4230 /* Some security problems are detected during generic vtable construction */
4231 mono_class_setup_vtable (klass);
4232 /* need to report exceptions ? */
4233 if (throwOnError && klass->exception_type) {
4234 /* report SecurityException (or others) that occured when loading the assembly */
4235 MonoException *exc = mono_class_get_exception_for_failure (klass);
4236 mono_loader_clear_error ();
4237 mono_raise_exception (exc);
4238 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4243 /* g_print ("got it\n"); */
4244 return mono_type_get_object (mono_object_domain (assembly), type);
4248 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4251 gchar *shadow_ini_file;
4254 /* Check for shadow-copied assembly */
4255 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4256 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4258 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4259 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4265 g_free (shadow_ini_file);
4266 if (content != NULL) {
4269 *filename = content;
4276 ICALL_EXPORT MonoString *
4277 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4279 MonoDomain *domain = mono_object_domain (assembly);
4280 MonoAssembly *mass = assembly->assembly;
4281 MonoString *res = NULL;
4286 MONO_ARCH_SAVE_REGS;
4288 if (g_path_is_absolute (mass->image->name)) {
4289 absolute = g_strdup (mass->image->name);
4290 dirname = g_path_get_dirname (absolute);
4292 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4293 dirname = g_strdup (mass->basedir);
4296 replace_shadow_path (domain, dirname, &absolute);
4301 for (i = strlen (absolute) - 1; i >= 0; i--)
4302 if (absolute [i] == '\\')
4307 uri = g_filename_to_uri (absolute, NULL, NULL);
4309 const char *prepend = "file://";
4311 if (*absolute == '/' && *(absolute + 1) == '/') {
4314 prepend = "file:///";
4317 uri = g_strconcat (prepend, absolute, NULL);
4321 res = mono_string_new (domain, uri);
4328 ICALL_EXPORT MonoBoolean
4329 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4331 MonoAssembly *mass = assembly->assembly;
4333 MONO_ARCH_SAVE_REGS;
4335 return mass->in_gac;
4338 ICALL_EXPORT MonoReflectionAssembly*
4339 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4343 MonoImageOpenStatus status;
4345 MONO_ARCH_SAVE_REGS;
4347 name = mono_string_to_utf8 (mname);
4348 res = mono_assembly_load_with_partial_name (name, &status);
4354 return mono_assembly_get_object (mono_domain_get (), res);
4357 ICALL_EXPORT MonoString *
4358 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4360 MonoDomain *domain = mono_object_domain (assembly);
4363 MONO_ARCH_SAVE_REGS;
4365 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4370 ICALL_EXPORT MonoBoolean
4371 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4373 MONO_ARCH_SAVE_REGS;
4375 return assembly->assembly->ref_only;
4378 ICALL_EXPORT MonoString *
4379 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4381 MonoDomain *domain = mono_object_domain (assembly);
4383 MONO_ARCH_SAVE_REGS;
4385 return mono_string_new (domain, assembly->assembly->image->version);
4388 ICALL_EXPORT MonoReflectionMethod*
4389 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4391 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4393 MONO_ARCH_SAVE_REGS;
4397 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4400 ICALL_EXPORT MonoReflectionModule*
4401 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4403 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4406 ICALL_EXPORT MonoArray*
4407 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4409 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4410 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4414 MONO_ARCH_SAVE_REGS;
4416 for (i = 0; i < table->rows; ++i) {
4417 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4418 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4424 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4426 static MonoClass *System_Version = NULL;
4427 static MonoMethod *create_version = NULL;
4431 if (!System_Version) {
4432 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4433 g_assert (System_Version);
4436 if (!create_version) {
4437 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4438 create_version = mono_method_desc_search_in_class (desc, System_Version);
4439 g_assert (create_version);
4440 mono_method_desc_free (desc);
4446 args [3] = &revision;
4447 result = mono_object_new (domain, System_Version);
4448 mono_runtime_invoke (create_version, result, args, NULL);
4453 ICALL_EXPORT MonoArray*
4454 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4456 static MonoClass *System_Reflection_AssemblyName;
4458 MonoDomain *domain = mono_object_domain (assembly);
4460 static MonoMethod *create_culture = NULL;
4461 MonoImage *image = assembly->assembly->image;
4464 MONO_ARCH_SAVE_REGS;
4466 if (!System_Reflection_AssemblyName)
4467 System_Reflection_AssemblyName = mono_class_from_name (
4468 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4470 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4473 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4475 if (count > 0 && !create_culture) {
4476 MonoMethodDesc *desc = mono_method_desc_new (
4477 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4478 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4479 g_assert (create_culture);
4480 mono_method_desc_free (desc);
4483 for (i = 0; i < count; i++) {
4484 MonoReflectionAssemblyName *aname;
4485 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4487 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4489 aname = (MonoReflectionAssemblyName *) mono_object_new (
4490 domain, System_Reflection_AssemblyName);
4492 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4494 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4495 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4496 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4497 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4498 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4499 aname->versioncompat = 1; /* SameMachine (default) */
4500 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4501 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4503 if (create_culture) {
4505 MonoBoolean assembly_ref = 1;
4506 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4507 args [1] = &assembly_ref;
4508 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4511 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4512 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4513 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4515 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4516 /* public key token isn't copied - the class library will
4517 automatically generate it from the public key if required */
4518 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4519 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4521 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4522 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4525 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4528 /* note: this function doesn't return the codebase on purpose (i.e. it can
4529 be used under partial trust as path information isn't present). */
4531 mono_array_setref (result, i, aname);
4542 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4544 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4546 mono_array_setref (info->res, info->idx, name);
4550 ICALL_EXPORT MonoArray*
4551 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4553 MonoImage *img = assembly->assembly->image;
4558 MONO_ARCH_SAVE_REGS;
4560 mono_image_lock (img);
4561 mono_image_init_name_cache (img);
4564 len = g_hash_table_size (img->name_cache);
4565 mono_image_unlock (img);
4567 /*we can't create objects holding the image lock */
4568 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4570 mono_image_lock (img);
4571 /*len might have changed, create a new array*/
4572 if (len != g_hash_table_size (img->name_cache))
4577 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4578 mono_image_unlock (img);
4583 /* move this in some file in mono/util/ */
4585 g_concat_dir_and_file (const char *dir, const char *file)
4587 g_return_val_if_fail (dir != NULL, NULL);
4588 g_return_val_if_fail (file != NULL, NULL);
4591 * If the directory name doesn't have a / on the end, we need
4592 * to add one so we get a proper path to the file
4594 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4595 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4597 return g_strconcat (dir, file, NULL);
4601 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4603 char *n = mono_string_to_utf8 (name);
4604 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4606 guint32 cols [MONO_MANIFEST_SIZE];
4607 guint32 impl, file_idx;
4611 MONO_ARCH_SAVE_REGS;
4613 for (i = 0; i < table->rows; ++i) {
4614 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4615 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4616 if (strcmp (val, n) == 0)
4620 if (i == table->rows)
4623 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4626 * this code should only be called after obtaining the
4627 * ResourceInfo and handling the other cases.
4629 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4630 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4632 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4637 module = assembly->assembly->image;
4639 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4641 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4644 ICALL_EXPORT gboolean
4645 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4647 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4649 guint32 cols [MONO_MANIFEST_SIZE];
4650 guint32 file_cols [MONO_FILE_SIZE];
4654 MONO_ARCH_SAVE_REGS;
4656 n = mono_string_to_utf8 (name);
4657 for (i = 0; i < table->rows; ++i) {
4658 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4659 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4660 if (strcmp (val, n) == 0)
4664 if (i == table->rows)
4667 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4668 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4671 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4672 case MONO_IMPLEMENTATION_FILE:
4673 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4674 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4675 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4676 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4677 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4678 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4681 info->location = RESOURCE_LOCATION_EMBEDDED;
4684 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4685 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4686 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4687 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4688 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4689 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4691 mono_raise_exception (ex);
4693 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4695 /* Obtain info recursively */
4696 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4697 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4700 case MONO_IMPLEMENTATION_EXP_TYPE:
4701 g_assert_not_reached ();
4709 ICALL_EXPORT MonoObject*
4710 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4712 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4713 MonoArray *result = NULL;
4718 MONO_ARCH_SAVE_REGS;
4720 /* check hash if needed */
4722 n = mono_string_to_utf8 (name);
4723 for (i = 0; i < table->rows; ++i) {
4724 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4725 if (strcmp (val, n) == 0) {
4728 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4729 fn = mono_string_new (mono_object_domain (assembly), n);
4731 return (MonoObject*)fn;
4739 for (i = 0; i < table->rows; ++i) {
4740 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4744 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4747 for (i = 0; i < table->rows; ++i) {
4748 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4749 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4750 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4751 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4756 return (MonoObject*)result;
4759 ICALL_EXPORT MonoArray*
4760 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4762 MonoDomain *domain = mono_domain_get();
4765 int i, j, file_count = 0;
4766 MonoImage **modules;
4767 guint32 module_count, real_module_count;
4768 MonoTableInfo *table;
4769 guint32 cols [MONO_FILE_SIZE];
4770 MonoImage *image = assembly->assembly->image;
4772 g_assert (image != NULL);
4773 g_assert (!assembly->assembly->dynamic);
4775 table = &image->tables [MONO_TABLE_FILE];
4776 file_count = table->rows;
4778 modules = image->modules;
4779 module_count = image->module_count;
4781 real_module_count = 0;
4782 for (i = 0; i < module_count; ++i)
4784 real_module_count ++;
4786 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4787 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4789 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4791 for (i = 0; i < module_count; ++i)
4793 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4797 for (i = 0; i < file_count; ++i, ++j) {
4798 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4799 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4800 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4802 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4804 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4805 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4807 mono_array_setref (res, j, mono_module_get_object (domain, m));
4814 ICALL_EXPORT MonoReflectionMethod*
4815 ves_icall_GetCurrentMethod (void)
4817 MonoMethod *m = mono_method_get_last_managed ();
4819 while (m->is_inflated)
4820 m = ((MonoMethodInflated*)m)->declaring;
4822 return mono_method_get_object (mono_domain_get (), m, NULL);
4827 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4830 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4831 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4832 //method is inflated, we should inflate it on the other class
4833 MonoGenericContext ctx;
4834 ctx.method_inst = inflated->context.method_inst;
4835 ctx.class_inst = inflated->context.class_inst;
4836 if (klass->generic_class)
4837 ctx.class_inst = klass->generic_class->context.class_inst;
4838 else if (klass->generic_container)
4839 ctx.class_inst = klass->generic_container->context.class_inst;
4840 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4843 mono_class_setup_methods (method->klass);
4844 if (method->klass->exception_type)
4846 for (i = 0; i < method->klass->method.count; ++i) {
4847 if (method->klass->methods [i] == method) {
4852 mono_class_setup_methods (klass);
4853 if (klass->exception_type)
4855 g_assert (offset >= 0 && offset < klass->method.count);
4856 return klass->methods [offset];
4859 ICALL_EXPORT MonoReflectionMethod*
4860 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4864 klass = mono_class_from_mono_type (type);
4865 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4867 if (method->klass != klass) {
4868 method = mono_method_get_equivalent_method (method, klass);
4873 klass = method->klass;
4874 return mono_method_get_object (mono_domain_get (), method, klass);
4877 ICALL_EXPORT MonoReflectionMethod*
4878 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4880 return mono_method_get_object (mono_domain_get (), method, NULL);
4883 ICALL_EXPORT MonoReflectionMethodBody*
4884 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4886 return mono_method_body_get_object (mono_domain_get (), method);
4889 ICALL_EXPORT MonoReflectionAssembly*
4890 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4892 MonoMethod *dest = NULL;
4894 MONO_ARCH_SAVE_REGS;
4896 mono_stack_walk_no_il (get_executing, &dest);
4897 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4901 ICALL_EXPORT MonoReflectionAssembly*
4902 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4904 MonoDomain* domain = mono_domain_get ();
4906 MONO_ARCH_SAVE_REGS;
4908 if (!domain->entry_assembly)
4911 return mono_assembly_get_object (domain, domain->entry_assembly);
4914 ICALL_EXPORT MonoReflectionAssembly*
4915 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4920 MONO_ARCH_SAVE_REGS;
4923 mono_stack_walk_no_il (get_executing, &dest);
4925 mono_stack_walk_no_il (get_caller, &dest);
4928 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4931 ICALL_EXPORT MonoString *
4932 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4933 gboolean assembly_qualified)
4935 MonoDomain *domain = mono_object_domain (object);
4936 MonoTypeNameFormat format;
4941 format = assembly_qualified ?
4942 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4943 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4945 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4947 name = mono_type_get_name_full (object->type, format);
4951 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4956 res = mono_string_new (domain, name);
4963 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4965 MonoClass *klass = mono_class_from_mono_type (this->type);
4966 mono_class_init_or_throw (klass);
4967 return mono_security_core_clr_class_level (klass);
4971 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4973 static MonoMethod *create_culture = NULL;
4976 const char *pkey_ptr;
4978 MonoBoolean assembly_ref = 0;
4980 MONO_ARCH_SAVE_REGS;
4982 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4983 aname->major = name->major;
4984 aname->minor = name->minor;
4985 aname->build = name->build;
4986 aname->flags = name->flags;
4987 aname->revision = name->revision;
4988 aname->hashalg = name->hash_alg;
4989 aname->versioncompat = 1; /* SameMachine (default) */
4990 aname->processor_architecture = name->arch;
4992 if (by_default_version)
4993 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4996 if (absolute != NULL && *absolute != '\0') {
4997 const gchar *prepend = "file://";
5000 codebase = g_strdup (absolute);
5005 for (i = strlen (codebase) - 1; i >= 0; i--)
5006 if (codebase [i] == '\\')
5009 if (*codebase == '/' && *(codebase + 1) == '/') {
5012 prepend = "file:///";
5016 result = g_strconcat (prepend, codebase, NULL);
5022 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5026 if (!create_culture) {
5027 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5028 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5029 g_assert (create_culture);
5030 mono_method_desc_free (desc);
5033 if (name->culture) {
5034 args [0] = mono_string_new (domain, name->culture);
5035 args [1] = &assembly_ref;
5036 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5039 if (name->public_key) {
5040 pkey_ptr = (char*)name->public_key;
5041 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5043 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5044 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5045 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5046 } else if (default_publickey) {
5047 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5048 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5051 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5052 if (name->public_key_token [0]) {
5056 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5057 p = mono_array_addr (aname->keyToken, char, 0);
5059 for (i = 0, j = 0; i < 8; i++) {
5060 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5061 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5064 } else if (default_token) {
5065 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5069 ICALL_EXPORT MonoString *
5070 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5072 MonoDomain *domain = mono_object_domain (assembly);
5073 MonoAssembly *mass = assembly->assembly;
5077 name = mono_stringify_assembly_name (&mass->aname);
5078 res = mono_string_new (domain, name);
5085 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5088 MonoAssembly *mass = assembly->assembly;
5090 MONO_ARCH_SAVE_REGS;
5092 if (g_path_is_absolute (mass->image->name)) {
5093 fill_reflection_assembly_name (mono_object_domain (assembly),
5094 aname, &mass->aname, mass->image->name, TRUE,
5098 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5100 fill_reflection_assembly_name (mono_object_domain (assembly),
5101 aname, &mass->aname, absolute, TRUE, TRUE,
5108 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5111 MonoImageOpenStatus status = MONO_IMAGE_OK;
5114 MonoAssemblyName name;
5117 MONO_ARCH_SAVE_REGS;
5119 filename = mono_string_to_utf8 (fname);
5121 dirname = g_path_get_dirname (filename);
5122 replace_shadow_path (mono_domain_get (), dirname, &filename);
5125 image = mono_image_open (filename, &status);
5131 if (status == MONO_IMAGE_IMAGE_INVALID)
5132 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5134 exc = mono_get_exception_file_not_found2 (NULL, fname);
5135 mono_raise_exception (exc);
5138 res = mono_assembly_fill_assembly_name (image, &name);
5140 mono_image_close (image);
5142 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5145 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5149 mono_image_close (image);
5152 ICALL_EXPORT MonoBoolean
5153 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5154 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5156 MonoBoolean result = FALSE;
5157 MonoDeclSecurityEntry entry;
5159 /* SecurityAction.RequestMinimum */
5160 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5161 *minimum = entry.blob;
5162 *minLength = entry.size;
5165 /* SecurityAction.RequestOptional */
5166 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5167 *optional = entry.blob;
5168 *optLength = entry.size;
5171 /* SecurityAction.RequestRefuse */
5172 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5173 *refused = entry.blob;
5174 *refLength = entry.size;
5182 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5186 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5188 guint32 attrs, visibility;
5190 /* we start the count from 1 because we skip the special type <Module> */
5193 for (i = 1; i < tdef->rows; ++i) {
5194 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5195 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5196 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5200 count = tdef->rows - 1;
5202 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5203 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5205 for (i = 1; i < tdef->rows; ++i) {
5206 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5207 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5208 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5209 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5211 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5213 MonoLoaderError *error;
5216 error = mono_loader_get_last_error ();
5217 g_assert (error != NULL);
5219 ex = mono_loader_error_prepare_exception (error);
5220 mono_array_setref (*exceptions, count, ex);
5222 if (mono_loader_get_last_error ())
5223 mono_loader_clear_error ();
5231 ICALL_EXPORT MonoArray*
5232 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5234 MonoArray *res = NULL;
5235 MonoArray *exceptions = NULL;
5236 MonoImage *image = NULL;
5237 MonoTableInfo *table = NULL;
5240 int i, len, ex_count;
5242 MONO_ARCH_SAVE_REGS;
5244 domain = mono_object_domain (assembly);
5246 g_assert (!assembly->assembly->dynamic);
5247 image = assembly->assembly->image;
5248 table = &image->tables [MONO_TABLE_FILE];
5249 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5251 /* Append data from all modules in the assembly */
5252 for (i = 0; i < table->rows; ++i) {
5253 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5254 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5257 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5258 /* Append the new types to the end of the array */
5259 if (mono_array_length (res2) > 0) {
5261 MonoArray *res3, *ex3;
5263 len1 = mono_array_length (res);
5264 len2 = mono_array_length (res2);
5266 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5267 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5268 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5271 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5272 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5273 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5280 /* the ReflectionTypeLoadException must have all the types (Types property),
5281 * NULL replacing types which throws an exception. The LoaderException must
5282 * contain all exceptions for NULL items.
5285 len = mono_array_length (res);
5288 for (i = 0; i < len; i++) {
5289 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5293 klass = mono_type_get_class (t->type);
5294 if ((klass != NULL) && klass->exception_type) {
5295 /* keep the class in the list */
5296 list = g_list_append (list, klass);
5297 /* and replace Type with NULL */
5298 mono_array_setref (res, i, NULL);
5305 if (list || ex_count) {
5307 MonoException *exc = NULL;
5308 MonoArray *exl = NULL;
5309 int j, length = g_list_length (list) + ex_count;
5311 mono_loader_clear_error ();
5313 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5314 /* Types for which mono_class_get () succeeded */
5315 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5316 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5317 mono_array_setref (exl, i, exc);
5319 /* Types for which it don't */
5320 for (j = 0; j < mono_array_length (exceptions); ++j) {
5321 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5323 g_assert (i < length);
5324 mono_array_setref (exl, i, exc);
5331 exc = mono_get_exception_reflection_type_load (res, exl);
5332 mono_loader_clear_error ();
5333 mono_raise_exception (exc);
5339 ICALL_EXPORT gboolean
5340 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5342 MonoAssemblyName aname;
5343 MonoDomain *domain = mono_object_domain (name);
5345 gboolean is_version_defined;
5346 gboolean is_token_defined;
5348 aname.public_key = NULL;
5349 val = mono_string_to_utf8 (assname);
5350 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5351 g_free ((guint8*) aname.public_key);
5356 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5357 FALSE, is_token_defined);
5359 mono_assembly_name_free (&aname);
5360 g_free ((guint8*) aname.public_key);
5366 ICALL_EXPORT MonoReflectionType*
5367 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5369 MonoDomain *domain = mono_object_domain (module);
5372 MONO_ARCH_SAVE_REGS;
5374 g_assert (module->image);
5376 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5377 /* These images do not have a global type */
5380 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5381 return mono_type_get_object (domain, &klass->byval_arg);
5385 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5387 /*if (module->image)
5388 mono_image_close (module->image);*/
5391 ICALL_EXPORT MonoString*
5392 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5394 MonoDomain *domain = mono_object_domain (module);
5396 MONO_ARCH_SAVE_REGS;
5398 g_assert (module->image);
5399 return mono_string_new (domain, module->image->guid);
5402 ICALL_EXPORT gpointer
5403 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5406 if (module->image && module->image->is_module_handle)
5407 return module->image->raw_data;
5410 return (gpointer) (-1);
5414 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5416 if (image->dynamic) {
5417 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5418 *pe_kind = dyn->pe_kind;
5419 *machine = dyn->machine;
5422 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5423 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5428 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5430 return (image->md_version_major << 16) | (image->md_version_minor);
5433 ICALL_EXPORT MonoArray*
5434 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5436 MonoArray *exceptions;
5439 MONO_ARCH_SAVE_REGS;
5442 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5444 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5445 for (i = 0; i < mono_array_length (exceptions); ++i) {
5446 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5448 mono_raise_exception (ex);
5455 mono_memberref_is_method (MonoImage *image, guint32 token)
5457 if (!image->dynamic) {
5458 guint32 cols [MONO_MEMBERREF_SIZE];
5460 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5461 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5462 mono_metadata_decode_blob_size (sig, &sig);
5463 return (*sig != 0x6);
5465 MonoClass *handle_class;
5467 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5470 return mono_defaults.methodhandle_class == handle_class;
5475 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5478 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5479 mono_array_addr (type_args, MonoType*, 0));
5481 context->class_inst = NULL;
5483 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5484 mono_array_addr (method_args, MonoType*, 0));
5486 context->method_inst = NULL;
5489 ICALL_EXPORT MonoType*
5490 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5493 int table = mono_metadata_token_table (token);
5494 int index = mono_metadata_token_index (token);
5495 MonoGenericContext context;
5497 *error = ResolveTokenError_Other;
5499 /* Validate token */
5500 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5501 (table != MONO_TABLE_TYPESPEC)) {
5502 *error = ResolveTokenError_BadTable;
5506 if (image->dynamic) {
5507 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5508 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5509 return klass ? &klass->byval_arg : NULL;
5512 init_generic_context_from_args (&context, type_args, method_args);
5513 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5514 return klass ? &klass->byval_arg : NULL;
5517 if ((index <= 0) || (index > image->tables [table].rows)) {
5518 *error = ResolveTokenError_OutOfRange;
5522 init_generic_context_from_args (&context, type_args, method_args);
5523 klass = mono_class_get_full (image, token, &context);
5525 if (mono_loader_get_last_error ())
5526 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5529 return &klass->byval_arg;
5534 ICALL_EXPORT MonoMethod*
5535 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5537 int table = mono_metadata_token_table (token);
5538 int index = mono_metadata_token_index (token);
5539 MonoGenericContext context;
5542 *error = ResolveTokenError_Other;
5544 /* Validate token */
5545 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5546 (table != MONO_TABLE_MEMBERREF)) {
5547 *error = ResolveTokenError_BadTable;
5551 if (image->dynamic) {
5552 if (table == MONO_TABLE_METHOD)
5553 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5555 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5556 *error = ResolveTokenError_BadTable;
5560 init_generic_context_from_args (&context, type_args, method_args);
5561 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5564 if ((index <= 0) || (index > image->tables [table].rows)) {
5565 *error = ResolveTokenError_OutOfRange;
5568 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5569 *error = ResolveTokenError_BadTable;
5573 init_generic_context_from_args (&context, type_args, method_args);
5574 method = mono_get_method_full (image, token, NULL, &context);
5576 if (mono_loader_get_last_error ())
5577 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5582 ICALL_EXPORT MonoString*
5583 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5585 int index = mono_metadata_token_index (token);
5587 *error = ResolveTokenError_Other;
5589 /* Validate token */
5590 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5591 *error = ResolveTokenError_BadTable;
5596 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5598 if ((index <= 0) || (index >= image->heap_us.size)) {
5599 *error = ResolveTokenError_OutOfRange;
5603 /* FIXME: What to do if the index points into the middle of a string ? */
5605 return mono_ldstr (mono_domain_get (), image, index);
5608 ICALL_EXPORT MonoClassField*
5609 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5612 int table = mono_metadata_token_table (token);
5613 int index = mono_metadata_token_index (token);
5614 MonoGenericContext context;
5615 MonoClassField *field;
5617 *error = ResolveTokenError_Other;
5619 /* Validate token */
5620 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5621 *error = ResolveTokenError_BadTable;
5625 if (image->dynamic) {
5626 if (table == MONO_TABLE_FIELD)
5627 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5629 if (mono_memberref_is_method (image, token)) {
5630 *error = ResolveTokenError_BadTable;
5634 init_generic_context_from_args (&context, type_args, method_args);
5635 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5638 if ((index <= 0) || (index > image->tables [table].rows)) {
5639 *error = ResolveTokenError_OutOfRange;
5642 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5643 *error = ResolveTokenError_BadTable;
5647 init_generic_context_from_args (&context, type_args, method_args);
5648 field = mono_field_from_token (image, token, &klass, &context);
5650 if (mono_loader_get_last_error ())
5651 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5657 ICALL_EXPORT MonoObject*
5658 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5660 int table = mono_metadata_token_table (token);
5662 *error = ResolveTokenError_Other;
5665 case MONO_TABLE_TYPEDEF:
5666 case MONO_TABLE_TYPEREF:
5667 case MONO_TABLE_TYPESPEC: {
5668 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5670 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5674 case MONO_TABLE_METHOD:
5675 case MONO_TABLE_METHODSPEC: {
5676 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5678 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5682 case MONO_TABLE_FIELD: {
5683 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5685 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5689 case MONO_TABLE_MEMBERREF:
5690 if (mono_memberref_is_method (image, token)) {
5691 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5693 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5698 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5700 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5707 *error = ResolveTokenError_BadTable;
5713 ICALL_EXPORT MonoArray*
5714 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5716 int table = mono_metadata_token_table (token);
5717 int idx = mono_metadata_token_index (token);
5718 MonoTableInfo *tables = image->tables;
5723 *error = ResolveTokenError_OutOfRange;
5725 /* FIXME: Support other tables ? */
5726 if (table != MONO_TABLE_STANDALONESIG)
5732 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5735 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5737 ptr = mono_metadata_blob_heap (image, sig);
5738 len = mono_metadata_decode_blob_size (ptr, &ptr);
5740 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5741 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5745 ICALL_EXPORT MonoReflectionType*
5746 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5749 int isbyref = 0, rank;
5750 char *str = mono_string_to_utf8 (smodifiers);
5753 MONO_ARCH_SAVE_REGS;
5755 klass = mono_class_from_mono_type (tb->type.type);
5757 /* logic taken from mono_reflection_parse_type(): keep in sync */
5761 if (isbyref) { /* only one level allowed by the spec */
5768 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5771 klass = mono_ptr_class_get (&klass->byval_arg);
5772 mono_class_init (klass);
5783 else if (*p != '*') { /* '*' means unknown lower bound */
5794 klass = mono_array_class_get (klass, rank);
5795 mono_class_init (klass);
5802 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5805 ICALL_EXPORT MonoBoolean
5806 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5811 MONO_ARCH_SAVE_REGS;
5814 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5820 check_for_invalid_type (MonoClass *klass)
5824 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5827 name = mono_type_get_full_name (klass);
5828 str = mono_string_new (mono_domain_get (), name);
5830 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5833 ICALL_EXPORT MonoReflectionType *
5834 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5836 MonoClass *klass, *aklass;
5838 MONO_ARCH_SAVE_REGS;
5840 klass = mono_class_from_mono_type (type->type);
5841 check_for_invalid_type (klass);
5843 if (rank == 0) //single dimentional array
5844 aklass = mono_array_class_get (klass, 1);
5846 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5848 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5851 ICALL_EXPORT MonoReflectionType *
5852 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5856 MONO_ARCH_SAVE_REGS;
5858 klass = mono_class_from_mono_type (type->type);
5859 mono_class_init_or_throw (klass);
5860 check_for_invalid_type (klass);
5862 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5865 ICALL_EXPORT MonoReflectionType *
5866 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5868 MonoClass *klass, *pklass;
5870 klass = mono_class_from_mono_type (type->type);
5871 mono_class_init_or_throw (klass);
5872 check_for_invalid_type (klass);
5874 pklass = mono_ptr_class_get (type->type);
5876 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5879 ICALL_EXPORT MonoObject *
5880 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5881 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5883 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5884 MonoObject *delegate;
5886 MonoMethod *method = info->method;
5888 MONO_ARCH_SAVE_REGS;
5890 mono_class_init_or_throw (delegate_class);
5892 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5894 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5895 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5899 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5901 if (method->dynamic) {
5902 /* Creating a trampoline would leak memory */
5903 func = mono_compile_method (method);
5905 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5906 method = mono_object_get_virtual_method (target, method);
5907 func = mono_create_ftnptr (mono_domain_get (),
5908 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5911 mono_delegate_ctor_with_method (delegate, target, func, method);
5917 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5919 /* Reset the invoke impl to the default one */
5920 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5924 * Magic number to convert a time which is relative to
5925 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5927 #define EPOCH_ADJUST ((guint64)62135596800LL)
5930 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5932 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5935 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5937 convert_to_absolute_date(SYSTEMTIME *date)
5939 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5940 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5941 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5942 /* from the calendar FAQ */
5943 int a = (14 - date->wMonth) / 12;
5944 int y = date->wYear - a;
5945 int m = date->wMonth + 12 * a - 2;
5946 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5948 /* d is now the day of the week for the first of the month (0 == Sunday) */
5950 int day_of_week = date->wDayOfWeek;
5952 /* set day_in_month to the first day in the month which falls on day_of_week */
5953 int day_in_month = 1 + (day_of_week - d);
5954 if (day_in_month <= 0)
5957 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5958 date->wDay = day_in_month + (date->wDay - 1) * 7;
5959 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5966 * Return's the offset from GMT of a local time.
5968 * tm is a local time
5969 * t is the same local time as seconds.
5972 gmt_offset(struct tm *tm, time_t t)
5974 #if defined (HAVE_TM_GMTOFF)
5975 return tm->tm_gmtoff;
5980 g.tm_isdst = tm->tm_isdst;
5982 return (int)difftime(t, t2);
5987 * This is heavily based on zdump.c from glibc 2.2.
5989 * * data[0]: start of daylight saving time (in DateTime ticks).
5990 * * data[1]: end of daylight saving time (in DateTime ticks).
5991 * * data[2]: utcoffset (in TimeSpan ticks).
5992 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5993 * * name[0]: name of this timezone when not daylight saving.
5994 * * name[1]: name of this timezone when daylight saving.
5996 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5997 * the class library allows years between 1 and 9999.
5999 * Returns true on success and zero on failure.
6001 ICALL_EXPORT guint32
6002 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6005 MonoDomain *domain = mono_domain_get ();
6006 struct tm start, tt;
6010 int is_daylight = 0, day;
6013 MONO_ARCH_SAVE_REGS;
6015 MONO_CHECK_ARG_NULL (data);
6016 MONO_CHECK_ARG_NULL (names);
6018 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
6019 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6022 * no info is better than crashing: we'll need our own tz data
6023 * to make this work properly, anyway. The range is probably
6024 * reduced to 1970 .. 2037 because that is what mktime is
6025 * guaranteed to support (we get into an infinite loop
6029 memset (&start, 0, sizeof (start));
6032 start.tm_year = year-1900;
6034 t = mktime (&start);
6036 if ((year < 1970) || (year > 2037) || (t == -1)) {
6038 tt = *localtime (&t);
6039 strftime (tzone, sizeof (tzone), "%Z", &tt);
6040 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6041 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6045 gmtoff = gmt_offset (&start, t);
6047 /* For each day of the year, calculate the tm_gmtoff. */
6048 for (day = 0; day < 365; day++) {
6051 tt = *localtime (&t);
6053 /* Daylight saving starts or ends here. */
6054 if (gmt_offset (&tt, t) != gmtoff) {
6058 /* Try to find the exact hour when daylight saving starts/ends. */
6062 tt1 = *localtime (&t1);
6063 } while (gmt_offset (&tt1, t1) != gmtoff);
6065 /* Try to find the exact minute when daylight saving starts/ends. */
6068 tt1 = *localtime (&t1);
6069 } while (gmt_offset (&tt1, t1) == gmtoff);
6071 strftime (tzone, sizeof (tzone), "%Z", &tt);
6073 /* Write data, if we're already in daylight saving, we're done. */
6075 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6076 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6082 memset (&end, 0, sizeof (end));
6083 end.tm_year = year-1900 + 1;
6088 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6089 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6090 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6091 mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
6095 /* This is only set once when we enter daylight saving. */
6096 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6097 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6099 gmtoff = gmt_offset (&tt, t);
6104 strftime (tzone, sizeof (tzone), "%Z", &tt);
6105 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6106 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6107 mono_array_set ((*data), gint64, 0, 0);
6108 mono_array_set ((*data), gint64, 1, 0);
6109 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6110 mono_array_set ((*data), gint64, 3, 0);
6115 MonoDomain *domain = mono_domain_get ();
6116 TIME_ZONE_INFORMATION tz_info;
6121 tz_id = GetTimeZoneInformation (&tz_info);
6122 if (tz_id == TIME_ZONE_ID_INVALID)
6125 MONO_CHECK_ARG_NULL (data);
6126 MONO_CHECK_ARG_NULL (names);
6128 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6129 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6131 for (i = 0; i < 32; ++i)
6132 if (!tz_info.DaylightName [i])
6134 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6135 for (i = 0; i < 32; ++i)
6136 if (!tz_info.StandardName [i])
6138 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6140 if ((year <= 1601) || (year > 30827)) {
6142 * According to MSDN, the MS time functions can't handle dates outside
6148 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6149 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6150 tz_info.StandardDate.wYear = year;
6151 convert_to_absolute_date(&tz_info.StandardDate);
6152 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6157 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6158 tz_info.DaylightDate.wYear = year;
6159 convert_to_absolute_date(&tz_info.DaylightDate);
6160 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6165 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6167 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6168 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6174 ICALL_EXPORT gpointer
6175 ves_icall_System_Object_obj_address (MonoObject *this)
6177 MONO_ARCH_SAVE_REGS;
6184 static inline gint32
6185 mono_array_get_byte_length (MonoArray *array)
6191 klass = array->obj.vtable->klass;
6193 if (array->bounds == NULL)
6194 length = array->max_length;
6197 for (i = 0; i < klass->rank; ++ i)
6198 length *= array->bounds [i].length;
6201 switch (klass->element_class->byval_arg.type) {
6204 case MONO_TYPE_BOOLEAN:
6208 case MONO_TYPE_CHAR:
6216 return length * sizeof (gpointer);
6227 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6229 MONO_ARCH_SAVE_REGS;
6231 return mono_array_get_byte_length (array);
6235 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6237 MONO_ARCH_SAVE_REGS;
6239 return mono_array_get (array, gint8, idx);
6243 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6245 MONO_ARCH_SAVE_REGS;
6247 mono_array_set (array, gint8, idx, value);
6250 ICALL_EXPORT MonoBoolean
6251 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6253 guint8 *src_buf, *dest_buf;
6255 MONO_ARCH_SAVE_REGS;
6257 /* This is called directly from the class libraries without going through the managed wrapper */
6258 MONO_CHECK_ARG_NULL (src);
6259 MONO_CHECK_ARG_NULL (dest);
6261 /* watch out for integer overflow */
6262 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6265 src_buf = (guint8 *)src->vector + src_offset;
6266 dest_buf = (guint8 *)dest->vector + dest_offset;
6269 memcpy (dest_buf, src_buf, count);
6271 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6276 ICALL_EXPORT MonoObject *
6277 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6279 MonoDomain *domain = mono_object_domain (this);
6281 MonoRealProxy *rp = ((MonoRealProxy *)this);
6282 MonoTransparentProxy *tp;
6286 MONO_ARCH_SAVE_REGS;
6288 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6289 tp = (MonoTransparentProxy*) res;
6291 MONO_OBJECT_SETREF (tp, rp, rp);
6292 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6293 klass = mono_class_from_mono_type (type);
6295 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6296 tp->remote_class = mono_remote_class (domain, class_name, klass);
6298 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6302 ICALL_EXPORT MonoReflectionType *
6303 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6305 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6308 /* System.Environment */
6311 ves_icall_System_Environment_get_UserName (void)
6313 MONO_ARCH_SAVE_REGS;
6315 /* using glib is more portable */
6316 return mono_string_new (mono_domain_get (), g_get_user_name ());
6320 ICALL_EXPORT MonoString *
6321 ves_icall_System_Environment_get_MachineName (void)
6323 #if defined (HOST_WIN32)
6328 len = MAX_COMPUTERNAME_LENGTH + 1;
6329 buf = g_new (gunichar2, len);
6332 if (GetComputerName (buf, (PDWORD) &len))
6333 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6337 #elif !defined(DISABLE_SOCKETS)
6341 if (gethostname (buf, sizeof (buf)) == 0)
6342 result = mono_string_new (mono_domain_get (), buf);
6348 return mono_string_new (mono_domain_get (), "mono");
6353 ves_icall_System_Environment_get_Platform (void)
6355 #if defined (TARGET_WIN32)
6358 #elif defined(__MACH__)
6361 // Notice that the value is hidden from user code, and only exposed
6362 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6363 // define and making assumptions based on Unix/128/4 values before there
6364 // was a MacOS define. Lots of code would assume that not-Unix meant
6365 // Windows, but in this case, it would be OSX.
6374 ICALL_EXPORT MonoString *
6375 ves_icall_System_Environment_get_NewLine (void)
6377 MONO_ARCH_SAVE_REGS;
6379 #if defined (HOST_WIN32)
6380 return mono_string_new (mono_domain_get (), "\r\n");
6382 return mono_string_new (mono_domain_get (), "\n");
6386 ICALL_EXPORT MonoString *
6387 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6392 MONO_ARCH_SAVE_REGS;
6397 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6398 value = g_getenv (utf8_name);
6405 return mono_string_new (mono_domain_get (), value);
6409 * There is no standard way to get at environ.
6412 #ifndef __MINGW32_VERSION
6413 #if defined(__APPLE__) && !defined (__arm__)
6414 /* Apple defines this in crt_externs.h but doesn't provide that header for
6415 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6416 * in fact exist on all implementations (so far)
6418 gchar ***_NSGetEnviron(void);
6419 #define environ (*_NSGetEnviron())
6427 ICALL_EXPORT MonoArray *
6428 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6439 env_strings = GetEnvironmentStrings();
6442 env_string = env_strings;
6443 while (*env_string != '\0') {
6444 /* weird case that MS seems to skip */
6445 if (*env_string != '=')
6447 while (*env_string != '\0')
6453 domain = mono_domain_get ();
6454 names = mono_array_new (domain, mono_defaults.string_class, n);
6458 env_string = env_strings;
6459 while (*env_string != '\0') {
6460 /* weird case that MS seems to skip */
6461 if (*env_string != '=') {
6462 equal_str = wcschr(env_string, '=');
6463 g_assert(equal_str);
6464 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6465 mono_array_setref (names, n, str);
6468 while (*env_string != '\0')
6473 FreeEnvironmentStrings (env_strings);
6485 MONO_ARCH_SAVE_REGS;
6488 for (e = environ; *e != 0; ++ e)
6491 domain = mono_domain_get ();
6492 names = mono_array_new (domain, mono_defaults.string_class, n);
6495 for (e = environ; *e != 0; ++ e) {
6496 parts = g_strsplit (*e, "=", 2);
6498 str = mono_string_new (domain, *parts);
6499 mono_array_setref (names, n, str);
6512 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6514 #if !GLIB_CHECK_VERSION(2,4,0)
6515 #define g_setenv(a,b,c) setenv(a,b,c)
6516 #define g_unsetenv(a) unsetenv(a)
6520 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6525 gunichar2 *utf16_name, *utf16_value;
6527 gchar *utf8_name, *utf8_value;
6530 MONO_ARCH_SAVE_REGS;
6533 utf16_name = mono_string_to_utf16 (name);
6534 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6535 SetEnvironmentVariable (utf16_name, NULL);
6536 g_free (utf16_name);
6540 utf16_value = mono_string_to_utf16 (value);
6542 SetEnvironmentVariable (utf16_name, utf16_value);
6544 g_free (utf16_name);
6545 g_free (utf16_value);
6547 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6549 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6550 g_unsetenv (utf8_name);
6555 utf8_value = mono_string_to_utf8_checked (value, &error);
6556 if (!mono_error_ok (&error)) {
6558 mono_error_raise_exception (&error);
6560 g_setenv (utf8_name, utf8_value, TRUE);
6563 g_free (utf8_value);
6568 ves_icall_System_Environment_Exit (int result)
6570 MONO_ARCH_SAVE_REGS;
6572 mono_threads_set_shutting_down ();
6574 mono_runtime_set_shutting_down ();
6576 /* This will kill the tp threads which cannot be suspended */
6577 mono_thread_pool_cleanup ();
6579 /* Suspend all managed threads since the runtime is going away */
6580 mono_thread_suspend_all_other_threads ();
6582 mono_runtime_quit ();
6584 /* we may need to do some cleanup here... */
6588 ICALL_EXPORT MonoString*
6589 ves_icall_System_Environment_GetGacPath (void)
6591 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6594 ICALL_EXPORT MonoString*
6595 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6597 #if defined (HOST_WIN32)
6598 #ifndef CSIDL_FLAG_CREATE
6599 #define CSIDL_FLAG_CREATE 0x8000
6602 WCHAR path [MAX_PATH];
6603 /* Create directory if no existing */
6604 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6608 return mono_string_new_utf16 (mono_domain_get (), path, len);
6611 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6613 return mono_string_new (mono_domain_get (), "");
6616 ICALL_EXPORT MonoArray *
6617 ves_icall_System_Environment_GetLogicalDrives (void)
6619 gunichar2 buf [256], *ptr, *dname;
6621 guint initial_size = 127, size = 128;
6624 MonoString *drivestr;
6625 MonoDomain *domain = mono_domain_get ();
6628 MONO_ARCH_SAVE_REGS;
6633 while (size > initial_size) {
6634 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6635 if (size > initial_size) {
6638 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6639 initial_size = size;
6653 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6658 while (*u16) { u16++; len ++; }
6659 drivestr = mono_string_new_utf16 (domain, dname, len);
6660 mono_array_setref (result, ndrives++, drivestr);
6670 ICALL_EXPORT MonoString *
6671 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6673 gunichar2 volume_name [MAX_PATH + 1];
6675 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6677 return mono_string_from_utf16 (volume_name);
6680 ICALL_EXPORT MonoString *
6681 ves_icall_System_Environment_InternalGetHome (void)
6683 MONO_ARCH_SAVE_REGS;
6685 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6688 static const char *encodings [] = {
6690 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6691 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6692 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6694 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6695 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6696 "x_unicode_2_0_utf_7",
6698 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6699 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6701 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6704 "unicodefffe", "utf_16be",
6711 * Returns the internal codepage, if the value of "int_code_page" is
6712 * 1 at entry, and we can not compute a suitable code page number,
6713 * returns the code page as a string
6715 ICALL_EXPORT MonoString*
6716 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6721 char *codepage = NULL;
6723 int want_name = *int_code_page;
6726 *int_code_page = -1;
6727 MONO_ARCH_SAVE_REGS;
6729 g_get_charset (&cset);
6730 c = codepage = strdup (cset);
6731 for (c = codepage; *c; c++){
6732 if (isascii (*c) && isalpha (*c))
6737 /* g_print ("charset: %s\n", cset); */
6739 /* handle some common aliases */
6742 for (i = 0; p != 0; ){
6743 if ((gssize) p < 7){
6745 p = encodings [++i];
6748 if (strcmp (p, codepage) == 0){
6749 *int_code_page = code;
6752 p = encodings [++i];
6755 if (strstr (codepage, "utf_8") != NULL)
6756 *int_code_page |= 0x10000000;
6759 if (want_name && *int_code_page == -1)
6760 return mono_string_new (mono_domain_get (), cset);
6765 ICALL_EXPORT MonoBoolean
6766 ves_icall_System_Environment_get_HasShutdownStarted (void)
6768 if (mono_runtime_is_shutting_down ())
6771 if (mono_domain_is_unloading (mono_domain_get ()))
6778 ves_icall_System_Environment_BroadcastSettingChange (void)
6781 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6786 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6787 MonoReflectionMethod *method,
6788 MonoArray *out_args)
6790 MONO_ARCH_SAVE_REGS;
6792 mono_message_init (mono_object_domain (this), this, method, out_args);
6795 ICALL_EXPORT MonoBoolean
6796 ves_icall_IsTransparentProxy (MonoObject *proxy)
6798 MONO_ARCH_SAVE_REGS;
6803 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6809 ICALL_EXPORT MonoReflectionMethod *
6810 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6811 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6815 MonoMethod **vtable;
6816 MonoMethod *res = NULL;
6818 MONO_CHECK_ARG_NULL (rtype);
6819 MONO_CHECK_ARG_NULL (rmethod);
6821 method = rmethod->method;
6822 klass = mono_class_from_mono_type (rtype->type);
6823 mono_class_init_or_throw (klass);
6825 if (MONO_CLASS_IS_INTERFACE (klass))
6828 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6831 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6832 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6838 mono_class_setup_vtable (klass);
6839 vtable = klass->vtable;
6841 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6842 gboolean variance_used = FALSE;
6843 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6844 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6846 res = vtable [offs + method->slot];
6848 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6851 if (method->slot != -1)
6852 res = vtable [method->slot];
6858 return mono_method_get_object (mono_domain_get (), res, NULL);
6862 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6867 MONO_ARCH_SAVE_REGS;
6869 klass = mono_class_from_mono_type (type->type);
6870 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6872 if (enable) vtable->remote = 1;
6873 else vtable->remote = 0;
6876 ICALL_EXPORT MonoObject *
6877 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6882 MONO_ARCH_SAVE_REGS;
6884 domain = mono_object_domain (type);
6885 klass = mono_class_from_mono_type (type->type);
6886 mono_class_init_or_throw (klass);
6888 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6889 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6891 if (klass->rank >= 1) {
6892 g_assert (klass->rank == 1);
6893 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6895 /* Bypass remoting object creation check */
6896 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6900 ICALL_EXPORT MonoString *
6901 ves_icall_System_IO_get_temp_path (void)
6903 MONO_ARCH_SAVE_REGS;
6905 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6908 #ifndef PLATFORM_NO_DRIVEINFO
6909 ICALL_EXPORT MonoBoolean
6910 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6911 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6915 ULARGE_INTEGER wapi_free_bytes_avail;
6916 ULARGE_INTEGER wapi_total_number_of_bytes;
6917 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6919 MONO_ARCH_SAVE_REGS;
6921 *error = ERROR_SUCCESS;
6922 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6923 &wapi_total_number_of_free_bytes);
6926 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6927 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6928 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6930 *free_bytes_avail = 0;
6931 *total_number_of_bytes = 0;
6932 *total_number_of_free_bytes = 0;
6933 *error = GetLastError ();
6939 ICALL_EXPORT guint32
6940 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6942 MONO_ARCH_SAVE_REGS;
6944 return GetDriveType (mono_string_chars (root_path_name));
6948 ICALL_EXPORT gpointer
6949 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6951 MONO_ARCH_SAVE_REGS;
6953 return mono_compile_method (method);
6956 ICALL_EXPORT MonoString *
6957 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6962 MONO_ARCH_SAVE_REGS;
6964 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6966 #if defined (HOST_WIN32)
6967 /* Avoid mixing '/' and '\\' */
6970 for (i = strlen (path) - 1; i >= 0; i--)
6971 if (path [i] == '/')
6975 mcpath = mono_string_new (mono_domain_get (), path);
6982 get_bundled_app_config (void)
6984 const gchar *app_config;
6987 gchar *config_file_name, *config_file_path;
6991 MONO_ARCH_SAVE_REGS;
6993 domain = mono_domain_get ();
6994 file = domain->setup->configuration_file;
6998 // Retrieve config file and remove the extension
6999 config_file_name = mono_string_to_utf8 (file);
7000 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7001 if (!config_file_path)
7002 config_file_path = config_file_name;
7003 len = strlen (config_file_path) - strlen (".config");
7004 module = g_malloc0 (len + 1);
7005 memcpy (module, config_file_path, len);
7006 // Get the config file from the module name
7007 app_config = mono_config_string_for_assembly_file (module);
7010 if (config_file_name != config_file_path)
7011 g_free (config_file_name);
7012 g_free (config_file_path);
7017 return mono_string_new (mono_domain_get (), app_config);
7021 get_bundled_machine_config (void)
7023 const gchar *machine_config;
7025 MONO_ARCH_SAVE_REGS;
7027 machine_config = mono_get_machine_config ();
7029 if (!machine_config)
7032 return mono_string_new (mono_domain_get (), machine_config);
7035 ICALL_EXPORT MonoString *
7036 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7041 MONO_ARCH_SAVE_REGS;
7043 path = g_path_get_dirname (mono_get_config_dir ());
7045 #if defined (HOST_WIN32)
7046 /* Avoid mixing '/' and '\\' */
7049 for (i = strlen (path) - 1; i >= 0; i--)
7050 if (path [i] == '/')
7054 ipath = mono_string_new (mono_domain_get (), path);
7060 ICALL_EXPORT gboolean
7061 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7063 MonoPEResourceDataEntry *entry;
7066 MONO_ARCH_SAVE_REGS;
7068 if (!assembly || !result || !size)
7073 image = assembly->assembly->image;
7074 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7078 *result = mono_image_rva_map (image, entry->rde_data_offset);
7083 *size = entry->rde_size;
7088 ICALL_EXPORT MonoBoolean
7089 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7091 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7094 ICALL_EXPORT MonoBoolean
7095 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7097 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7098 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7104 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7106 if (mono_get_runtime_callbacks ()->debug_log)
7107 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7111 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7113 #if defined (HOST_WIN32)
7114 OutputDebugString (mono_string_chars (message));
7116 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7120 /* Only used for value types */
7121 ICALL_EXPORT MonoObject *
7122 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7127 MONO_ARCH_SAVE_REGS;
7129 domain = mono_object_domain (type);
7130 klass = mono_class_from_mono_type (type->type);
7131 mono_class_init_or_throw (klass);
7133 if (mono_class_is_nullable (klass))
7134 /* No arguments -> null */
7137 return mono_object_new (domain, klass);
7140 ICALL_EXPORT MonoReflectionMethod *
7141 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7143 MonoClass *klass, *parent;
7144 MonoMethod *method = m->method;
7145 MonoMethod *result = NULL;
7148 MONO_ARCH_SAVE_REGS;
7150 if (method->klass == NULL)
7153 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7154 MONO_CLASS_IS_INTERFACE (method->klass) ||
7155 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7158 slot = mono_method_get_vtable_slot (method);
7162 klass = method->klass;
7163 if (klass->generic_class)
7164 klass = klass->generic_class->container_class;
7167 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7168 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7169 mono_class_setup_vtable (parent);
7170 if (parent->vtable_size <= slot)
7175 klass = klass->parent;
7180 if (klass == method->klass)
7183 /*This is possible if definition == FALSE.
7184 * Do it here to be really sure we don't read invalid memory.
7186 if (slot >= klass->vtable_size)
7189 mono_class_setup_vtable (klass);
7191 result = klass->vtable [slot];
7192 if (result == NULL) {
7193 /* It is an abstract method */
7194 gpointer iter = NULL;
7195 while ((result = mono_class_get_methods (klass, &iter)))
7196 if (result->slot == slot)
7203 return mono_method_get_object (mono_domain_get (), result, NULL);
7206 ICALL_EXPORT MonoString*
7207 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7209 MonoMethod *method = m->method;
7211 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7216 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7218 MONO_ARCH_SAVE_REGS;
7220 iter->sig = *(MonoMethodSignature**)argsp;
7222 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7223 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7226 /* FIXME: it's not documented what start is exactly... */
7230 iter->args = argsp + sizeof (gpointer);
7232 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7234 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7237 ICALL_EXPORT MonoTypedRef
7238 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7240 guint32 i, arg_size;
7243 MONO_ARCH_SAVE_REGS;
7245 i = iter->sig->sentinelpos + iter->next_arg;
7247 g_assert (i < iter->sig->param_count);
7249 res.type = iter->sig->params [i];
7250 res.klass = mono_class_from_mono_type (res.type);
7251 arg_size = mono_type_stack_size (res.type, &align);
7252 #if defined(__arm__) || defined(__mips__)
7253 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7255 res.value = iter->args;
7256 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7257 if (arg_size <= sizeof (gpointer)) {
7259 int padding = arg_size - mono_type_size (res.type, &dummy);
7260 res.value = (guint8*)res.value + padding;
7263 iter->args = (char*)iter->args + arg_size;
7266 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7271 ICALL_EXPORT MonoTypedRef
7272 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7274 guint32 i, arg_size;
7277 MONO_ARCH_SAVE_REGS;
7279 i = iter->sig->sentinelpos + iter->next_arg;
7281 g_assert (i < iter->sig->param_count);
7283 while (i < iter->sig->param_count) {
7284 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7286 res.type = iter->sig->params [i];
7287 res.klass = mono_class_from_mono_type (res.type);
7288 /* FIXME: endianess issue... */
7289 arg_size = mono_type_stack_size (res.type, &align);
7290 #if defined(__arm__) || defined(__mips__)
7291 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7293 res.value = iter->args;
7294 iter->args = (char*)iter->args + arg_size;
7296 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7299 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7307 ICALL_EXPORT MonoType*
7308 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7311 MONO_ARCH_SAVE_REGS;
7313 i = iter->sig->sentinelpos + iter->next_arg;
7315 g_assert (i < iter->sig->param_count);
7317 return iter->sig->params [i];
7320 ICALL_EXPORT MonoObject*
7321 mono_TypedReference_ToObject (MonoTypedRef tref)
7323 MONO_ARCH_SAVE_REGS;
7325 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7326 MonoObject** objp = tref.value;
7330 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7333 ICALL_EXPORT MonoObject*
7334 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7336 MONO_ARCH_SAVE_REGS;
7338 if (MONO_TYPE_IS_REFERENCE (type)) {
7339 MonoObject** objp = value;
7343 return mono_value_box (mono_domain_get (), klass, value);
7347 prelink_method (MonoMethod *method)
7349 const char *exc_class, *exc_arg;
7350 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7352 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7354 mono_raise_exception(
7355 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7357 /* create the wrapper, too? */
7361 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7363 MONO_ARCH_SAVE_REGS;
7364 prelink_method (method->method);
7368 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7370 MonoClass *klass = mono_class_from_mono_type (type->type);
7372 gpointer iter = NULL;
7373 MONO_ARCH_SAVE_REGS;
7375 mono_class_init_or_throw (klass);
7377 while ((m = mono_class_get_methods (klass, &iter)))
7381 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7383 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7384 gint32 const **exponents,
7385 gunichar2 const **digitLowerTable,
7386 gunichar2 const **digitUpperTable,
7387 gint64 const **tenPowersList,
7388 gint32 const **decHexDigits)
7390 *mantissas = Formatter_MantissaBitsTable;
7391 *exponents = Formatter_TensExponentTable;
7392 *digitLowerTable = Formatter_DigitLowerTable;
7393 *digitUpperTable = Formatter_DigitUpperTable;
7394 *tenPowersList = Formatter_TenPowersList;
7395 *decHexDigits = Formatter_DecHexDigits;
7399 get_category_data (int version,
7400 guint8 const **category_data,
7401 guint16 const **category_astral_index)
7403 *category_astral_index = NULL;
7405 #ifndef DISABLE_NET_4_0
7407 *category_data = CategoryData_v4;
7408 #ifndef DISABLE_ASTRAL
7409 *category_astral_index = CategoryData_v4_astral_index;
7415 *category_data = CategoryData_v2;
7416 #ifndef DISABLE_ASTRAL
7417 *category_astral_index = CategoryData_v2_astral_index;
7421 /* These parameters are "readonly" in corlib/System/Char.cs */
7423 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7424 guint8 const **category_data,
7425 guint16 const **category_astral_index,
7426 guint8 const **numeric_data,
7427 gdouble const **numeric_data_values,
7428 guint16 const **to_lower_data_low,
7429 guint16 const **to_lower_data_high,
7430 guint16 const **to_upper_data_low,
7431 guint16 const **to_upper_data_high)
7433 get_category_data (category_data_version, category_data, category_astral_index);
7434 *numeric_data = NumericData;
7435 *numeric_data_values = NumericDataValues;
7436 *to_lower_data_low = ToLowerDataLow;
7437 *to_lower_data_high = ToLowerDataHigh;
7438 *to_upper_data_low = ToUpperDataLow;
7439 *to_upper_data_high = ToUpperDataHigh;
7443 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7445 return method->method->token;
7449 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7450 * and avoid useless allocations.
7453 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7457 for (i = 0; i < type->num_mods; ++i) {
7458 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7463 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7465 for (i = 0; i < type->num_mods; ++i) {
7466 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7467 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7468 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7475 ICALL_EXPORT MonoArray*
7476 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7478 MonoType *type = param->ClassImpl->type;
7479 MonoClass *member_class = mono_object_class (param->MemberImpl);
7480 MonoMethod *method = NULL;
7483 MonoMethodSignature *sig;
7485 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7486 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7487 method = rmethod->method;
7488 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7489 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7490 if (!(method = prop->property->get))
7491 method = prop->property->set;
7494 char *type_name = mono_type_get_full_name (member_class);
7495 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7496 MonoException *ex = mono_get_exception_not_supported (msg);
7499 mono_raise_exception (ex);
7502 image = method->klass->image;
7503 pos = param->PositionImpl;
7504 sig = mono_method_signature (method);
7508 type = sig->params [pos];
7510 return type_array_from_modifiers (image, type, optional);
7514 get_property_type (MonoProperty *prop)
7516 MonoMethodSignature *sig;
7518 sig = mono_method_signature (prop->get);
7520 } else if (prop->set) {
7521 sig = mono_method_signature (prop->set);
7522 return sig->params [sig->param_count - 1];
7527 ICALL_EXPORT MonoArray*
7528 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7530 MonoType *type = get_property_type (property->property);
7531 MonoImage *image = property->klass->image;
7535 return type_array_from_modifiers (image, type, optional);
7539 *Construct a MonoType suited to be used to decode a constant blob object.
7541 * @type is the target type which will be constructed
7542 * @blob_type is the blob type, for example, that comes from the constant table
7543 * @real_type is the expected constructed type.
7546 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7548 type->type = blob_type;
7549 type->data.klass = NULL;
7550 if (blob_type == MONO_TYPE_CLASS)
7551 type->data.klass = mono_defaults.object_class;
7552 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7553 /* For enums, we need to use the base type */
7554 type->type = MONO_TYPE_VALUETYPE;
7555 type->data.klass = mono_class_from_mono_type (real_type);
7557 type->data.klass = mono_class_from_mono_type (real_type);
7560 ICALL_EXPORT MonoObject*
7561 property_info_get_default_value (MonoReflectionProperty *property)
7564 MonoProperty *prop = property->property;
7565 MonoType *type = get_property_type (prop);
7566 MonoDomain *domain = mono_object_domain (property);
7567 MonoTypeEnum def_type;
7568 const char *def_value;
7571 mono_class_init (prop->parent);
7573 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7574 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7576 def_value = mono_class_get_property_default_value (prop, &def_type);
7578 mono_type_from_blob_type (&blob_type, def_type, type);
7579 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7584 ICALL_EXPORT MonoBoolean
7585 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7587 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7588 MonoCustomAttrInfo *cinfo;
7591 mono_class_init_or_throw (attr_class);
7593 cinfo = mono_reflection_get_custom_attrs_info (obj);
7596 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7598 mono_custom_attrs_free (cinfo);
7602 ICALL_EXPORT MonoArray*
7603 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7605 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7610 mono_class_init_or_throw (attr_class);
7612 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7613 if (!mono_error_ok (&error))
7614 mono_error_raise_exception (&error);
7615 if (mono_loader_get_last_error ()) {
7616 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7617 g_assert_not_reached ();
7625 ICALL_EXPORT MonoString*
7626 ves_icall_Mono_Runtime_GetDisplayName (void)
7629 MonoString *display_name;
7631 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7632 display_name = mono_string_new (mono_domain_get (), info);
7634 return display_name;
7637 ICALL_EXPORT MonoString*
7638 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7640 MonoString *message;
7644 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7645 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7648 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7650 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7658 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7659 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7660 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7661 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7662 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7663 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7664 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7665 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7669 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7674 gunichar2 last, prev_last, prev2_last;
7681 int havePadding = 0;
7683 last = prev_last = 0, prev2_last = 0;
7684 for (i = 0; i < ilength; i++) {
7686 if (c >= sizeof (dbase64)) {
7687 exc = mono_exception_from_name_msg (mono_get_corlib (),
7688 "System", "FormatException",
7689 "Invalid character found.");
7690 mono_raise_exception (exc);
7691 } else if (isspace (c)) {
7693 } else if (havePadding && c != '=') {
7694 exc = mono_exception_from_name_msg (mono_get_corlib (),
7695 "System", "FormatException",
7696 "Invalid character found.");
7697 mono_raise_exception (exc);
7699 if (c == '=') havePadding = 1;
7700 prev2_last = prev_last;
7706 olength = ilength - ignored;
7708 if (allowWhitespaceOnly && olength == 0) {
7709 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7712 if ((olength & 3) != 0 || olength <= 0) {
7713 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7714 "FormatException", "Invalid length.");
7715 mono_raise_exception (exc);
7718 if (prev2_last == '=') {
7719 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7720 mono_raise_exception (exc);
7723 olength = (olength * 3) / 4;
7727 if (prev_last == '=')
7730 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7731 res_ptr = mono_array_addr (result, guchar, 0);
7732 for (i = 0; i < ilength; ) {
7735 for (k = 0; k < 4 && i < ilength;) {
7741 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7742 exc = mono_exception_from_name_msg (mono_get_corlib (),
7743 "System", "FormatException",
7744 "Invalid character found.");
7745 mono_raise_exception (exc);
7750 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7752 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7754 *res_ptr++ = (b [2] << 6) | b [3];
7756 while (i < ilength && isspace (start [i]))
7763 ICALL_EXPORT MonoArray *
7764 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7766 MONO_ARCH_SAVE_REGS;
7768 return base64_to_byte_array (mono_string_chars (str),
7769 mono_string_length (str), allowWhitespaceOnly);
7772 ICALL_EXPORT MonoArray *
7773 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7775 MONO_ARCH_SAVE_REGS;
7777 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7781 #ifndef DISABLE_ICALL_TABLES
7783 #define ICALL_TYPE(id,name,first)
7784 #define ICALL(id,name,func) Icall_ ## id,
7787 #include "metadata/icall-def.h"
7793 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7794 #define ICALL(id,name,func)
7796 #include "metadata/icall-def.h"
7802 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7803 #define ICALL(id,name,func)
7805 guint16 first_icall;
7808 static const IcallTypeDesc
7809 icall_type_descs [] = {
7810 #include "metadata/icall-def.h"
7814 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7817 #define ICALL_TYPE(id,name,first)
7820 #ifdef HAVE_ARRAY_ELEM_INIT
7821 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7822 #define MSGSTRFIELD1(line) str##line
7824 static const struct msgstrtn_t {
7825 #define ICALL(id,name,func)
7827 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7828 #include "metadata/icall-def.h"
7830 } icall_type_names_str = {
7831 #define ICALL_TYPE(id,name,first) (name),
7832 #include "metadata/icall-def.h"
7835 static const guint16 icall_type_names_idx [] = {
7836 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7837 #include "metadata/icall-def.h"
7840 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7842 static const struct msgstr_t {
7844 #define ICALL_TYPE(id,name,first)
7845 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7846 #include "metadata/icall-def.h"
7848 } icall_names_str = {
7849 #define ICALL(id,name,func) (name),
7850 #include "metadata/icall-def.h"
7853 static const guint16 icall_names_idx [] = {
7854 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7855 #include "metadata/icall-def.h"
7858 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7864 #define ICALL_TYPE(id,name,first) name,
7865 #define ICALL(id,name,func)
7866 static const char* const
7867 icall_type_names [] = {
7868 #include "metadata/icall-def.h"
7872 #define icall_type_name_get(id) (icall_type_names [(id)])
7876 #define ICALL_TYPE(id,name,first)
7877 #define ICALL(id,name,func) name,
7878 static const char* const
7880 #include "metadata/icall-def.h"
7883 #define icall_name_get(id) icall_names [(id)]
7885 #endif /* !HAVE_ARRAY_ELEM_INIT */
7889 #define ICALL_TYPE(id,name,first)
7890 #define ICALL(id,name,func) func,
7891 static const gconstpointer
7892 icall_functions [] = {
7893 #include "metadata/icall-def.h"
7897 #ifdef ENABLE_ICALL_SYMBOL_MAP
7900 #define ICALL_TYPE(id,name,first)
7901 #define ICALL(id,name,func) #func,
7902 static const gconstpointer
7903 icall_symbols [] = {
7904 #include "metadata/icall-def.h"
7909 #endif /* DISABLE_ICALL_TABLES */
7911 static GHashTable *icall_hash = NULL;
7912 static GHashTable *jit_icall_hash_name = NULL;
7913 static GHashTable *jit_icall_hash_addr = NULL;
7916 mono_icall_init (void)
7918 #ifndef DISABLE_ICALL_TABLES
7921 /* check that tables are sorted: disable in release */
7924 const char *prev_class = NULL;
7925 const char *prev_method;
7927 for (i = 0; i < Icall_type_num; ++i) {
7928 const IcallTypeDesc *desc;
7931 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7932 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7933 prev_class = icall_type_name_get (i);
7934 desc = &icall_type_descs [i];
7935 num_icalls = icall_desc_num_icalls (desc);
7936 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7937 for (j = 0; j < num_icalls; ++j) {
7938 const char *methodn = icall_name_get (desc->first_icall + j);
7939 if (prev_method && strcmp (prev_method, methodn) >= 0)
7940 g_print ("method %s should come before method %s\n", methodn, prev_method);
7941 prev_method = methodn;
7947 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7951 mono_icall_cleanup (void)
7953 g_hash_table_destroy (icall_hash);
7954 g_hash_table_destroy (jit_icall_hash_name);
7955 g_hash_table_destroy (jit_icall_hash_addr);
7959 mono_add_internal_call (const char *name, gconstpointer method)
7961 mono_loader_lock ();
7963 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7965 mono_loader_unlock ();
7968 #ifndef DISABLE_ICALL_TABLES
7970 #ifdef HAVE_ARRAY_ELEM_INIT
7972 compare_method_imap (const void *key, const void *elem)
7974 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7975 return strcmp (key, method_name);
7979 find_method_icall (const IcallTypeDesc *imap, const char *name)
7981 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7984 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7988 compare_class_imap (const void *key, const void *elem)
7990 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7991 return strcmp (key, class_name);
7994 static const IcallTypeDesc*
7995 find_class_icalls (const char *name)
7997 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8000 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8003 #else /* HAVE_ARRAY_ELEM_INIT */
8006 compare_method_imap (const void *key, const void *elem)
8008 const char** method_name = (const char**)elem;
8009 return strcmp (key, *method_name);
8013 find_method_icall (const IcallTypeDesc *imap, const char *name)
8015 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8018 return (gpointer)icall_functions [(nameslot - icall_names)];
8022 compare_class_imap (const void *key, const void *elem)
8024 const char** class_name = (const char**)elem;
8025 return strcmp (key, *class_name);
8028 static const IcallTypeDesc*
8029 find_class_icalls (const char *name)
8031 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8034 return &icall_type_descs [nameslot - icall_type_names];
8037 #endif /* HAVE_ARRAY_ELEM_INIT */
8039 #endif /* DISABLE_ICALL_TABLES */
8042 * we should probably export this as an helper (handle nested types).
8043 * Returns the number of chars written in buf.
8046 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8048 int nspacelen, cnamelen;
8049 nspacelen = strlen (klass->name_space);
8050 cnamelen = strlen (klass->name);
8051 if (nspacelen + cnamelen + 2 > bufsize)
8054 memcpy (buf, klass->name_space, nspacelen);
8055 buf [nspacelen ++] = '.';
8057 memcpy (buf + nspacelen, klass->name, cnamelen);
8058 buf [nspacelen + cnamelen] = 0;
8059 return nspacelen + cnamelen;
8062 #ifdef DISABLE_ICALL_TABLES
8064 no_icall_table (void)
8066 g_assert_not_reached ();
8071 mono_lookup_internal_call (MonoMethod *method)
8076 int typelen = 0, mlen, siglen;
8078 #ifndef DISABLE_ICALL_TABLES
8079 const IcallTypeDesc *imap = NULL;
8082 g_assert (method != NULL);
8084 if (method->is_inflated)
8085 method = ((MonoMethodInflated *) method)->declaring;
8087 if (method->klass->nested_in) {
8088 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8092 mname [pos++] = '/';
8095 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8101 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8106 #ifndef DISABLE_ICALL_TABLES
8107 imap = find_class_icalls (mname);
8110 mname [typelen] = ':';
8111 mname [typelen + 1] = ':';
8113 mlen = strlen (method->name);
8114 memcpy (mname + typelen + 2, method->name, mlen);
8115 sigstart = mname + typelen + 2 + mlen;
8118 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8119 siglen = strlen (tmpsig);
8120 if (typelen + mlen + siglen + 6 > sizeof (mname))
8123 memcpy (sigstart + 1, tmpsig, siglen);
8124 sigstart [siglen + 1] = ')';
8125 sigstart [siglen + 2] = 0;
8128 mono_loader_lock ();
8130 res = g_hash_table_lookup (icall_hash, mname);
8132 mono_loader_unlock ();
8135 /* try without signature */
8137 res = g_hash_table_lookup (icall_hash, mname);
8139 mono_loader_unlock ();
8143 #ifdef DISABLE_ICALL_TABLES
8144 mono_loader_unlock ();
8145 /* Fail only when the result is actually used */
8146 /* mono_marshal_get_native_wrapper () depends on this */
8147 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8148 return ves_icall_System_String_ctor_RedirectToCreateString;
8150 return no_icall_table;
8152 /* it wasn't found in the static call tables */
8154 mono_loader_unlock ();
8157 res = find_method_icall (imap, sigstart - mlen);
8159 mono_loader_unlock ();
8162 /* try _with_ signature */
8164 res = find_method_icall (imap, sigstart - mlen);
8166 mono_loader_unlock ();
8170 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8171 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8172 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8173 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8174 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");
8175 g_print ("If you see other errors or faults after this message they are probably related\n");
8176 g_print ("and you need to fix your mono install first.\n");
8178 mono_loader_unlock ();
8184 #ifdef ENABLE_ICALL_SYMBOL_MAP
8186 func_cmp (gconstpointer key, gconstpointer p)
8188 return (gsize)key - (gsize)*(gsize*)p;
8193 * mono_lookup_icall_symbol:
8195 * Given the icall METHOD, returns its C symbol.
8198 mono_lookup_icall_symbol (MonoMethod *m)
8200 #ifdef DISABLE_ICALL_TABLES
8201 g_assert_not_reached ();
8204 #ifdef ENABLE_ICALL_SYMBOL_MAP
8208 static gconstpointer *functions_sorted;
8209 static const char**symbols_sorted;
8210 static gboolean inited;
8215 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8216 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8217 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8218 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8219 /* Bubble sort the two arrays */
8223 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8224 if (functions_sorted [i] > functions_sorted [i + 1]) {
8227 tmp = functions_sorted [i];
8228 functions_sorted [i] = functions_sorted [i + 1];
8229 functions_sorted [i + 1] = tmp;
8230 tmp = symbols_sorted [i];
8231 symbols_sorted [i] = symbols_sorted [i + 1];
8232 symbols_sorted [i + 1] = tmp;
8239 func = mono_lookup_internal_call (m);
8242 slot = bsearch (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8246 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8248 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8249 g_assert_not_reached ();
8256 type_from_typename (char *typename)
8258 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8260 if (!strcmp (typename, "int"))
8261 klass = mono_defaults.int_class;
8262 else if (!strcmp (typename, "ptr"))
8263 klass = mono_defaults.int_class;
8264 else if (!strcmp (typename, "void"))
8265 klass = mono_defaults.void_class;
8266 else if (!strcmp (typename, "int32"))
8267 klass = mono_defaults.int32_class;
8268 else if (!strcmp (typename, "uint32"))
8269 klass = mono_defaults.uint32_class;
8270 else if (!strcmp (typename, "int8"))
8271 klass = mono_defaults.sbyte_class;
8272 else if (!strcmp (typename, "uint8"))
8273 klass = mono_defaults.byte_class;
8274 else if (!strcmp (typename, "int16"))
8275 klass = mono_defaults.int16_class;
8276 else if (!strcmp (typename, "uint16"))
8277 klass = mono_defaults.uint16_class;
8278 else if (!strcmp (typename, "long"))
8279 klass = mono_defaults.int64_class;
8280 else if (!strcmp (typename, "ulong"))
8281 klass = mono_defaults.uint64_class;
8282 else if (!strcmp (typename, "float"))
8283 klass = mono_defaults.single_class;
8284 else if (!strcmp (typename, "double"))
8285 klass = mono_defaults.double_class;
8286 else if (!strcmp (typename, "object"))
8287 klass = mono_defaults.object_class;
8288 else if (!strcmp (typename, "obj"))
8289 klass = mono_defaults.object_class;
8290 else if (!strcmp (typename, "string"))
8291 klass = mono_defaults.string_class;
8292 else if (!strcmp (typename, "bool"))
8293 klass = mono_defaults.boolean_class;
8294 else if (!strcmp (typename, "boolean"))
8295 klass = mono_defaults.boolean_class;
8297 g_error ("%s", typename);
8298 g_assert_not_reached ();
8300 return &klass->byval_arg;
8303 MonoMethodSignature*
8304 mono_create_icall_signature (const char *sigstr)
8309 MonoMethodSignature *res;
8311 mono_loader_lock ();
8312 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8314 mono_loader_unlock ();
8318 parts = g_strsplit (sigstr, " ", 256);
8327 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8332 * Under windows, the default pinvoke calling convention is STDCALL but
8335 res->call_convention = MONO_CALL_C;
8338 res->ret = type_from_typename (parts [0]);
8339 for (i = 1; i < len; ++i) {
8340 res->params [i - 1] = type_from_typename (parts [i]);
8345 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8347 mono_loader_unlock ();
8353 mono_find_jit_icall_by_name (const char *name)
8355 MonoJitICallInfo *info;
8356 g_assert (jit_icall_hash_name);
8358 mono_loader_lock ();
8359 info = g_hash_table_lookup (jit_icall_hash_name, name);
8360 mono_loader_unlock ();
8365 mono_find_jit_icall_by_addr (gconstpointer addr)
8367 MonoJitICallInfo *info;
8368 g_assert (jit_icall_hash_addr);
8370 mono_loader_lock ();
8371 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8372 mono_loader_unlock ();
8378 * mono_get_jit_icall_info:
8380 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8381 * caller should access it while holding the loader lock.
8384 mono_get_jit_icall_info (void)
8386 return jit_icall_hash_name;
8390 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8392 mono_loader_lock ();
8393 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8394 mono_loader_unlock ();
8398 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8400 MonoJitICallInfo *info;
8405 mono_loader_lock ();
8407 if (!jit_icall_hash_name) {
8408 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8409 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8412 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8413 g_warning ("jit icall already defined \"%s\"\n", name);
8414 g_assert_not_reached ();
8417 info = g_new0 (MonoJitICallInfo, 1);
8424 info->wrapper = func;
8426 info->wrapper = NULL;
8429 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8430 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8432 mono_loader_unlock ();