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)
21 #ifdef HAVE_SYS_TIME_H
27 #if defined (HOST_WIN32)
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/io-layer/io-layer.h>
71 #include <mono/utils/strtod.h>
72 #include <mono/utils/monobitset.h>
73 #include <mono/utils/mono-time.h>
74 #include <mono/utils/mono-proclib.h>
75 #include <mono/utils/mono-string.h>
76 #include <mono/utils/mono-error-internals.h>
77 #include <mono/utils/mono-mmap.h>
79 #if defined (HOST_WIN32)
85 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
87 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
90 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
92 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
93 * It works by allocating an initial small array on stack and only going to malloc'd memory if needed.
101 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
103 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\
105 (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
106 (ARRAY).data = INITIAL_SIZE > MONO_PTR_ARRAY_MAX_ON_STACK ? mono_gc_alloc_fixed (sizeof (void*) * INITIAL_SIZE, NULL) : g_newa (void*, MONO_PTR_ARRAY_MAX_ON_STACK); \
109 #define mono_ptr_array_destroy(ARRAY) do {\
110 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
111 mono_gc_free_fixed ((ARRAY).data); \
114 #define mono_ptr_array_append(ARRAY, VALUE) do { \
115 if ((ARRAY).size >= (ARRAY).capacity) {\
116 void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \
117 memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
118 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
119 mono_gc_free_fixed ((ARRAY).data); \
120 (ARRAY).data = __tmp; \
121 (ARRAY).capacity *= 2;\
123 ((ARRAY).data [(ARRAY).size++] = VALUE); \
126 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
127 ((ARRAY).data [(IDX)] = VALUE); \
130 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
132 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
135 static inline MonoBoolean
136 is_generic_parameter (MonoType *type)
138 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
142 mono_class_init_or_throw (MonoClass *klass)
144 if (!mono_class_init (klass))
145 mono_raise_exception (mono_class_get_exception_for_failure (klass));
149 * We expect a pointer to a char, not a string
152 mono_double_ParseImpl (char *ptr, double *result)
154 gchar *endptr = NULL;
161 *result = strtod (ptr, &endptr);
165 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
166 EnterCriticalSection (&mono_strtod_mutex);
167 *result = mono_strtod (ptr, &endptr);
168 LeaveCriticalSection (&mono_strtod_mutex);
170 *result = mono_strtod (ptr, &endptr);
175 if (!*ptr || (endptr && *endptr))
182 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
191 ao = (MonoArray *)this;
192 ac = (MonoClass *)ao->obj.vtable->klass;
194 esize = mono_array_element_size (ac);
195 ea = (gpointer*)((char*)ao->vector + (pos * esize));
197 if (ac->element_class->valuetype)
198 return mono_value_box (this->vtable->domain, ac->element_class, ea);
204 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
212 MONO_CHECK_ARG_NULL (idxs);
214 io = (MonoArray *)idxs;
215 ic = (MonoClass *)io->obj.vtable->klass;
217 ao = (MonoArray *)this;
218 ac = (MonoClass *)ao->obj.vtable->klass;
220 g_assert (ic->rank == 1);
221 if (io->bounds != NULL || io->max_length != ac->rank)
222 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
224 ind = (gint32 *)io->vector;
226 if (ao->bounds == NULL) {
227 if (*ind < 0 || *ind >= ao->max_length)
228 mono_raise_exception (mono_get_exception_index_out_of_range ());
230 return ves_icall_System_Array_GetValueImpl (this, *ind);
233 for (i = 0; i < ac->rank; i++)
234 if ((ind [i] < ao->bounds [i].lower_bound) ||
235 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
236 mono_raise_exception (mono_get_exception_index_out_of_range ());
238 pos = ind [0] - ao->bounds [0].lower_bound;
239 for (i = 1; i < ac->rank; i++)
240 pos = pos*ao->bounds [i].length + ind [i] -
241 ao->bounds [i].lower_bound;
243 return ves_icall_System_Array_GetValueImpl (this, pos);
247 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
249 MonoClass *ac, *vc, *ec;
261 vc = value->vtable->klass;
265 ac = this->obj.vtable->klass;
266 ec = ac->element_class;
268 esize = mono_array_element_size (ac);
269 ea = (gpointer*)((char*)this->vector + (pos * esize));
270 va = (gpointer*)((char*)value + sizeof (MonoObject));
272 if (mono_class_is_nullable (ec)) {
273 mono_nullable_init ((guint8*)ea, value, ec);
278 memset (ea, 0, esize);
282 #define NO_WIDENING_CONVERSION G_STMT_START{\
283 mono_raise_exception (mono_get_exception_argument ( \
284 "value", "not a widening conversion")); \
287 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
288 if (esize < vsize + (extra)) \
289 mono_raise_exception (mono_get_exception_argument ( \
290 "value", "not a widening conversion")); \
293 #define INVALID_CAST G_STMT_START{\
294 mono_raise_exception (mono_get_exception_invalid_cast ()); \
297 /* Check element (destination) type. */
298 switch (ec->byval_arg.type) {
299 case MONO_TYPE_STRING:
300 switch (vc->byval_arg.type) {
301 case MONO_TYPE_STRING:
307 case MONO_TYPE_BOOLEAN:
308 switch (vc->byval_arg.type) {
309 case MONO_TYPE_BOOLEAN:
322 NO_WIDENING_CONVERSION;
329 if (!ec->valuetype) {
330 if (!mono_object_isinst (value, ec))
332 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
336 if (mono_object_isinst (value, ec)) {
337 if (ec->has_references)
338 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
340 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
347 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
349 et = ec->byval_arg.type;
350 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
351 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
353 vt = vc->byval_arg.type;
354 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
355 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
357 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
363 case MONO_TYPE_CHAR: \
364 CHECK_WIDENING_CONVERSION(0); \
365 *(etype *) ea = (etype) u64; \
367 /* You can't assign a signed value to an unsigned array. */ \
372 /* You can't assign a floating point number to an integer array. */ \
375 NO_WIDENING_CONVERSION; \
379 #define ASSIGN_SIGNED(etype) G_STMT_START{\
385 CHECK_WIDENING_CONVERSION(0); \
386 *(etype *) ea = (etype) i64; \
388 /* You can assign an unsigned value to a signed array if the array's */ \
389 /* element size is larger than the value size. */ \
394 case MONO_TYPE_CHAR: \
395 CHECK_WIDENING_CONVERSION(1); \
396 *(etype *) ea = (etype) u64; \
398 /* You can't assign a floating point number to an integer array. */ \
401 NO_WIDENING_CONVERSION; \
405 #define ASSIGN_REAL(etype) G_STMT_START{\
409 CHECK_WIDENING_CONVERSION(0); \
410 *(etype *) ea = (etype) r64; \
412 /* All integer values fit into a floating point array, so we don't */ \
413 /* need to CHECK_WIDENING_CONVERSION here. */ \
418 *(etype *) ea = (etype) i64; \
424 case MONO_TYPE_CHAR: \
425 *(etype *) ea = (etype) u64; \
432 u64 = *(guint8 *) va;
435 u64 = *(guint16 *) va;
438 u64 = *(guint32 *) va;
441 u64 = *(guint64 *) va;
447 i64 = *(gint16 *) va;
450 i64 = *(gint32 *) va;
453 i64 = *(gint64 *) va;
456 r64 = *(gfloat *) va;
459 r64 = *(gdouble *) va;
462 u64 = *(guint16 *) va;
464 case MONO_TYPE_BOOLEAN:
465 /* Boolean is only compatible with itself. */
478 NO_WIDENING_CONVERSION;
485 /* If we can't do a direct copy, let's try a widening conversion. */
488 ASSIGN_UNSIGNED (guint16);
490 ASSIGN_UNSIGNED (guint8);
492 ASSIGN_UNSIGNED (guint16);
494 ASSIGN_UNSIGNED (guint32);
496 ASSIGN_UNSIGNED (guint64);
498 ASSIGN_SIGNED (gint8);
500 ASSIGN_SIGNED (gint16);
502 ASSIGN_SIGNED (gint32);
504 ASSIGN_SIGNED (gint64);
506 ASSIGN_REAL (gfloat);
508 ASSIGN_REAL (gdouble);
512 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
516 #undef NO_WIDENING_CONVERSION
517 #undef CHECK_WIDENING_CONVERSION
518 #undef ASSIGN_UNSIGNED
524 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
532 MONO_CHECK_ARG_NULL (idxs);
534 ic = idxs->obj.vtable->klass;
535 ac = this->obj.vtable->klass;
537 g_assert (ic->rank == 1);
538 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
539 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
541 ind = (gint32 *)idxs->vector;
543 if (this->bounds == NULL) {
544 if (*ind < 0 || *ind >= this->max_length)
545 mono_raise_exception (mono_get_exception_index_out_of_range ());
547 ves_icall_System_Array_SetValueImpl (this, value, *ind);
551 for (i = 0; i < ac->rank; i++)
552 if ((ind [i] < this->bounds [i].lower_bound) ||
553 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
554 mono_raise_exception (mono_get_exception_index_out_of_range ());
556 pos = ind [0] - this->bounds [0].lower_bound;
557 for (i = 1; i < ac->rank; i++)
558 pos = pos * this->bounds [i].length + ind [i] -
559 this->bounds [i].lower_bound;
561 ves_icall_System_Array_SetValueImpl (this, value, pos);
565 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
567 MonoClass *aklass, *klass;
570 gboolean bounded = FALSE;
574 MONO_CHECK_ARG_NULL (type);
575 MONO_CHECK_ARG_NULL (lengths);
577 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
579 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
581 for (i = 0; i < mono_array_length (lengths); i++)
582 if (mono_array_get (lengths, gint32, i) < 0)
583 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
585 klass = mono_class_from_mono_type (type->type);
586 mono_class_init_or_throw (klass);
588 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
589 /* vectors are not the same as one dimensional arrays with no-zero bounds */
594 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
596 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
597 for (i = 0; i < aklass->rank; ++i) {
598 sizes [i] = mono_array_get (lengths, guint32, i);
600 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
602 sizes [i + aklass->rank] = 0;
605 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
611 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
613 MonoClass *aklass, *klass;
616 gboolean bounded = FALSE;
620 MONO_CHECK_ARG_NULL (type);
621 MONO_CHECK_ARG_NULL (lengths);
623 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
625 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
627 for (i = 0; i < mono_array_length (lengths); i++)
628 if ((mono_array_get (lengths, gint64, i) < 0) ||
629 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
630 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
632 klass = mono_class_from_mono_type (type->type);
633 mono_class_init_or_throw (klass);
635 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
636 /* vectors are not the same as one dimensional arrays with no-zero bounds */
641 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
643 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
644 for (i = 0; i < aklass->rank; ++i) {
645 sizes [i] = mono_array_get (lengths, guint64, i);
647 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
649 sizes [i + aklass->rank] = 0;
652 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
658 ves_icall_System_Array_GetRank (MonoObject *this)
662 return this->vtable->klass->rank;
666 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
668 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
673 if ((dimension < 0) || (dimension >= rank))
674 mono_raise_exception (mono_get_exception_index_out_of_range ());
676 if (this->bounds == NULL)
677 length = this->max_length;
679 length = this->bounds [dimension].length;
681 #ifdef MONO_BIG_ARRAYS
682 if (length > G_MAXINT32)
683 mono_raise_exception (mono_get_exception_overflow ());
689 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
691 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
695 if ((dimension < 0) || (dimension >= rank))
696 mono_raise_exception (mono_get_exception_index_out_of_range ());
698 if (this->bounds == NULL)
699 return this->max_length;
701 return this->bounds [dimension].length;
705 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
707 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
711 if ((dimension < 0) || (dimension >= rank))
712 mono_raise_exception (mono_get_exception_index_out_of_range ());
714 if (this->bounds == NULL)
717 return this->bounds [dimension].lower_bound;
721 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
723 int sz = mono_array_element_size (mono_object_class (arr));
724 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
728 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
733 MonoClass *src_class;
734 MonoClass *dest_class;
739 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
742 if (source->bounds || dest->bounds)
745 /* there's no integer overflow since mono_array_length returns an unsigned integer */
746 if ((dest_idx + length > mono_array_length (dest)) ||
747 (source_idx + length > mono_array_length (source)))
750 src_class = source->obj.vtable->klass->element_class;
751 dest_class = dest->obj.vtable->klass->element_class;
754 * Handle common cases.
757 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
758 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
759 int has_refs = dest_class->has_references;
760 for (i = source_idx; i < source_idx + length; ++i) {
761 MonoObject *elem = mono_array_get (source, MonoObject*, i);
762 if (elem && !mono_object_isinst (elem, dest_class))
766 element_size = mono_array_element_size (dest->obj.vtable->klass);
767 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
768 for (i = 0; i < length; ++i) {
769 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
770 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
774 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
776 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
781 /* Check if we're copying a char[] <==> (u)short[] */
782 if (src_class != dest_class) {
783 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
786 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
788 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
789 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
790 for (i = source_idx; i < source_idx + length; ++i) {
791 MonoObject *elem = mono_array_get (source, MonoObject*, i);
792 if (elem && !mono_object_isinst (elem, dest_class))
799 if (dest_class->valuetype) {
800 element_size = mono_array_element_size (source->obj.vtable->klass);
801 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
802 if (dest_class->has_references) {
803 mono_value_copy_array (dest, dest_idx, source_addr, length);
805 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
806 memmove (dest_addr, source_addr, element_size * length);
809 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
816 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
825 ao = (MonoArray *)this;
826 ac = (MonoClass *)ao->obj.vtable->klass;
828 esize = mono_array_element_size (ac);
829 ea = (gpointer*)((char*)ao->vector + (pos * esize));
831 memcpy (value, ea, esize);
835 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
844 ao = (MonoArray *)this;
845 ac = (MonoClass *)ao->obj.vtable->klass;
846 ec = ac->element_class;
848 esize = mono_array_element_size (ac);
849 ea = (gpointer*)((char*)ao->vector + (pos * esize));
851 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
852 g_assert (esize == sizeof (gpointer));
853 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
855 g_assert (ec->inited);
856 g_assert (esize == mono_class_value_size (ec, NULL));
857 if (ec->has_references)
858 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
860 memcpy (ea, value, esize);
865 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
867 MonoClass *klass = array->obj.vtable->klass;
868 guint32 size = mono_array_element_size (klass);
869 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
871 const char *field_data;
873 if (MONO_TYPE_IS_REFERENCE (type) ||
874 (type->type == MONO_TYPE_VALUETYPE &&
875 (!mono_type_get_class (type) ||
876 mono_type_get_class (type)->has_references))) {
877 MonoException *exc = mono_get_exception_argument("array",
878 "Cannot initialize array containing references");
879 mono_raise_exception (exc);
882 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
883 MonoException *exc = mono_get_exception_argument("field_handle",
884 "Field doesn't have an RVA");
885 mono_raise_exception (exc);
888 size *= array->max_length;
889 field_data = mono_field_get_data (field_handle);
891 if (size > mono_type_size (field_handle->type, &align)) {
892 MonoException *exc = mono_get_exception_argument("field_handle",
893 "Field not large enough to fill array");
894 mono_raise_exception (exc);
897 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
899 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
900 guint ## n *src = (guint ## n *) field_data; \
901 guint ## n *end = (guint ## n *)((char*)src + size); \
903 for (; src < end; data++, src++) { \
904 *data = read ## n (src); \
908 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
910 switch (type->type) {
927 memcpy (mono_array_addr (array, char, 0), field_data, size);
931 memcpy (mono_array_addr (array, char, 0), field_data, size);
933 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
936 double *data = (double*)mono_array_addr (array, double, 0);
938 for (i = 0; i < size; i++, data++) {
948 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
952 return offsetof (MonoString, chars);
956 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
960 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
963 return mono_object_clone (obj);
967 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
972 MONO_CHECK_ARG_NULL (handle);
974 klass = mono_class_from_mono_type (handle);
975 MONO_CHECK_ARG (handle, klass);
977 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
979 /* This will call the type constructor */
980 mono_runtime_class_init (vtable);
984 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
988 mono_image_check_for_module_cctor (image);
989 if (image->has_module_cctor) {
990 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
991 /*It's fine to raise the exception here*/
992 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
997 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
1002 /* later make this configurable and per-arch */
1003 int min_size = 4096 * 4 * sizeof (void*);
1004 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
1005 /* if we have no info we are optimistic and assume there is enough room */
1008 current = (guint8 *)&stack_addr;
1009 if (current > stack_addr) {
1010 if ((current - stack_addr) < min_size)
1013 if (current - (stack_addr - stack_size) < min_size)
1020 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
1022 MONO_ARCH_SAVE_REGS;
1024 return mono_object_clone (this);
1028 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
1031 MonoObject **values = NULL;
1035 MonoClassField* field;
1038 MONO_ARCH_SAVE_REGS;
1040 klass = mono_object_class (this);
1042 if (mono_class_num_fields (klass) == 0)
1043 return mono_object_hash (this);
1046 * Compute the starting value of the hashcode for fields of primitive
1047 * types, and return the remaining fields in an array to the managed side.
1048 * This way, we can avoid costly reflection operations in managed code.
1051 while ((field = mono_class_get_fields (klass, &iter))) {
1052 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1054 if (mono_field_is_deleted (field))
1056 /* FIXME: Add more types */
1057 switch (field->type->type) {
1059 result ^= *(gint32*)((guint8*)this + field->offset);
1061 case MONO_TYPE_STRING: {
1063 s = *(MonoString**)((guint8*)this + field->offset);
1065 result ^= mono_string_hash (s);
1070 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1071 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1072 values [count++] = o;
1078 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1079 for (i = 0; i < count; ++i)
1080 mono_array_setref (*fields, i, values [i]);
1088 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1091 MonoObject **values = NULL;
1093 MonoClassField* field;
1097 MONO_ARCH_SAVE_REGS;
1099 MONO_CHECK_ARG_NULL (that);
1101 if (this->vtable != that->vtable)
1104 klass = mono_object_class (this);
1106 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1107 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1110 * Do the comparison for fields of primitive type and return a result if
1111 * possible. Otherwise, return the remaining fields in an array to the
1112 * managed side. This way, we can avoid costly reflection operations in
1117 while ((field = mono_class_get_fields (klass, &iter))) {
1118 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1120 if (mono_field_is_deleted (field))
1122 /* FIXME: Add more types */
1123 switch (field->type->type) {
1126 case MONO_TYPE_BOOLEAN:
1127 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1132 case MONO_TYPE_CHAR:
1133 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1138 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1143 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1147 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1151 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1156 case MONO_TYPE_STRING: {
1157 MonoString *s1, *s2;
1158 guint32 s1len, s2len;
1159 s1 = *(MonoString**)((guint8*)this + field->offset);
1160 s2 = *(MonoString**)((guint8*)that + field->offset);
1163 if ((s1 == NULL) || (s2 == NULL))
1165 s1len = mono_string_length (s1);
1166 s2len = mono_string_length (s2);
1170 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1176 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1177 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1178 values [count++] = o;
1179 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1180 values [count++] = o;
1183 if (klass->enumtype)
1184 /* enums only have one non-static field */
1190 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1191 for (i = 0; i < count; ++i)
1192 mono_array_setref (*fields, i, values [i]);
1199 static MonoReflectionType *
1200 ves_icall_System_Object_GetType (MonoObject *obj)
1202 MONO_ARCH_SAVE_REGS;
1204 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1205 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1207 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1211 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1213 MONO_ARCH_SAVE_REGS;
1215 mtype->type = &obj->vtable->klass->byval_arg;
1216 g_assert (mtype->type->type);
1220 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1222 MONO_ARCH_SAVE_REGS;
1224 MONO_CHECK_ARG_NULL (obj);
1226 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1230 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1231 MonoReflectionMethod *method,
1232 MonoArray *opt_param_types)
1234 MONO_ARCH_SAVE_REGS;
1236 MONO_CHECK_ARG_NULL (method);
1238 return mono_image_create_method_token (
1239 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1243 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1245 MONO_ARCH_SAVE_REGS;
1247 mono_image_create_pefile (mb, file);
1251 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1253 MONO_ARCH_SAVE_REGS;
1255 mono_image_build_metadata (mb);
1259 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1261 MONO_ARCH_SAVE_REGS;
1263 mono_image_register_token (mb->dynamic_image, token, obj);
1267 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1269 MonoMethod **dest = data;
1271 /* skip unmanaged frames */
1287 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1289 MonoMethod **dest = data;
1291 /* skip unmanaged frames */
1296 if (!strcmp (m->klass->name_space, "System.Reflection"))
1305 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1307 MonoMethod **dest = data;
1309 /* skip unmanaged frames */
1313 if (m->wrapper_type != MONO_WRAPPER_NONE)
1316 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1330 static MonoReflectionType *
1331 type_from_name (const char *str, MonoBoolean ignoreCase)
1333 MonoType *type = NULL;
1334 MonoAssembly *assembly = NULL;
1335 MonoTypeNameParse info;
1336 char *temp_str = g_strdup (str);
1337 gboolean type_resolve = FALSE;
1339 MONO_ARCH_SAVE_REGS;
1341 /* mono_reflection_parse_type() mangles the string */
1342 if (!mono_reflection_parse_type (temp_str, &info)) {
1343 mono_reflection_free_type_info (&info);
1348 if (info.assembly.name) {
1349 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1351 MonoMethod *m = mono_method_get_last_managed ();
1352 MonoMethod *dest = m;
1354 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1359 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1360 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1361 * to crash. This only seems to happen in some strange remoting
1362 * scenarios and I was unable to figure out what's happening there.
1363 * Dec 10, 2005 - Martin.
1367 assembly = dest->klass->image->assembly;
1368 type_resolve = TRUE;
1370 g_warning (G_STRLOC);
1375 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1376 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1379 if (!info.assembly.name && !type) /* try mscorlib */
1380 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1382 if (assembly && !type && type_resolve) {
1383 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1384 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1387 mono_reflection_free_type_info (&info);
1393 return mono_type_get_object (mono_domain_get (), type);
1397 MonoReflectionType *
1398 mono_type_get (const char *str)
1400 char *copy = g_strdup (str);
1401 MonoReflectionType *type = type_from_name (copy, FALSE);
1408 static MonoReflectionType*
1409 ves_icall_type_from_name (MonoString *name,
1410 MonoBoolean throwOnError,
1411 MonoBoolean ignoreCase)
1413 char *str = mono_string_to_utf8 (name);
1414 MonoReflectionType *type;
1416 type = type_from_name (str, ignoreCase);
1419 MonoException *e = NULL;
1422 e = mono_get_exception_type_load (name, NULL);
1424 mono_loader_clear_error ();
1426 mono_raise_exception (e);
1433 static MonoReflectionType*
1434 ves_icall_type_from_handle (MonoType *handle)
1436 MonoDomain *domain = mono_domain_get ();
1438 MONO_ARCH_SAVE_REGS;
1440 return mono_type_get_object (domain, handle);
1444 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1446 MONO_ARCH_SAVE_REGS;
1448 if (c && type->type && c->type)
1449 return mono_metadata_type_equal (type->type, c->type);
1451 return (type == c) ? TRUE : FALSE;
1454 /* System.TypeCode */
1473 TYPECODE_STRING = 18
1477 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1479 int t = type->type->type;
1481 MONO_ARCH_SAVE_REGS;
1483 if (type->type->byref)
1484 return TYPECODE_OBJECT;
1488 case MONO_TYPE_VOID:
1489 return TYPECODE_OBJECT;
1490 case MONO_TYPE_BOOLEAN:
1491 return TYPECODE_BOOLEAN;
1493 return TYPECODE_BYTE;
1495 return TYPECODE_SBYTE;
1497 return TYPECODE_UINT16;
1499 return TYPECODE_INT16;
1500 case MONO_TYPE_CHAR:
1501 return TYPECODE_CHAR;
1505 return TYPECODE_OBJECT;
1507 return TYPECODE_UINT32;
1509 return TYPECODE_INT32;
1511 return TYPECODE_UINT64;
1513 return TYPECODE_INT64;
1515 return TYPECODE_SINGLE;
1517 return TYPECODE_DOUBLE;
1518 case MONO_TYPE_VALUETYPE:
1519 if (type->type->data.klass->enumtype) {
1520 t = mono_class_enum_basetype (type->type->data.klass)->type;
1523 MonoClass *k = type->type->data.klass;
1524 if (strcmp (k->name_space, "System") == 0) {
1525 if (strcmp (k->name, "Decimal") == 0)
1526 return TYPECODE_DECIMAL;
1527 else if (strcmp (k->name, "DateTime") == 0)
1528 return TYPECODE_DATETIME;
1531 return TYPECODE_OBJECT;
1532 case MONO_TYPE_STRING:
1533 return TYPECODE_STRING;
1534 case MONO_TYPE_SZARRAY:
1535 case MONO_TYPE_ARRAY:
1536 case MONO_TYPE_OBJECT:
1538 case MONO_TYPE_MVAR:
1539 case MONO_TYPE_TYPEDBYREF:
1540 return TYPECODE_OBJECT;
1541 case MONO_TYPE_CLASS:
1543 MonoClass *k = type->type->data.klass;
1544 if (strcmp (k->name_space, "System") == 0) {
1545 if (strcmp (k->name, "DBNull") == 0)
1546 return TYPECODE_DBNULL;
1549 return TYPECODE_OBJECT;
1550 case MONO_TYPE_GENERICINST:
1551 return TYPECODE_OBJECT;
1553 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1559 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1565 MONO_ARCH_SAVE_REGS;
1567 g_assert (type != NULL);
1569 domain = ((MonoObject *)type)->vtable->domain;
1571 if (!c) /* FIXME: dont know what do do here */
1574 klass = mono_class_from_mono_type (type->type);
1575 klassc = mono_class_from_mono_type (c->type);
1577 /* Interface check requires a more complex setup so we
1578 * only do for them. Otherwise we simply avoid mono_class_init.
1580 if (check_interfaces) {
1581 mono_class_init_or_throw (klass);
1582 mono_class_init_or_throw (klassc);
1583 } else if (!klass->supertypes || !klassc->supertypes) {
1584 mono_loader_lock ();
1585 mono_class_setup_supertypes (klass);
1586 mono_class_setup_supertypes (klassc);
1587 mono_loader_unlock ();
1590 if (type->type->byref)
1591 return klassc == mono_defaults.object_class;
1593 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1597 mono_type_is_primitive (MonoType *type)
1599 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1600 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1604 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1606 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1607 return mono_class_enum_basetype (type->data.klass);
1608 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1609 return mono_class_enum_basetype (type->data.generic_class->container_class);
1614 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1620 MONO_ARCH_SAVE_REGS;
1622 g_assert (type != NULL);
1624 domain = ((MonoObject *)type)->vtable->domain;
1626 klass = mono_class_from_mono_type (type->type);
1627 klassc = mono_class_from_mono_type (c->type);
1629 mono_class_init_or_throw (klass);
1630 mono_class_init_or_throw (klassc);
1632 if (type->type->byref ^ c->type->byref)
1635 if (type->type->byref) {
1636 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1637 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1639 klass = mono_class_from_mono_type (t);
1640 klassc = mono_class_from_mono_type (ot);
1642 if (mono_type_is_primitive (t)) {
1643 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1644 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1645 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1646 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1647 return t->type == ot->type;
1649 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1652 if (klass->valuetype)
1653 return klass == klassc;
1654 return klass->valuetype == klassc->valuetype;
1657 return mono_class_is_assignable_from (klass, klassc);
1661 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1663 MonoClass *klass = mono_class_from_mono_type (type->type);
1664 mono_class_init_or_throw (klass);
1665 return mono_object_isinst (obj, klass) != NULL;
1669 ves_icall_get_attributes (MonoReflectionType *type)
1671 MonoClass *klass = mono_class_from_mono_type (type->type);
1672 return klass->flags;
1675 static MonoReflectionMarshal*
1676 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1678 MonoClass *klass = field->field->parent;
1679 MonoMarshalType *info;
1682 if (klass->generic_container ||
1683 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1686 info = mono_marshal_load_type_info (klass);
1688 for (i = 0; i < info->num_fields; ++i) {
1689 if (info->fields [i].field == field->field) {
1690 if (!info->fields [i].mspec)
1693 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1700 static MonoReflectionField*
1701 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1703 gboolean found = FALSE;
1710 klass = handle->parent;
1712 klass = mono_class_from_mono_type (type);
1714 /* Check that the field belongs to the class */
1715 for (k = klass; k; k = k->parent) {
1716 if (k == handle->parent) {
1723 /* The managed code will throw the exception */
1727 return mono_field_get_object (mono_domain_get (), klass, handle);
1731 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1733 MonoType *type = field->field->type;
1735 return type_array_from_modifiers (field->field->parent->image, type, optional);
1739 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1741 MonoDomain *domain = mono_domain_get ();
1742 MonoMethodSignature* sig;
1743 MONO_ARCH_SAVE_REGS;
1745 sig = mono_method_signature (method);
1747 g_assert (mono_loader_get_last_error ());
1748 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1751 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1752 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1753 info->attrs = method->flags;
1754 info->implattrs = method->iflags;
1755 if (sig->call_convention == MONO_CALL_DEFAULT)
1756 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1758 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1763 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1767 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1769 MonoDomain *domain = mono_domain_get ();
1771 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1774 static MonoReflectionMarshal*
1775 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1777 MonoDomain *domain = mono_domain_get ();
1778 MonoReflectionMarshal* res = NULL;
1779 MonoMarshalSpec **mspecs;
1782 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1783 mono_method_get_marshal_info (method, mspecs);
1786 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1788 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1790 mono_metadata_free_marshal_spec (mspecs [i]);
1797 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1799 return field->field->offset - sizeof (MonoObject);
1802 static MonoReflectionType*
1803 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1806 MONO_ARCH_SAVE_REGS;
1808 parent = declaring? field->field->parent: field->klass;
1810 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1814 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1816 MonoClass *fklass = field->klass;
1817 MonoClassField *cf = field->field;
1818 MonoDomain *domain = mono_object_domain (field);
1820 if (fklass->image->assembly->ref_only)
1821 mono_raise_exception (mono_get_exception_invalid_operation (
1822 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1824 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1825 mono_security_core_clr_ensure_reflection_access_field (cf);
1827 return mono_field_get_value_object (domain, cf, obj);
1831 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1833 MonoClassField *cf = field->field;
1836 MONO_ARCH_SAVE_REGS;
1838 if (field->klass->image->assembly->ref_only)
1839 mono_raise_exception (mono_get_exception_invalid_operation (
1840 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1842 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1843 mono_security_core_clr_ensure_reflection_access_field (cf);
1845 v = (gchar *) value;
1846 if (!cf->type->byref) {
1847 switch (cf->type->type) {
1850 case MONO_TYPE_BOOLEAN:
1853 case MONO_TYPE_CHAR:
1862 case MONO_TYPE_VALUETYPE:
1864 v += sizeof (MonoObject);
1866 case MONO_TYPE_STRING:
1867 case MONO_TYPE_OBJECT:
1868 case MONO_TYPE_CLASS:
1869 case MONO_TYPE_ARRAY:
1870 case MONO_TYPE_SZARRAY:
1873 case MONO_TYPE_GENERICINST: {
1874 MonoGenericClass *gclass = cf->type->data.generic_class;
1875 g_assert (!gclass->context.class_inst->is_open);
1877 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1878 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1879 MonoObject *nullable;
1882 * Convert the boxed vtype into a Nullable structure.
1883 * This is complicated by the fact that Nullables have
1884 * a variable structure.
1886 nullable = mono_object_new (mono_domain_get (), nklass);
1888 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1890 v = mono_object_unbox (nullable);
1893 if (gclass->container_class->valuetype && (v != NULL))
1894 v += sizeof (MonoObject);
1898 g_error ("type 0x%x not handled in "
1899 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1904 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1905 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1906 if (!vtable->initialized)
1907 mono_runtime_class_init (vtable);
1908 mono_field_static_set_value (vtable, cf, v);
1910 mono_field_set_value (obj, cf, v);
1915 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1917 MonoObject *o = NULL;
1918 MonoClassField *field = this->field;
1920 MonoDomain *domain = mono_object_domain (this);
1922 MonoTypeEnum def_type;
1923 const char *def_value;
1925 MONO_ARCH_SAVE_REGS;
1927 mono_class_init (field->parent);
1929 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1930 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1932 if (field->parent->image->dynamic) {
1934 g_assert_not_reached ();
1937 def_value = mono_class_get_field_default_value (field, &def_type);
1939 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1943 case MONO_TYPE_BOOLEAN:
1946 case MONO_TYPE_CHAR:
1954 case MONO_TYPE_R8: {
1957 /* boxed value type */
1958 t = g_new0 (MonoType, 1);
1960 klass = mono_class_from_mono_type (t);
1962 o = mono_object_new (domain, klass);
1963 v = ((gchar *) o) + sizeof (MonoObject);
1964 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1967 case MONO_TYPE_STRING:
1968 case MONO_TYPE_CLASS:
1969 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1972 g_assert_not_reached ();
1978 static MonoReflectionType*
1979 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1981 MonoMethod *method = rmethod->method.method;
1983 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1986 /* From MonoProperty.cs */
1988 PInfo_Attributes = 1,
1989 PInfo_GetMethod = 1 << 1,
1990 PInfo_SetMethod = 1 << 2,
1991 PInfo_ReflectedType = 1 << 3,
1992 PInfo_DeclaringType = 1 << 4,
1997 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1999 MonoDomain *domain = mono_object_domain (property);
2001 MONO_ARCH_SAVE_REGS;
2003 if ((req_info & PInfo_ReflectedType) != 0)
2004 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2005 else if ((req_info & PInfo_DeclaringType) != 0)
2006 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2008 if ((req_info & PInfo_Name) != 0)
2009 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2011 if ((req_info & PInfo_Attributes) != 0)
2012 info->attrs = property->property->attrs;
2014 if ((req_info & PInfo_GetMethod) != 0)
2015 MONO_STRUCT_SETREF (info, get, property->property->get ?
2016 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2018 if ((req_info & PInfo_SetMethod) != 0)
2019 MONO_STRUCT_SETREF (info, set, property->property->set ?
2020 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2022 * There may be other methods defined for properties, though, it seems they are not exposed
2023 * in the reflection API
2028 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2030 MonoDomain *domain = mono_object_domain (event);
2032 MONO_ARCH_SAVE_REGS;
2034 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2035 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2037 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2038 info->attrs = event->event->attrs;
2039 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2040 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2041 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2043 #ifndef MONO_SMALL_CONFIG
2044 if (event->event->other) {
2046 while (event->event->other [n])
2048 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2050 for (i = 0; i < n; i++)
2051 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2057 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2060 MonoDomain *domain = mono_object_domain (type);
2062 GPtrArray *ifaces = NULL;
2064 MonoClass *class = mono_class_from_mono_type (type->type);
2067 MonoGenericContext *context = NULL;
2069 mono_class_init_or_throw (class);
2071 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2072 context = mono_class_get_context (class);
2073 class = class->generic_class->container_class;
2076 mono_class_setup_vtable (class);
2078 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2080 for (parent = class; parent; parent = parent->parent) {
2081 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error);
2082 if (!mono_error_ok (&error)) {
2083 mono_bitset_free (slots);
2084 mono_error_raise_exception (&error);
2086 } else if (tmp_ifaces) {
2087 for (i = 0; i < tmp_ifaces->len; ++i) {
2088 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2090 if (mono_bitset_test (slots, ic->interface_id))
2093 mono_bitset_set (slots, ic->interface_id);
2095 ifaces = g_ptr_array_new ();
2096 g_ptr_array_add (ifaces, ic);
2098 g_ptr_array_free (tmp_ifaces, TRUE);
2101 mono_bitset_free (slots);
2104 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2106 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2107 for (i = 0; i < ifaces->len; ++i) {
2108 MonoClass *ic = g_ptr_array_index (ifaces, i);
2109 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2110 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2111 inflated = ret = mono_class_inflate_generic_type (ret, context);
2113 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2115 mono_metadata_free_type (inflated);
2117 g_ptr_array_free (ifaces, TRUE);
2123 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2125 gboolean variance_used;
2126 MonoClass *class = mono_class_from_mono_type (type->type);
2127 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2128 MonoReflectionMethod *member;
2131 int i = 0, len, ioffset;
2134 MONO_ARCH_SAVE_REGS;
2135 mono_class_init_or_throw (class);
2136 mono_class_init_or_throw (iclass);
2138 mono_class_setup_vtable (class);
2140 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2144 len = mono_class_num_methods (iclass);
2145 domain = mono_object_domain (type);
2146 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2147 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2149 while ((method = mono_class_get_methods (iclass, &iter))) {
2150 member = mono_method_get_object (domain, method, iclass);
2151 mono_array_setref (*methods, i, member);
2152 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2153 mono_array_setref (*targets, i, member);
2160 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2162 MonoClass *klass = mono_class_from_mono_type (type->type);
2163 mono_class_init_or_throw (klass);
2165 if (klass->image->dynamic) {
2166 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2167 *packing = tb->packing_size;
2168 *size = tb->class_size;
2170 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2174 static MonoReflectionType*
2175 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2179 MONO_ARCH_SAVE_REGS;
2181 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2182 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2184 class = mono_class_from_mono_type (type->type);
2185 mono_class_init_or_throw (class);
2187 // GetElementType should only return a type for:
2188 // Array Pointer PassedByRef
2189 if (type->type->byref)
2190 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2191 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2192 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2193 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2194 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2199 static MonoReflectionType*
2200 ves_icall_get_type_parent (MonoReflectionType *type)
2202 MonoClass *class = mono_class_from_mono_type (type->type);
2203 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2207 ves_icall_type_ispointer (MonoReflectionType *type)
2209 MONO_ARCH_SAVE_REGS;
2211 return type->type->type == MONO_TYPE_PTR;
2215 ves_icall_type_isprimitive (MonoReflectionType *type)
2217 MONO_ARCH_SAVE_REGS;
2219 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)));
2223 ves_icall_type_isbyref (MonoReflectionType *type)
2225 MONO_ARCH_SAVE_REGS;
2227 return type->type->byref;
2231 ves_icall_type_iscomobject (MonoReflectionType *type)
2233 MonoClass *klass = mono_class_from_mono_type (type->type);
2234 mono_class_init_or_throw (klass);
2236 return (klass && klass->is_com_object);
2239 static MonoReflectionModule*
2240 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2242 MonoClass *class = mono_class_from_mono_type (type->type);
2243 mono_class_init_or_throw (class);
2245 return mono_module_get_object (mono_object_domain (type), class->image);
2248 static MonoReflectionAssembly*
2249 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2251 MonoDomain *domain = mono_domain_get ();
2252 MonoClass *class = mono_class_from_mono_type (type->type);
2254 mono_class_init_or_throw (class);
2256 return mono_assembly_get_object (domain, class->image->assembly);
2259 static MonoReflectionType*
2260 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2262 MonoDomain *domain = mono_domain_get ();
2265 MONO_ARCH_SAVE_REGS;
2267 if (type->type->byref)
2269 if (type->type->type == MONO_TYPE_VAR)
2270 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2271 else if (type->type->type == MONO_TYPE_MVAR)
2272 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2274 class = mono_class_from_mono_type (type->type)->nested_in;
2276 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2280 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2282 MonoDomain *domain = mono_domain_get ();
2283 MonoClass *class = mono_class_from_mono_type (type->type);
2285 if (type->type->byref) {
2286 char *n = g_strdup_printf ("%s&", class->name);
2287 MonoString *res = mono_string_new (domain, n);
2293 return mono_string_new (domain, class->name);
2298 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2300 MonoDomain *domain = mono_domain_get ();
2301 MonoClass *class = mono_class_from_mono_type (type->type);
2303 while (class->nested_in)
2304 class = class->nested_in;
2306 if (class->name_space [0] == '\0')
2309 return mono_string_new (domain, class->name_space);
2313 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2317 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2318 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2320 class = mono_class_from_mono_type (type->type);
2321 mono_class_init_or_throw (class);
2327 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2330 MonoClass *klass, *pklass;
2331 MonoDomain *domain = mono_object_domain (type);
2332 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2334 MONO_ARCH_SAVE_REGS;
2336 klass = mono_class_from_mono_type (type->type);
2337 mono_class_init_or_throw (klass);
2339 if (klass->generic_container) {
2340 MonoGenericContainer *container = klass->generic_container;
2341 res = mono_array_new_specific (array_vtable, container->type_argc);
2342 for (i = 0; i < container->type_argc; ++i) {
2343 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2344 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2346 } else if (klass->generic_class) {
2347 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2348 res = mono_array_new_specific (array_vtable, inst->type_argc);
2349 for (i = 0; i < inst->type_argc; ++i)
2350 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2352 res = mono_array_new_specific (array_vtable, 0);
2358 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2361 MONO_ARCH_SAVE_REGS;
2363 if (!IS_MONOTYPE (type))
2366 if (type->type->byref)
2369 klass = mono_class_from_mono_type (type->type);
2370 return klass->generic_container != NULL;
2373 static MonoReflectionType*
2374 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2377 MONO_ARCH_SAVE_REGS;
2379 if (type->type->byref)
2382 klass = mono_class_from_mono_type (type->type);
2383 mono_class_init_or_throw (klass);
2385 if (klass->generic_container) {
2386 return type; /* check this one */
2388 if (klass->generic_class) {
2389 MonoClass *generic_class = klass->generic_class->container_class;
2392 tb = mono_class_get_ref_info (generic_class);
2394 if (generic_class->wastypebuilder && tb)
2397 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2402 static MonoReflectionType*
2403 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2405 MonoType *geninst, **types;
2408 g_assert (IS_MONOTYPE (type));
2409 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2411 count = mono_array_length (type_array);
2412 types = g_new0 (MonoType *, count);
2414 for (i = 0; i < count; i++) {
2415 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2416 types [i] = t->type;
2419 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2424 return mono_type_get_object (mono_object_domain (type), geninst);
2428 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2431 MONO_ARCH_SAVE_REGS;
2433 if (type->type->byref)
2436 klass = mono_class_from_mono_type (type->type);
2438 return klass->generic_class != NULL;
2442 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2445 MONO_ARCH_SAVE_REGS;
2447 if (!IS_MONOTYPE (type))
2450 if (type->type->byref)
2453 klass = mono_class_from_mono_type (type->type);
2454 return klass->generic_class != NULL || klass->generic_container != NULL;
2458 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2460 MONO_ARCH_SAVE_REGS;
2462 if (!IS_MONOTYPE (type))
2465 if (is_generic_parameter (type->type))
2466 return mono_type_get_generic_param_num (type->type);
2470 static GenericParameterAttributes
2471 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2473 MONO_ARCH_SAVE_REGS;
2475 g_assert (IS_MONOTYPE (type));
2476 g_assert (is_generic_parameter (type->type));
2477 return mono_generic_param_info (type->type->data.generic_param)->flags;
2481 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2483 MonoGenericParamInfo *param_info;
2489 MONO_ARCH_SAVE_REGS;
2491 g_assert (IS_MONOTYPE (type));
2493 domain = mono_object_domain (type);
2494 param_info = mono_generic_param_info (type->type->data.generic_param);
2495 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2498 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2499 for (i = 0; i < count; i++)
2500 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2507 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2509 MONO_ARCH_SAVE_REGS;
2510 return is_generic_parameter (type->type);
2514 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2516 MONO_ARCH_SAVE_REGS;
2517 return is_generic_parameter (tb->type.type);
2521 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2522 MonoReflectionType *t)
2524 enumtype->type = t->type;
2527 static MonoReflectionMethod*
2528 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2529 MonoReflectionMethod* generic)
2536 MONO_ARCH_SAVE_REGS;
2538 domain = ((MonoObject *)type)->vtable->domain;
2540 klass = mono_class_from_mono_type (type->type);
2541 mono_class_init_or_throw (klass);
2544 while ((method = mono_class_get_methods (klass, &iter))) {
2545 if (method->token == generic->method->token)
2546 return mono_method_get_object (domain, method, klass);
2554 static MonoReflectionMethod *
2555 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2558 MonoType *type = ref_type->type;
2560 MONO_ARCH_SAVE_REGS;
2562 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2563 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2564 if (type->type == MONO_TYPE_VAR)
2567 method = mono_type_get_generic_param_owner (type)->owner.method;
2569 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2572 static MonoReflectionDllImportAttribute*
2573 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2575 static MonoClass *DllImportAttributeClass = NULL;
2576 MonoDomain *domain = mono_domain_get ();
2577 MonoReflectionDllImportAttribute *attr;
2578 MonoImage *image = method->klass->image;
2579 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2580 MonoTableInfo *tables = image->tables;
2581 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2582 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2583 guint32 im_cols [MONO_IMPLMAP_SIZE];
2584 guint32 scope_token;
2585 const char *import = NULL;
2586 const char *scope = NULL;
2589 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2592 if (!DllImportAttributeClass) {
2593 DllImportAttributeClass =
2594 mono_class_from_name (mono_defaults.corlib,
2595 "System.Runtime.InteropServices", "DllImportAttribute");
2596 g_assert (DllImportAttributeClass);
2599 if (method->klass->image->dynamic) {
2600 MonoReflectionMethodAux *method_aux =
2601 g_hash_table_lookup (
2602 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2604 import = method_aux->dllentry;
2605 scope = method_aux->dll;
2608 if (!import || !scope) {
2609 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2614 if (piinfo->implmap_idx) {
2615 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2617 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2618 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2619 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2620 scope = mono_metadata_string_heap (image, scope_token);
2623 flags = piinfo->piflags;
2625 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2627 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2628 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2629 attr->call_conv = (flags & 0x700) >> 8;
2630 attr->charset = ((flags & 0x6) >> 1) + 1;
2631 if (attr->charset == 1)
2633 attr->exact_spelling = (flags & 0x1) != 0;
2634 attr->set_last_error = (flags & 0x40) != 0;
2635 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2636 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2637 attr->preserve_sig = FALSE;
2642 static MonoReflectionMethod *
2643 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2645 MonoMethodInflated *imethod;
2648 MONO_ARCH_SAVE_REGS;
2650 if (method->method->is_generic)
2653 if (!method->method->is_inflated)
2656 imethod = (MonoMethodInflated *) method->method;
2658 result = imethod->declaring;
2659 /* Not a generic method. */
2660 if (!result->is_generic)
2663 if (method->method->klass->image->dynamic) {
2664 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2665 MonoReflectionMethod *res;
2668 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2669 * the dynamic case as well ?
2671 mono_loader_lock ();
2672 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2673 mono_loader_unlock ();
2679 if (imethod->context.class_inst) {
2680 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2681 /*Generic methods gets the context of the GTD.*/
2682 if (mono_class_get_context (klass))
2683 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2686 return mono_method_get_object (mono_object_domain (method), result, NULL);
2690 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2692 MONO_ARCH_SAVE_REGS;
2694 return mono_method_signature (method->method)->generic_param_count != 0;
2698 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2700 MONO_ARCH_SAVE_REGS;
2702 return method->method->is_generic;
2706 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2711 MONO_ARCH_SAVE_REGS;
2713 domain = mono_object_domain (method);
2715 if (method->method->is_inflated) {
2716 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2719 count = inst->type_argc;
2720 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2722 for (i = 0; i < count; i++)
2723 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2729 count = mono_method_signature (method->method)->generic_param_count;
2730 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2732 for (i = 0; i < count; i++) {
2733 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2734 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2735 MonoClass *pklass = mono_class_from_generic_parameter (
2736 param, method->method->klass->image, TRUE);
2737 mono_array_setref (res, i,
2738 mono_type_get_object (domain, &pklass->byval_arg));
2745 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2748 * Invoke from reflection is supposed to always be a virtual call (the API
2749 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2750 * greater flexibility.
2752 MonoMethod *m = method->method;
2756 MONO_ARCH_SAVE_REGS;
2760 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2761 mono_security_core_clr_ensure_reflection_access_method (m);
2763 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2764 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2765 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2770 if (!mono_object_isinst (this, m->klass)) {
2771 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2774 m = mono_object_get_virtual_method (this, m);
2775 /* must pass the pointer to the value for valuetype methods */
2776 if (m->klass->valuetype)
2777 obj = mono_object_unbox (this);
2778 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2779 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2784 pcount = params? mono_array_length (params): 0;
2785 if (pcount != mono_method_signature (m)->param_count) {
2786 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2790 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2791 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."));
2795 if (m->klass->image->assembly->ref_only) {
2796 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."));
2800 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2803 intptr_t *lower_bounds;
2804 pcount = mono_array_length (params);
2805 lengths = alloca (sizeof (uintptr_t) * pcount);
2806 /* Note: the synthetized array .ctors have int32 as argument type */
2807 for (i = 0; i < pcount; ++i)
2808 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2810 if (m->klass->rank == pcount) {
2811 /* Only lengths provided. */
2812 lower_bounds = NULL;
2814 g_assert (pcount == (m->klass->rank * 2));
2815 /* lower bounds are first. */
2816 lower_bounds = (intptr_t*)lengths;
2817 lengths += m->klass->rank;
2820 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2822 return mono_runtime_invoke_array (m, obj, params, NULL);
2826 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2828 MonoDomain *domain = mono_object_domain (method);
2829 MonoMethod *m = method->method;
2830 MonoMethodSignature *sig = mono_method_signature (m);
2831 MonoArray *out_args;
2833 int i, j, outarg_count = 0;
2835 MONO_ARCH_SAVE_REGS;
2837 if (m->klass == mono_defaults.object_class) {
2839 if (!strcmp (m->name, "FieldGetter")) {
2840 MonoClass *k = this->vtable->klass;
2844 /* If this is a proxy, then it must be a CBO */
2845 if (k == mono_defaults.transparent_proxy_class) {
2846 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2847 this = tp->rp->unwrapped_server;
2849 k = this->vtable->klass;
2852 name = mono_array_get (params, MonoString *, 1);
2853 str = mono_string_to_utf8 (name);
2856 MonoClassField* field = mono_class_get_field_from_name (k, str);
2858 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2859 if (field_klass->valuetype)
2860 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2862 result = *((gpointer *)((char *)this + field->offset));
2864 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2865 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2866 mono_array_setref (out_args, 0, result);
2874 g_assert_not_reached ();
2876 } else if (!strcmp (m->name, "FieldSetter")) {
2877 MonoClass *k = this->vtable->klass;
2883 /* If this is a proxy, then it must be a CBO */
2884 if (k == mono_defaults.transparent_proxy_class) {
2885 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2886 this = tp->rp->unwrapped_server;
2888 k = this->vtable->klass;
2891 name = mono_array_get (params, MonoString *, 1);
2892 str = mono_string_to_utf8 (name);
2895 MonoClassField* field = mono_class_get_field_from_name (k, str);
2897 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2898 MonoObject *val = mono_array_get (params, gpointer, 2);
2900 if (field_klass->valuetype) {
2901 size = mono_type_size (field->type, &align);
2902 g_assert (size == mono_class_value_size (field_klass, NULL));
2903 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2905 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2908 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2909 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2919 g_assert_not_reached ();
2924 for (i = 0; i < mono_array_length (params); i++) {
2925 if (sig->params [i]->byref)
2929 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2931 /* handle constructors only for objects already allocated */
2932 if (!strcmp (method->method->name, ".ctor"))
2935 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2936 g_assert (!method->method->klass->valuetype);
2937 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2939 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2940 if (sig->params [i]->byref) {
2942 arg = mono_array_get (params, gpointer, i);
2943 mono_array_setref (out_args, j, arg);
2948 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2954 read_enum_value (char *mem, int type)
2958 return *(guint8*)mem;
2960 return *(gint8*)mem;
2962 return *(guint16*)mem;
2964 return *(gint16*)mem;
2966 return *(guint32*)mem;
2968 return *(gint32*)mem;
2970 return *(guint64*)mem;
2972 return *(gint64*)mem;
2974 g_assert_not_reached ();
2980 write_enum_value (char *mem, int type, guint64 value)
2984 case MONO_TYPE_I1: {
2985 guint8 *p = (guint8*)mem;
2990 case MONO_TYPE_I2: {
2991 guint16 *p = (void*)mem;
2996 case MONO_TYPE_I4: {
2997 guint32 *p = (void*)mem;
3002 case MONO_TYPE_I8: {
3003 guint64 *p = (void*)mem;
3008 g_assert_not_reached ();
3014 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3017 MonoClass *enumc, *objc;
3022 MONO_ARCH_SAVE_REGS;
3024 MONO_CHECK_ARG_NULL (enumType);
3025 MONO_CHECK_ARG_NULL (value);
3027 domain = mono_object_domain (enumType);
3028 enumc = mono_class_from_mono_type (enumType->type);
3030 mono_class_init_or_throw (enumc);
3032 objc = value->vtable->klass;
3034 if (!enumc->enumtype)
3035 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3036 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3037 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."));
3039 etype = mono_class_enum_basetype (enumc);
3041 /* MS throws this for typebuilders */
3042 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3044 res = mono_object_new (domain, enumc);
3045 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3046 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3052 ves_icall_System_Enum_get_value (MonoObject *this)
3060 MONO_ARCH_SAVE_REGS;
3065 g_assert (this->vtable->klass->enumtype);
3067 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3068 res = mono_object_new (mono_object_domain (this), enumc);
3069 dst = (char *)res + sizeof (MonoObject);
3070 src = (char *)this + sizeof (MonoObject);
3071 size = mono_class_value_size (enumc, NULL);
3073 memcpy (dst, src, size);
3078 static MonoReflectionType *
3079 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3084 MONO_ARCH_SAVE_REGS;
3086 klass = mono_class_from_mono_type (type->type);
3087 mono_class_init_or_throw (klass);
3089 etype = mono_class_enum_basetype (klass);
3091 /* MS throws this for typebuilders */
3092 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3094 return mono_type_get_object (mono_object_domain (type), etype);
3098 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3100 gpointer tdata = (char *)this + sizeof (MonoObject);
3101 gpointer odata = (char *)other + sizeof (MonoObject);
3102 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3103 g_assert (basetype);
3105 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3106 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3107 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3110 return me > other ? 1 : -1; \
3113 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3114 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3115 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3118 return me - other; \
3121 switch (basetype->type) {
3123 COMPARE_ENUM_VALUES (guint8);
3125 COMPARE_ENUM_VALUES (gint8);
3126 case MONO_TYPE_CHAR:
3128 COMPARE_ENUM_VALUES_RANGE (guint16);
3130 COMPARE_ENUM_VALUES (gint16);
3132 COMPARE_ENUM_VALUES (guint32);
3134 COMPARE_ENUM_VALUES (gint32);
3136 COMPARE_ENUM_VALUES (guint64);
3138 COMPARE_ENUM_VALUES (gint64);
3140 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3142 #undef COMPARE_ENUM_VALUES_RANGE
3143 #undef COMPARE_ENUM_VALUES
3148 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3150 gpointer data = (char *)this + sizeof (MonoObject);
3151 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3152 g_assert (basetype);
3154 switch (basetype->type) {
3156 return *((gint8*)data);
3158 return *((guint8*)data);
3159 case MONO_TYPE_CHAR:
3161 return *((guint16*)data);
3164 return *((gint16*)data);
3166 return *((guint32*)data);
3168 return *((gint32*)data);
3170 case MONO_TYPE_I8: {
3171 gint64 value = *((gint64*)data);
3172 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3175 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3181 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3183 MonoDomain *domain = mono_object_domain (type);
3184 MonoClass *enumc = mono_class_from_mono_type (type->type);
3185 guint j = 0, nvalues, crow;
3187 MonoClassField *field;
3189 MONO_ARCH_SAVE_REGS;
3191 mono_class_init_or_throw (enumc);
3193 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3194 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3195 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3196 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3200 while ((field = mono_class_get_fields (enumc, &iter))) {
3203 MonoTypeEnum def_type;
3205 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3207 if (mono_field_is_deleted (field))
3209 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3211 p = mono_class_get_field_default_value (field, &def_type);
3212 len = mono_metadata_decode_blob_size (p, &p);
3213 switch (mono_class_enum_basetype (enumc)->type) {
3216 mono_array_set (info->values, gchar, j, *p);
3218 case MONO_TYPE_CHAR:
3221 mono_array_set (info->values, gint16, j, read16 (p));
3225 mono_array_set (info->values, gint32, j, read32 (p));
3229 mono_array_set (info->values, gint64, j, read64 (p));
3232 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3239 BFLAGS_IgnoreCase = 1,
3240 BFLAGS_DeclaredOnly = 2,
3241 BFLAGS_Instance = 4,
3243 BFLAGS_Public = 0x10,
3244 BFLAGS_NonPublic = 0x20,
3245 BFLAGS_FlattenHierarchy = 0x40,
3246 BFLAGS_InvokeMethod = 0x100,
3247 BFLAGS_CreateInstance = 0x200,
3248 BFLAGS_GetField = 0x400,
3249 BFLAGS_SetField = 0x800,
3250 BFLAGS_GetProperty = 0x1000,
3251 BFLAGS_SetProperty = 0x2000,
3252 BFLAGS_ExactBinding = 0x10000,
3253 BFLAGS_SuppressChangeType = 0x20000,
3254 BFLAGS_OptionalParamBinding = 0x40000
3257 static MonoReflectionField *
3258 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3261 MonoClass *startklass, *klass;
3263 MonoClassField *field;
3266 int (*compare_func) (const char *s1, const char *s2) = NULL;
3267 domain = ((MonoObject *)type)->vtable->domain;
3268 klass = startklass = mono_class_from_mono_type (type->type);
3269 mono_class_init_or_throw (klass);
3272 mono_raise_exception (mono_get_exception_argument_null ("name"));
3273 if (type->type->byref)
3276 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3279 if (klass->exception_type != MONO_EXCEPTION_NONE)
3280 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3283 while ((field = mono_class_get_fields (klass, &iter))) {
3286 if (field->type == NULL)
3288 if (mono_field_is_deleted (field))
3290 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3291 if (bflags & BFLAGS_Public)
3293 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3294 if (bflags & BFLAGS_NonPublic) {
3301 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3302 if (bflags & BFLAGS_Static)
3303 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3306 if (bflags & BFLAGS_Instance)
3313 utf8_name = mono_string_to_utf8 (name);
3315 if (compare_func (mono_field_get_name (field), utf8_name)) {
3321 return mono_field_get_object (domain, klass, field);
3323 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3330 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3333 MonoClass *startklass, *klass, *refklass;
3338 MonoClassField *field;
3339 MonoPtrArray tmp_array;
3341 MONO_ARCH_SAVE_REGS;
3343 domain = ((MonoObject *)type)->vtable->domain;
3344 if (type->type->byref)
3345 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3346 klass = startklass = mono_class_from_mono_type (type->type);
3347 refklass = mono_class_from_mono_type (reftype->type);
3349 mono_class_init_or_throw (klass);
3350 mono_class_init_or_throw (refklass);
3352 mono_ptr_array_init (tmp_array, 2);
3355 if (klass->exception_type != MONO_EXCEPTION_NONE)
3356 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3359 while ((field = mono_class_get_fields (klass, &iter))) {
3361 if (mono_field_is_deleted (field))
3363 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3364 if (bflags & BFLAGS_Public)
3366 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3367 if (bflags & BFLAGS_NonPublic) {
3374 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3375 if (bflags & BFLAGS_Static)
3376 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3379 if (bflags & BFLAGS_Instance)
3385 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3386 mono_ptr_array_append (tmp_array, member);
3388 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3391 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3393 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3394 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3396 mono_ptr_array_destroy (tmp_array);
3402 method_nonpublic (MonoMethod* method, gboolean start_klass)
3404 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3405 case METHOD_ATTRIBUTE_ASSEM:
3406 return (start_klass || mono_defaults.generic_ilist_class);
3407 case METHOD_ATTRIBUTE_PRIVATE:
3409 case METHOD_ATTRIBUTE_PUBLIC:
3417 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3419 static MonoClass *MethodInfo_array;
3421 MonoClass *startklass, *klass, *refklass;
3426 int i, len, match, nslots;
3427 /*FIXME, use MonoBitSet*/
3428 guint32 method_slots_default [8];
3429 guint32 *method_slots = NULL;
3430 gchar *mname = NULL;
3431 int (*compare_func) (const char *s1, const char *s2) = NULL;
3432 MonoVTable *array_vtable;
3434 MonoPtrArray tmp_array;
3436 mono_ptr_array_init (tmp_array, 4);
3438 if (!MethodInfo_array) {
3439 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3440 mono_memory_barrier ();
3441 MethodInfo_array = klass;
3444 domain = ((MonoObject *)type)->vtable->domain;
3445 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3446 if (type->type->byref)
3447 return mono_array_new_specific (array_vtable, 0);
3448 klass = startklass = mono_class_from_mono_type (type->type);
3449 refklass = mono_class_from_mono_type (reftype->type);
3451 mono_class_init_or_throw (klass);
3452 mono_class_init_or_throw (refklass);
3456 mname = mono_string_to_utf8 (name);
3457 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3460 /* An optimization for calls made from Delegate:CreateDelegate () */
3461 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3462 method = mono_get_delegate_invoke (klass);
3463 if (mono_loader_get_last_error ())
3466 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3468 res = mono_array_new_specific (array_vtable, 1);
3469 mono_array_setref (res, 0, member);
3474 mono_class_setup_vtable (klass);
3475 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3478 if (is_generic_parameter (type->type))
3479 nslots = mono_class_get_vtable_size (klass->parent);
3481 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3482 if (nslots >= sizeof (method_slots_default) * 8) {
3483 method_slots = g_new0 (guint32, nslots / 32 + 1);
3485 method_slots = method_slots_default;
3486 memset (method_slots, 0, sizeof (method_slots_default));
3489 mono_class_setup_vtable (klass);
3490 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3494 while ((method = mono_class_get_methods (klass, &iter))) {
3496 if (method->slot != -1) {
3497 g_assert (method->slot < nslots);
3498 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3500 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3501 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3504 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3506 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3507 if (bflags & BFLAGS_Public)
3509 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3515 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3516 if (bflags & BFLAGS_Static)
3517 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3520 if (bflags & BFLAGS_Instance)
3528 if (compare_func (mname, method->name))
3534 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3536 mono_ptr_array_append (tmp_array, member);
3538 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3542 if (method_slots != method_slots_default)
3543 g_free (method_slots);
3545 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3547 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3548 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3550 mono_ptr_array_destroy (tmp_array);
3555 if (method_slots != method_slots_default)
3556 g_free (method_slots);
3557 mono_ptr_array_destroy (tmp_array);
3558 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3559 ex = mono_class_get_exception_for_failure (klass);
3561 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3562 mono_loader_clear_error ();
3564 mono_raise_exception (ex);
3569 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3572 static MonoClass *System_Reflection_ConstructorInfo;
3573 MonoClass *startklass, *klass, *refklass;
3578 gpointer iter = NULL;
3579 MonoPtrArray tmp_array;
3581 MONO_ARCH_SAVE_REGS;
3583 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3585 domain = ((MonoObject *)type)->vtable->domain;
3586 if (type->type->byref)
3587 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3588 klass = startklass = mono_class_from_mono_type (type->type);
3589 refklass = mono_class_from_mono_type (reftype->type);
3591 mono_class_init_or_throw (klass);
3592 mono_class_init_or_throw (refklass);
3594 if (klass->exception_type != MONO_EXCEPTION_NONE)
3595 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3597 if (!System_Reflection_ConstructorInfo)
3598 System_Reflection_ConstructorInfo = mono_class_from_name (
3599 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3602 while ((method = mono_class_get_methods (klass, &iter))) {
3604 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3606 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3607 if (bflags & BFLAGS_Public)
3610 if (bflags & BFLAGS_NonPublic)
3616 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3617 if (bflags & BFLAGS_Static)
3618 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3621 if (bflags & BFLAGS_Instance)
3627 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3629 mono_ptr_array_append (tmp_array, member);
3632 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3634 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3635 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3637 mono_ptr_array_destroy (tmp_array);
3643 property_hash (gconstpointer data)
3645 MonoProperty *prop = (MonoProperty*)data;
3647 return g_str_hash (prop->name);
3651 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3653 // Properties are hide-by-name-and-signature
3654 if (!g_str_equal (prop1->name, prop2->name))
3657 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3659 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3665 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3670 return method_nonpublic (accessor, start_klass);
3674 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3677 static MonoClass *System_Reflection_PropertyInfo;
3678 MonoClass *startklass, *klass;
3684 gchar *propname = NULL;
3685 int (*compare_func) (const char *s1, const char *s2) = NULL;
3687 GHashTable *properties;
3688 MonoPtrArray tmp_array;
3690 MONO_ARCH_SAVE_REGS;
3692 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3694 if (!System_Reflection_PropertyInfo)
3695 System_Reflection_PropertyInfo = mono_class_from_name (
3696 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3698 domain = ((MonoObject *)type)->vtable->domain;
3699 if (type->type->byref)
3700 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3701 klass = startklass = mono_class_from_mono_type (type->type);
3702 mono_class_init_or_throw (klass);
3707 propname = mono_string_to_utf8 (name);
3708 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3711 mono_class_setup_vtable (klass);
3713 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3715 mono_class_setup_vtable (klass);
3716 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3717 g_hash_table_destroy (properties);
3720 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3724 while ((prop = mono_class_get_properties (klass, &iter))) {
3730 flags = method->flags;
3733 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3734 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3735 if (bflags & BFLAGS_Public)
3737 } else if (bflags & BFLAGS_NonPublic) {
3738 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3739 property_accessor_nonpublic(prop->set, startklass == klass)) {
3746 if (flags & METHOD_ATTRIBUTE_STATIC) {
3747 if (bflags & BFLAGS_Static)
3748 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3751 if (bflags & BFLAGS_Instance)
3760 if (compare_func (propname, prop->name))
3764 if (g_hash_table_lookup (properties, prop))
3767 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3769 g_hash_table_insert (properties, prop, prop);
3771 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3774 g_hash_table_destroy (properties);
3777 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3778 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3779 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3781 mono_ptr_array_destroy (tmp_array);
3786 static MonoReflectionEvent *
3787 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3790 MonoClass *klass, *startklass;
3796 MONO_ARCH_SAVE_REGS;
3798 event_name = mono_string_to_utf8 (name);
3799 if (type->type->byref)
3801 klass = startklass = mono_class_from_mono_type (type->type);
3802 domain = mono_object_domain (type);
3804 mono_class_init_or_throw (klass);
3807 if (klass->exception_type != MONO_EXCEPTION_NONE)
3808 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3811 while ((event = mono_class_get_events (klass, &iter))) {
3812 if (strcmp (event->name, event_name))
3815 method = event->add;
3817 method = event->remove;
3819 method = event->raise;
3821 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3822 if (!(bflags & BFLAGS_Public))
3825 if (!(bflags & BFLAGS_NonPublic))
3827 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3831 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3832 if (!(bflags & BFLAGS_Static))
3834 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3837 if (!(bflags & BFLAGS_Instance))
3841 if (!(bflags & BFLAGS_NonPublic))
3844 g_free (event_name);
3845 return mono_event_get_object (domain, startklass, event);
3848 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3851 g_free (event_name);
3856 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3859 static MonoClass *System_Reflection_EventInfo;
3860 MonoClass *startklass, *klass;
3867 MonoPtrArray tmp_array;
3869 MONO_ARCH_SAVE_REGS;
3871 mono_ptr_array_init (tmp_array, 4);
3873 if (!System_Reflection_EventInfo)
3874 System_Reflection_EventInfo = mono_class_from_name (
3875 mono_defaults.corlib, "System.Reflection", "EventInfo");
3877 domain = mono_object_domain (type);
3878 if (type->type->byref)
3879 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3880 klass = startklass = mono_class_from_mono_type (type->type);
3881 mono_class_init_or_throw (klass);
3885 if (klass->exception_type != MONO_EXCEPTION_NONE)
3886 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3889 while ((event = mono_class_get_events (klass, &iter))) {
3891 method = event->add;
3893 method = event->remove;
3895 method = event->raise;
3897 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3898 if (bflags & BFLAGS_Public)
3900 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3901 if (bflags & BFLAGS_NonPublic)
3906 if (bflags & BFLAGS_NonPublic)
3912 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3913 if (bflags & BFLAGS_Static)
3914 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3917 if (bflags & BFLAGS_Instance)
3922 if (bflags & BFLAGS_Instance)
3926 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3928 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3931 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3933 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3934 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3936 mono_ptr_array_destroy (tmp_array);
3941 static MonoReflectionType *
3942 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3950 MONO_ARCH_SAVE_REGS;
3953 mono_raise_exception (mono_get_exception_argument_null ("name"));
3955 domain = ((MonoObject *)type)->vtable->domain;
3956 if (type->type->byref)
3958 klass = mono_class_from_mono_type (type->type);
3959 mono_class_init_or_throw (klass);
3961 str = mono_string_to_utf8 (name);
3964 if (klass->exception_type != MONO_EXCEPTION_NONE)
3965 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3968 * If a nested type is generic, return its generic type definition.
3969 * Note that this means that the return value is essentially a
3970 * nested type of the generic type definition of @klass.
3972 * A note in MSDN claims that a generic type definition can have
3973 * nested types that aren't generic. In any case, the container of that
3974 * nested type would be the generic type definition.
3976 if (klass->generic_class)
3977 klass = klass->generic_class->container_class;
3980 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3982 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3983 if (bflags & BFLAGS_Public)
3986 if (bflags & BFLAGS_NonPublic)
3991 if (strcmp (nested->name, str) == 0){
3993 return mono_type_get_object (domain, &nested->byval_arg);
3996 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4003 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4012 MonoPtrArray tmp_array;
4014 MONO_ARCH_SAVE_REGS;
4016 domain = ((MonoObject *)type)->vtable->domain;
4017 if (type->type->byref)
4018 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4019 klass = mono_class_from_mono_type (type->type);
4020 mono_class_init_or_throw (klass);
4023 * If a nested type is generic, return its generic type definition.
4024 * Note that this means that the return value is essentially the set
4025 * of nested types of the generic type definition of @klass.
4027 * A note in MSDN claims that a generic type definition can have
4028 * nested types that aren't generic. In any case, the container of that
4029 * nested type would be the generic type definition.
4031 if (klass->generic_class)
4032 klass = klass->generic_class->container_class;
4034 mono_ptr_array_init (tmp_array, 1);
4036 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4038 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4039 if (bflags & BFLAGS_Public)
4042 if (bflags & BFLAGS_NonPublic)
4047 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4048 mono_ptr_array_append (tmp_array, member);
4051 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4053 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4054 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4056 mono_ptr_array_destroy (tmp_array);
4061 static MonoReflectionType*
4062 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4065 MonoType *type = NULL;
4066 MonoTypeNameParse info;
4067 gboolean type_resolve;
4069 MONO_ARCH_SAVE_REGS;
4071 /* On MS.NET, this does not fire a TypeResolve event */
4072 type_resolve = TRUE;
4073 str = mono_string_to_utf8 (name);
4074 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4075 if (!mono_reflection_parse_type (str, &info)) {
4077 mono_reflection_free_type_info (&info);
4078 if (throwOnError) /* uhm: this is a parse error, though... */
4079 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4080 /*g_print ("failed parse\n");*/
4084 if (info.assembly.name) {
4086 mono_reflection_free_type_info (&info);
4088 /* 1.0 and 2.0 throw different exceptions */
4089 if (mono_defaults.generic_ilist_class)
4090 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4092 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4097 if (module != NULL) {
4099 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4104 if (assembly->assembly->dynamic) {
4105 /* Enumerate all modules */
4106 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4110 if (abuilder->modules) {
4111 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4112 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4113 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4119 if (!type && abuilder->loaded_modules) {
4120 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4121 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4122 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4129 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4131 mono_reflection_free_type_info (&info);
4133 MonoException *e = NULL;
4136 e = mono_get_exception_type_load (name, NULL);
4138 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4139 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4141 mono_loader_clear_error ();
4144 mono_raise_exception (e);
4149 if (type->type == MONO_TYPE_CLASS) {
4150 MonoClass *klass = mono_type_get_class (type);
4152 if (mono_is_security_manager_active () && !klass->exception_type)
4153 /* Some security problems are detected during generic vtable construction */
4154 mono_class_setup_vtable (klass);
4155 /* need to report exceptions ? */
4156 if (throwOnError && klass->exception_type) {
4157 /* report SecurityException (or others) that occured when loading the assembly */
4158 MonoException *exc = mono_class_get_exception_for_failure (klass);
4159 mono_loader_clear_error ();
4160 mono_raise_exception (exc);
4161 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4166 /* g_print ("got it\n"); */
4167 return mono_type_get_object (mono_object_domain (assembly), type);
4171 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4174 gchar *shadow_ini_file;
4177 /* Check for shadow-copied assembly */
4178 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4179 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4181 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4182 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4188 g_free (shadow_ini_file);
4189 if (content != NULL) {
4192 *filename = content;
4200 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4202 MonoDomain *domain = mono_object_domain (assembly);
4203 MonoAssembly *mass = assembly->assembly;
4204 MonoString *res = NULL;
4209 MONO_ARCH_SAVE_REGS;
4211 if (g_path_is_absolute (mass->image->name)) {
4212 absolute = g_strdup (mass->image->name);
4213 dirname = g_path_get_dirname (absolute);
4215 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4216 dirname = g_strdup (mass->basedir);
4219 replace_shadow_path (domain, dirname, &absolute);
4224 for (i = strlen (absolute) - 1; i >= 0; i--)
4225 if (absolute [i] == '\\')
4230 uri = g_filename_to_uri (absolute, NULL, NULL);
4232 const char *prepend = "file://";
4234 if (*absolute == '/' && *(absolute + 1) == '/') {
4237 prepend = "file:///";
4240 uri = g_strconcat (prepend, absolute, NULL);
4244 res = mono_string_new (domain, uri);
4252 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4254 MonoAssembly *mass = assembly->assembly;
4256 MONO_ARCH_SAVE_REGS;
4258 return mass->in_gac;
4261 static MonoReflectionAssembly*
4262 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4266 MonoImageOpenStatus status;
4268 MONO_ARCH_SAVE_REGS;
4270 name = mono_string_to_utf8 (mname);
4271 res = mono_assembly_load_with_partial_name (name, &status);
4277 return mono_assembly_get_object (mono_domain_get (), res);
4281 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4283 MonoDomain *domain = mono_object_domain (assembly);
4286 MONO_ARCH_SAVE_REGS;
4288 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4294 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4296 MONO_ARCH_SAVE_REGS;
4298 return assembly->assembly->ref_only;
4302 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4304 MonoDomain *domain = mono_object_domain (assembly);
4306 MONO_ARCH_SAVE_REGS;
4308 return mono_string_new (domain, assembly->assembly->image->version);
4311 static MonoReflectionMethod*
4312 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4314 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4316 MONO_ARCH_SAVE_REGS;
4320 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4323 static MonoReflectionModule*
4324 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4326 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4330 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4332 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4333 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4337 MONO_ARCH_SAVE_REGS;
4339 for (i = 0; i < table->rows; ++i) {
4340 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4341 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4347 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4349 static MonoClass *System_Version = NULL;
4350 static MonoMethod *create_version = NULL;
4354 if (!System_Version) {
4355 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4356 g_assert (System_Version);
4359 if (!create_version) {
4360 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4361 create_version = mono_method_desc_search_in_class (desc, System_Version);
4362 g_assert (create_version);
4363 mono_method_desc_free (desc);
4369 args [3] = &revision;
4370 result = mono_object_new (domain, System_Version);
4371 mono_runtime_invoke (create_version, result, args, NULL);
4377 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4379 static MonoClass *System_Reflection_AssemblyName;
4381 MonoDomain *domain = mono_object_domain (assembly);
4383 static MonoMethod *create_culture = NULL;
4384 MonoImage *image = assembly->assembly->image;
4387 MONO_ARCH_SAVE_REGS;
4389 if (!System_Reflection_AssemblyName)
4390 System_Reflection_AssemblyName = mono_class_from_name (
4391 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4393 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4396 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4398 if (count > 0 && !create_culture) {
4399 MonoMethodDesc *desc = mono_method_desc_new (
4400 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4401 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4402 g_assert (create_culture);
4403 mono_method_desc_free (desc);
4406 for (i = 0; i < count; i++) {
4407 MonoReflectionAssemblyName *aname;
4408 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4410 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4412 aname = (MonoReflectionAssemblyName *) mono_object_new (
4413 domain, System_Reflection_AssemblyName);
4415 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4417 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4418 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4419 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4420 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4421 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4422 aname->versioncompat = 1; /* SameMachine (default) */
4423 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4424 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4426 if (create_culture) {
4428 MonoBoolean assembly_ref = 1;
4429 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4430 args [1] = &assembly_ref;
4431 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4434 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4435 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4436 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4438 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4439 /* public key token isn't copied - the class library will
4440 automatically generate it from the public key if required */
4441 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4442 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4444 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4445 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4448 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4451 /* note: this function doesn't return the codebase on purpose (i.e. it can
4452 be used under partial trust as path information isn't present). */
4454 mono_array_setref (result, i, aname);
4465 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4467 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4469 mono_array_setref (info->res, info->idx, name);
4474 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4476 MonoImage *img = assembly->assembly->image;
4481 MONO_ARCH_SAVE_REGS;
4483 mono_image_lock (img);
4484 mono_image_init_name_cache (img);
4487 len = g_hash_table_size (img->name_cache);
4488 mono_image_unlock (img);
4490 /*we can't create objects holding the image lock */
4491 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4493 mono_image_lock (img);
4494 /*len might have changed, create a new array*/
4495 if (len != g_hash_table_size (img->name_cache))
4500 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4501 mono_image_unlock (img);
4506 /* move this in some file in mono/util/ */
4508 g_concat_dir_and_file (const char *dir, const char *file)
4510 g_return_val_if_fail (dir != NULL, NULL);
4511 g_return_val_if_fail (file != NULL, NULL);
4514 * If the directory name doesn't have a / on the end, we need
4515 * to add one so we get a proper path to the file
4517 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4518 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4520 return g_strconcat (dir, file, NULL);
4524 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4526 char *n = mono_string_to_utf8 (name);
4527 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4529 guint32 cols [MONO_MANIFEST_SIZE];
4530 guint32 impl, file_idx;
4534 MONO_ARCH_SAVE_REGS;
4536 for (i = 0; i < table->rows; ++i) {
4537 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4538 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4539 if (strcmp (val, n) == 0)
4543 if (i == table->rows)
4546 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4549 * this code should only be called after obtaining the
4550 * ResourceInfo and handling the other cases.
4552 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4553 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4555 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4560 module = assembly->assembly->image;
4562 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4564 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4568 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4570 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4572 guint32 cols [MONO_MANIFEST_SIZE];
4573 guint32 file_cols [MONO_FILE_SIZE];
4577 MONO_ARCH_SAVE_REGS;
4579 n = mono_string_to_utf8 (name);
4580 for (i = 0; i < table->rows; ++i) {
4581 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4582 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4583 if (strcmp (val, n) == 0)
4587 if (i == table->rows)
4590 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4591 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4594 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4595 case MONO_IMPLEMENTATION_FILE:
4596 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4597 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4598 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4599 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4600 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4601 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4604 info->location = RESOURCE_LOCATION_EMBEDDED;
4607 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4608 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4609 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4610 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4611 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4612 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4614 mono_raise_exception (ex);
4616 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4618 /* Obtain info recursively */
4619 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4620 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4623 case MONO_IMPLEMENTATION_EXP_TYPE:
4624 g_assert_not_reached ();
4633 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4635 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4636 MonoArray *result = NULL;
4641 MONO_ARCH_SAVE_REGS;
4643 /* check hash if needed */
4645 n = mono_string_to_utf8 (name);
4646 for (i = 0; i < table->rows; ++i) {
4647 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4648 if (strcmp (val, n) == 0) {
4651 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4652 fn = mono_string_new (mono_object_domain (assembly), n);
4654 return (MonoObject*)fn;
4662 for (i = 0; i < table->rows; ++i) {
4663 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4667 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4670 for (i = 0; i < table->rows; ++i) {
4671 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4672 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4673 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4674 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4679 return (MonoObject*)result;
4683 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4685 MonoDomain *domain = mono_domain_get();
4688 int i, j, file_count = 0;
4689 MonoImage **modules;
4690 guint32 module_count, real_module_count;
4691 MonoTableInfo *table;
4692 guint32 cols [MONO_FILE_SIZE];
4693 MonoImage *image = assembly->assembly->image;
4695 g_assert (image != NULL);
4696 g_assert (!assembly->assembly->dynamic);
4698 table = &image->tables [MONO_TABLE_FILE];
4699 file_count = table->rows;
4701 modules = image->modules;
4702 module_count = image->module_count;
4704 real_module_count = 0;
4705 for (i = 0; i < module_count; ++i)
4707 real_module_count ++;
4709 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4710 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4712 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4714 for (i = 0; i < module_count; ++i)
4716 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4720 for (i = 0; i < file_count; ++i, ++j) {
4721 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4722 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4723 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4725 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4727 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4728 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4730 mono_array_setref (res, j, mono_module_get_object (domain, m));
4737 static MonoReflectionMethod*
4738 ves_icall_GetCurrentMethod (void)
4740 MonoMethod *m = mono_method_get_last_managed ();
4742 while (m->is_inflated)
4743 m = ((MonoMethodInflated*)m)->declaring;
4745 return mono_method_get_object (mono_domain_get (), m, NULL);
4750 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4753 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4754 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4755 //method is inflated, we should inflate it on the other class
4756 MonoGenericContext ctx;
4757 ctx.method_inst = inflated->context.method_inst;
4758 ctx.class_inst = inflated->context.class_inst;
4759 if (klass->generic_class)
4760 ctx.class_inst = klass->generic_class->context.class_inst;
4761 else if (klass->generic_container)
4762 ctx.class_inst = klass->generic_container->context.class_inst;
4763 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4766 mono_class_setup_methods (method->klass);
4767 if (method->klass->exception_type)
4769 for (i = 0; i < method->klass->method.count; ++i) {
4770 if (method->klass->methods [i] == method) {
4775 mono_class_setup_methods (klass);
4776 if (klass->exception_type)
4778 g_assert (offset >= 0 && offset < klass->method.count);
4779 return klass->methods [offset];
4782 static MonoReflectionMethod*
4783 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4787 klass = mono_class_from_mono_type (type);
4788 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4790 if (method->klass != klass) {
4791 method = mono_method_get_equivalent_method (method, klass);
4796 klass = method->klass;
4797 return mono_method_get_object (mono_domain_get (), method, klass);
4800 static MonoReflectionMethod*
4801 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4803 return mono_method_get_object (mono_domain_get (), method, NULL);
4806 static MonoReflectionMethodBody*
4807 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4809 return mono_method_body_get_object (mono_domain_get (), method);
4812 static MonoReflectionAssembly*
4813 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4815 MonoMethod *dest = NULL;
4817 MONO_ARCH_SAVE_REGS;
4819 mono_stack_walk_no_il (get_executing, &dest);
4820 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4824 static MonoReflectionAssembly*
4825 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4827 MonoDomain* domain = mono_domain_get ();
4829 MONO_ARCH_SAVE_REGS;
4831 if (!domain->entry_assembly)
4834 return mono_assembly_get_object (domain, domain->entry_assembly);
4837 static MonoReflectionAssembly*
4838 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4843 MONO_ARCH_SAVE_REGS;
4846 mono_stack_walk_no_il (get_executing, &dest);
4848 mono_stack_walk_no_il (get_caller, &dest);
4851 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4855 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4856 gboolean assembly_qualified)
4858 MonoDomain *domain = mono_object_domain (object);
4859 MonoTypeNameFormat format;
4863 MONO_ARCH_SAVE_REGS;
4865 mono_class_init_or_throw (mono_class_from_mono_type (object->type));
4868 format = assembly_qualified ?
4869 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4870 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4872 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4874 name = mono_type_get_name_full (object->type, format);
4878 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4883 res = mono_string_new (domain, name);
4890 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4892 MonoClass *klass = mono_class_from_mono_type (this->type);
4893 mono_class_init_or_throw (klass);
4894 return mono_security_core_clr_class_level (klass);
4898 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4900 static MonoMethod *create_culture = NULL;
4903 const char *pkey_ptr;
4905 MonoBoolean assembly_ref = 0;
4907 MONO_ARCH_SAVE_REGS;
4909 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4910 aname->major = name->major;
4911 aname->minor = name->minor;
4912 aname->build = name->build;
4913 aname->flags = name->flags;
4914 aname->revision = name->revision;
4915 aname->hashalg = name->hash_alg;
4916 aname->versioncompat = 1; /* SameMachine (default) */
4918 if (by_default_version)
4919 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4922 if (absolute != NULL && *absolute != '\0') {
4923 const gchar *prepend = "file://";
4926 codebase = g_strdup (absolute);
4931 for (i = strlen (codebase) - 1; i >= 0; i--)
4932 if (codebase [i] == '\\')
4935 if (*codebase == '/' && *(codebase + 1) == '/') {
4938 prepend = "file:///";
4942 result = g_strconcat (prepend, codebase, NULL);
4948 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4952 if (!create_culture) {
4953 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4954 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4955 g_assert (create_culture);
4956 mono_method_desc_free (desc);
4959 if (name->culture) {
4960 args [0] = mono_string_new (domain, name->culture);
4961 args [1] = &assembly_ref;
4962 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4965 if (name->public_key) {
4966 pkey_ptr = (char*)name->public_key;
4967 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4969 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4970 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4971 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4972 } else if (default_publickey) {
4973 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4974 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4977 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4978 if (name->public_key_token [0]) {
4982 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4983 p = mono_array_addr (aname->keyToken, char, 0);
4985 for (i = 0, j = 0; i < 8; i++) {
4986 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4987 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4990 } else if (default_token) {
4991 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4996 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4998 MonoDomain *domain = mono_object_domain (assembly);
4999 MonoAssembly *mass = assembly->assembly;
5003 name = g_strdup_printf (
5004 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5006 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5007 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5008 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5009 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5011 res = mono_string_new (domain, name);
5018 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5021 MonoAssembly *mass = assembly->assembly;
5023 MONO_ARCH_SAVE_REGS;
5025 if (g_path_is_absolute (mass->image->name)) {
5026 fill_reflection_assembly_name (mono_object_domain (assembly),
5027 aname, &mass->aname, mass->image->name, TRUE,
5031 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5033 fill_reflection_assembly_name (mono_object_domain (assembly),
5034 aname, &mass->aname, absolute, TRUE, TRUE,
5041 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5044 MonoImageOpenStatus status = MONO_IMAGE_OK;
5047 MonoAssemblyName name;
5050 MONO_ARCH_SAVE_REGS;
5052 filename = mono_string_to_utf8 (fname);
5054 dirname = g_path_get_dirname (filename);
5055 replace_shadow_path (mono_domain_get (), dirname, &filename);
5058 image = mono_image_open (filename, &status);
5064 if (status == MONO_IMAGE_IMAGE_INVALID)
5065 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5067 exc = mono_get_exception_file_not_found2 (NULL, fname);
5068 mono_raise_exception (exc);
5071 res = mono_assembly_fill_assembly_name (image, &name);
5073 mono_image_close (image);
5075 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5078 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5082 mono_image_close (image);
5086 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5087 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5089 MonoBoolean result = FALSE;
5090 MonoDeclSecurityEntry entry;
5092 /* SecurityAction.RequestMinimum */
5093 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5094 *minimum = entry.blob;
5095 *minLength = entry.size;
5098 /* SecurityAction.RequestOptional */
5099 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5100 *optional = entry.blob;
5101 *optLength = entry.size;
5104 /* SecurityAction.RequestRefuse */
5105 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5106 *refused = entry.blob;
5107 *refLength = entry.size;
5115 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5119 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5121 guint32 attrs, visibility;
5123 /* we start the count from 1 because we skip the special type <Module> */
5126 for (i = 1; i < tdef->rows; ++i) {
5127 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5128 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5129 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5133 count = tdef->rows - 1;
5135 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5136 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5138 for (i = 1; i < tdef->rows; ++i) {
5139 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5140 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5141 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5142 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5144 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5146 MonoLoaderError *error;
5149 error = mono_loader_get_last_error ();
5150 g_assert (error != NULL);
5152 ex = mono_loader_error_prepare_exception (error);
5153 mono_array_setref (*exceptions, count, ex);
5155 if (mono_loader_get_last_error ())
5156 mono_loader_clear_error ();
5165 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5167 MonoArray *res = NULL;
5168 MonoArray *exceptions = NULL;
5169 MonoImage *image = NULL;
5170 MonoTableInfo *table = NULL;
5173 int i, len, ex_count;
5175 MONO_ARCH_SAVE_REGS;
5177 domain = mono_object_domain (assembly);
5179 g_assert (!assembly->assembly->dynamic);
5180 image = assembly->assembly->image;
5181 table = &image->tables [MONO_TABLE_FILE];
5182 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5184 /* Append data from all modules in the assembly */
5185 for (i = 0; i < table->rows; ++i) {
5186 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5187 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5190 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5191 /* Append the new types to the end of the array */
5192 if (mono_array_length (res2) > 0) {
5194 MonoArray *res3, *ex3;
5196 len1 = mono_array_length (res);
5197 len2 = mono_array_length (res2);
5199 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5200 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5201 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5204 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5205 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5206 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5213 /* the ReflectionTypeLoadException must have all the types (Types property),
5214 * NULL replacing types which throws an exception. The LoaderException must
5215 * contain all exceptions for NULL items.
5218 len = mono_array_length (res);
5221 for (i = 0; i < len; i++) {
5222 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5226 klass = mono_type_get_class (t->type);
5227 if ((klass != NULL) && klass->exception_type) {
5228 /* keep the class in the list */
5229 list = g_list_append (list, klass);
5230 /* and replace Type with NULL */
5231 mono_array_setref (res, i, NULL);
5238 if (list || ex_count) {
5240 MonoException *exc = NULL;
5241 MonoArray *exl = NULL;
5242 int j, length = g_list_length (list) + ex_count;
5244 mono_loader_clear_error ();
5246 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5247 /* Types for which mono_class_get () succeeded */
5248 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5249 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5250 mono_array_setref (exl, i, exc);
5252 /* Types for which it don't */
5253 for (j = 0; j < mono_array_length (exceptions); ++j) {
5254 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5256 g_assert (i < length);
5257 mono_array_setref (exl, i, exc);
5264 exc = mono_get_exception_reflection_type_load (res, exl);
5265 mono_loader_clear_error ();
5266 mono_raise_exception (exc);
5273 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5275 MonoAssemblyName aname;
5276 MonoDomain *domain = mono_object_domain (name);
5278 gboolean is_version_defined;
5279 gboolean is_token_defined;
5281 aname.public_key = NULL;
5282 val = mono_string_to_utf8 (assname);
5283 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5284 g_free ((guint8*) aname.public_key);
5289 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5290 FALSE, is_token_defined);
5292 mono_assembly_name_free (&aname);
5293 g_free ((guint8*) aname.public_key);
5299 static MonoReflectionType*
5300 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5302 MonoDomain *domain = mono_object_domain (module);
5305 MONO_ARCH_SAVE_REGS;
5307 g_assert (module->image);
5309 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5310 /* These images do not have a global type */
5313 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5314 return mono_type_get_object (domain, &klass->byval_arg);
5318 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5320 /*if (module->image)
5321 mono_image_close (module->image);*/
5325 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5327 MonoDomain *domain = mono_object_domain (module);
5329 MONO_ARCH_SAVE_REGS;
5331 g_assert (module->image);
5332 return mono_string_new (domain, module->image->guid);
5336 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5339 if (module->image && module->image->is_module_handle)
5340 return module->image->raw_data;
5343 return (gpointer) (-1);
5347 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5349 if (image->dynamic) {
5350 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5351 *pe_kind = dyn->pe_kind;
5352 *machine = dyn->machine;
5355 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5356 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5361 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5363 return (image->md_version_major << 16) | (image->md_version_minor);
5367 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5369 MonoArray *exceptions;
5372 MONO_ARCH_SAVE_REGS;
5375 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5377 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5378 for (i = 0; i < mono_array_length (exceptions); ++i) {
5379 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5381 mono_raise_exception (ex);
5388 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5390 guint32 cols [MONO_MEMBERREF_SIZE];
5392 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5393 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5394 mono_metadata_decode_blob_size (sig, &sig);
5395 return (*sig != 0x6);
5399 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5402 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5403 mono_array_addr (type_args, MonoType*, 0));
5405 context->class_inst = NULL;
5407 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5408 mono_array_addr (method_args, MonoType*, 0));
5410 context->method_inst = NULL;
5414 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5417 int table = mono_metadata_token_table (token);
5418 int index = mono_metadata_token_index (token);
5419 MonoGenericContext context;
5421 *error = ResolveTokenError_Other;
5423 /* Validate token */
5424 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5425 (table != MONO_TABLE_TYPESPEC)) {
5426 *error = ResolveTokenError_BadTable;
5430 if (image->dynamic) {
5431 if (type_args || method_args)
5432 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5433 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5436 return &klass->byval_arg;
5439 if ((index <= 0) || (index > image->tables [table].rows)) {
5440 *error = ResolveTokenError_OutOfRange;
5444 init_generic_context_from_args (&context, type_args, method_args);
5445 klass = mono_class_get_full (image, token, &context);
5447 if (mono_loader_get_last_error ())
5448 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5451 return &klass->byval_arg;
5457 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5459 int table = mono_metadata_token_table (token);
5460 int index = mono_metadata_token_index (token);
5461 MonoGenericContext context;
5464 *error = ResolveTokenError_Other;
5466 /* Validate token */
5467 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5468 (table != MONO_TABLE_MEMBERREF)) {
5469 *error = ResolveTokenError_BadTable;
5473 if (image->dynamic) {
5474 if (type_args || method_args)
5475 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5476 /* FIXME: validate memberref token type */
5477 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5480 if ((index <= 0) || (index > image->tables [table].rows)) {
5481 *error = ResolveTokenError_OutOfRange;
5484 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5485 *error = ResolveTokenError_BadTable;
5489 init_generic_context_from_args (&context, type_args, method_args);
5490 method = mono_get_method_full (image, token, NULL, &context);
5492 if (mono_loader_get_last_error ())
5493 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5499 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5501 int index = mono_metadata_token_index (token);
5503 *error = ResolveTokenError_Other;
5505 /* Validate token */
5506 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5507 *error = ResolveTokenError_BadTable;
5512 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5514 if ((index <= 0) || (index >= image->heap_us.size)) {
5515 *error = ResolveTokenError_OutOfRange;
5519 /* FIXME: What to do if the index points into the middle of a string ? */
5521 return mono_ldstr (mono_domain_get (), image, index);
5524 static MonoClassField*
5525 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5528 int table = mono_metadata_token_table (token);
5529 int index = mono_metadata_token_index (token);
5530 MonoGenericContext context;
5531 MonoClassField *field;
5533 *error = ResolveTokenError_Other;
5535 /* Validate token */
5536 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5537 *error = ResolveTokenError_BadTable;
5541 if (image->dynamic) {
5542 if (type_args || method_args)
5543 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5544 /* FIXME: validate memberref token type */
5545 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5548 if ((index <= 0) || (index > image->tables [table].rows)) {
5549 *error = ResolveTokenError_OutOfRange;
5552 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5553 *error = ResolveTokenError_BadTable;
5557 init_generic_context_from_args (&context, type_args, method_args);
5558 field = mono_field_from_token (image, token, &klass, &context);
5560 if (mono_loader_get_last_error ())
5561 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5568 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5570 int table = mono_metadata_token_table (token);
5572 *error = ResolveTokenError_Other;
5575 case MONO_TABLE_TYPEDEF:
5576 case MONO_TABLE_TYPEREF:
5577 case MONO_TABLE_TYPESPEC: {
5578 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5580 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5584 case MONO_TABLE_METHOD:
5585 case MONO_TABLE_METHODSPEC: {
5586 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5588 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5592 case MONO_TABLE_FIELD: {
5593 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5595 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5599 case MONO_TABLE_MEMBERREF:
5600 if (mono_metadata_memberref_is_method (image, token)) {
5601 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5603 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5608 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5610 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5617 *error = ResolveTokenError_BadTable;
5624 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5626 int table = mono_metadata_token_table (token);
5627 int idx = mono_metadata_token_index (token);
5628 MonoTableInfo *tables = image->tables;
5633 *error = ResolveTokenError_OutOfRange;
5635 /* FIXME: Support other tables ? */
5636 if (table != MONO_TABLE_STANDALONESIG)
5642 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5645 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5647 ptr = mono_metadata_blob_heap (image, sig);
5648 len = mono_metadata_decode_blob_size (ptr, &ptr);
5650 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5651 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5655 static MonoReflectionType*
5656 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5659 int isbyref = 0, rank;
5660 char *str = mono_string_to_utf8 (smodifiers);
5663 MONO_ARCH_SAVE_REGS;
5665 klass = mono_class_from_mono_type (tb->type.type);
5667 /* logic taken from mono_reflection_parse_type(): keep in sync */
5671 if (isbyref) { /* only one level allowed by the spec */
5678 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5681 klass = mono_ptr_class_get (&klass->byval_arg);
5682 mono_class_init (klass);
5693 else if (*p != '*') { /* '*' means unknown lower bound */
5704 klass = mono_array_class_get (klass, rank);
5705 mono_class_init (klass);
5712 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5716 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5721 MONO_ARCH_SAVE_REGS;
5724 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5729 static MonoReflectionType *
5730 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5732 MonoClass *klass, *aklass;
5734 MONO_ARCH_SAVE_REGS;
5736 klass = mono_class_from_mono_type (type->type);
5737 mono_class_init_or_throw (klass);
5739 if (rank == 0) //single dimentional array
5740 aklass = mono_array_class_get (klass, 1);
5742 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5744 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5747 static MonoReflectionType *
5748 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5752 MONO_ARCH_SAVE_REGS;
5754 klass = mono_class_from_mono_type (type->type);
5755 mono_class_init_or_throw (klass);
5757 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5760 static MonoReflectionType *
5761 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5765 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
5767 pklass = mono_ptr_class_get (type->type);
5769 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5773 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5774 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5776 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5777 MonoObject *delegate;
5779 MonoMethod *method = info->method;
5781 MONO_ARCH_SAVE_REGS;
5783 mono_class_init_or_throw (delegate_class);
5785 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5787 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5788 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5792 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5794 if (method->dynamic) {
5795 /* Creating a trampoline would leak memory */
5796 func = mono_compile_method (method);
5798 func = mono_create_ftnptr (mono_domain_get (),
5799 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5802 mono_delegate_ctor_with_method (delegate, target, func, method);
5808 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5810 /* Reset the invoke impl to the default one */
5811 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5815 * Magic number to convert a time which is relative to
5816 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5818 #define EPOCH_ADJUST ((guint64)62135596800LL)
5821 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5823 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5826 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5828 convert_to_absolute_date(SYSTEMTIME *date)
5830 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5831 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5832 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5833 /* from the calendar FAQ */
5834 int a = (14 - date->wMonth) / 12;
5835 int y = date->wYear - a;
5836 int m = date->wMonth + 12 * a - 2;
5837 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5839 /* d is now the day of the week for the first of the month (0 == Sunday) */
5841 int day_of_week = date->wDayOfWeek;
5843 /* set day_in_month to the first day in the month which falls on day_of_week */
5844 int day_in_month = 1 + (day_of_week - d);
5845 if (day_in_month <= 0)
5848 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5849 date->wDay = day_in_month + (date->wDay - 1) * 7;
5850 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5857 * Return's the offset from GMT of a local time.
5859 * tm is a local time
5860 * t is the same local time as seconds.
5863 gmt_offset(struct tm *tm, time_t t)
5865 #if defined (HAVE_TM_GMTOFF)
5866 return tm->tm_gmtoff;
5871 g.tm_isdst = tm->tm_isdst;
5873 return (int)difftime(t, t2);
5878 * This is heavily based on zdump.c from glibc 2.2.
5880 * * data[0]: start of daylight saving time (in DateTime ticks).
5881 * * data[1]: end of daylight saving time (in DateTime ticks).
5882 * * data[2]: utcoffset (in TimeSpan ticks).
5883 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5884 * * name[0]: name of this timezone when not daylight saving.
5885 * * name[1]: name of this timezone when daylight saving.
5887 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5888 * the class library allows years between 1 and 9999.
5890 * Returns true on success and zero on failure.
5893 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5896 MonoDomain *domain = mono_domain_get ();
5897 struct tm start, tt;
5901 int is_daylight = 0, day;
5904 MONO_ARCH_SAVE_REGS;
5906 MONO_CHECK_ARG_NULL (data);
5907 MONO_CHECK_ARG_NULL (names);
5909 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5910 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5913 * no info is better than crashing: we'll need our own tz data
5914 * to make this work properly, anyway. The range is probably
5915 * reduced to 1970 .. 2037 because that is what mktime is
5916 * guaranteed to support (we get into an infinite loop
5920 memset (&start, 0, sizeof (start));
5923 start.tm_year = year-1900;
5925 t = mktime (&start);
5927 if ((year < 1970) || (year > 2037) || (t == -1)) {
5929 tt = *localtime (&t);
5930 strftime (tzone, sizeof (tzone), "%Z", &tt);
5931 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5932 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5936 gmtoff = gmt_offset (&start, t);
5938 /* For each day of the year, calculate the tm_gmtoff. */
5939 for (day = 0; day < 365; day++) {
5942 tt = *localtime (&t);
5944 /* Daylight saving starts or ends here. */
5945 if (gmt_offset (&tt, t) != gmtoff) {
5949 /* Try to find the exact hour when daylight saving starts/ends. */
5953 tt1 = *localtime (&t1);
5954 } while (gmt_offset (&tt1, t1) != gmtoff);
5956 /* Try to find the exact minute when daylight saving starts/ends. */
5959 tt1 = *localtime (&t1);
5960 } while (gmt_offset (&tt1, t1) == gmtoff);
5962 strftime (tzone, sizeof (tzone), "%Z", &tt);
5964 /* Write data, if we're already in daylight saving, we're done. */
5966 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5967 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5970 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5971 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5975 /* This is only set once when we enter daylight saving. */
5976 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5977 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5979 gmtoff = gmt_offset (&tt, t);
5984 strftime (tzone, sizeof (tzone), "%Z", &tt);
5985 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5986 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5987 mono_array_set ((*data), gint64, 0, 0);
5988 mono_array_set ((*data), gint64, 1, 0);
5989 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5990 mono_array_set ((*data), gint64, 3, 0);
5995 MonoDomain *domain = mono_domain_get ();
5996 TIME_ZONE_INFORMATION tz_info;
6001 tz_id = GetTimeZoneInformation (&tz_info);
6002 if (tz_id == TIME_ZONE_ID_INVALID)
6005 MONO_CHECK_ARG_NULL (data);
6006 MONO_CHECK_ARG_NULL (names);
6008 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6009 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6011 for (i = 0; i < 32; ++i)
6012 if (!tz_info.DaylightName [i])
6014 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6015 for (i = 0; i < 32; ++i)
6016 if (!tz_info.StandardName [i])
6018 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6020 if ((year <= 1601) || (year > 30827)) {
6022 * According to MSDN, the MS time functions can't handle dates outside
6028 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6029 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6030 tz_info.StandardDate.wYear = year;
6031 convert_to_absolute_date(&tz_info.StandardDate);
6032 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6037 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6038 tz_info.DaylightDate.wYear = year;
6039 convert_to_absolute_date(&tz_info.DaylightDate);
6040 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6045 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6047 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6048 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6055 ves_icall_System_Object_obj_address (MonoObject *this)
6057 MONO_ARCH_SAVE_REGS;
6064 static inline gint32
6065 mono_array_get_byte_length (MonoArray *array)
6071 klass = array->obj.vtable->klass;
6073 if (array->bounds == NULL)
6074 length = array->max_length;
6077 for (i = 0; i < klass->rank; ++ i)
6078 length *= array->bounds [i].length;
6081 switch (klass->element_class->byval_arg.type) {
6084 case MONO_TYPE_BOOLEAN:
6088 case MONO_TYPE_CHAR:
6096 return length * sizeof (gpointer);
6107 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6109 MONO_ARCH_SAVE_REGS;
6111 return mono_array_get_byte_length (array);
6115 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6117 MONO_ARCH_SAVE_REGS;
6119 return mono_array_get (array, gint8, idx);
6123 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6125 MONO_ARCH_SAVE_REGS;
6127 mono_array_set (array, gint8, idx, value);
6131 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6133 guint8 *src_buf, *dest_buf;
6135 MONO_ARCH_SAVE_REGS;
6137 /* watch out for integer overflow */
6138 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6141 src_buf = (guint8 *)src->vector + src_offset;
6142 dest_buf = (guint8 *)dest->vector + dest_offset;
6145 memcpy (dest_buf, src_buf, count);
6147 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6153 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6155 MonoDomain *domain = mono_object_domain (this);
6157 MonoRealProxy *rp = ((MonoRealProxy *)this);
6158 MonoTransparentProxy *tp;
6162 MONO_ARCH_SAVE_REGS;
6164 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6165 tp = (MonoTransparentProxy*) res;
6167 MONO_OBJECT_SETREF (tp, rp, rp);
6168 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6169 klass = mono_class_from_mono_type (type);
6171 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6172 tp->remote_class = mono_remote_class (domain, class_name, klass);
6174 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6178 static MonoReflectionType *
6179 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6181 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6184 /* System.Environment */
6187 ves_icall_System_Environment_get_UserName (void)
6189 MONO_ARCH_SAVE_REGS;
6191 /* using glib is more portable */
6192 return mono_string_new (mono_domain_get (), g_get_user_name ());
6197 ves_icall_System_Environment_get_MachineName (void)
6199 #if defined (HOST_WIN32)
6204 len = MAX_COMPUTERNAME_LENGTH + 1;
6205 buf = g_new (gunichar2, len);
6208 if (GetComputerName (buf, (PDWORD) &len))
6209 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6213 #elif !defined(DISABLE_SOCKETS)
6217 if (gethostname (buf, sizeof (buf)) == 0)
6218 result = mono_string_new (mono_domain_get (), buf);
6224 return mono_string_new (mono_domain_get (), "mono");
6229 ves_icall_System_Environment_get_Platform (void)
6231 #if defined (TARGET_WIN32)
6234 #elif defined(__MACH__)
6237 // For compatibility with our client code, this will be 4 for a while.
6238 // We will eventually move to 6 to match .NET, but it requires all client
6239 // code to be updated and the documentation everywhere to be updated
6250 ves_icall_System_Environment_get_NewLine (void)
6252 MONO_ARCH_SAVE_REGS;
6254 #if defined (HOST_WIN32)
6255 return mono_string_new (mono_domain_get (), "\r\n");
6257 return mono_string_new (mono_domain_get (), "\n");
6262 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6267 MONO_ARCH_SAVE_REGS;
6272 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6273 value = g_getenv (utf8_name);
6280 return mono_string_new (mono_domain_get (), value);
6284 * There is no standard way to get at environ.
6287 #ifndef __MINGW32_VERSION
6289 /* Apple defines this in crt_externs.h but doesn't provide that header for
6290 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6291 * in fact exist on all implementations (so far)
6293 gchar ***_NSGetEnviron(void);
6294 #define environ (*_NSGetEnviron())
6303 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6314 env_strings = GetEnvironmentStrings();
6317 env_string = env_strings;
6318 while (*env_string != '\0') {
6319 /* weird case that MS seems to skip */
6320 if (*env_string != '=')
6322 while (*env_string != '\0')
6328 domain = mono_domain_get ();
6329 names = mono_array_new (domain, mono_defaults.string_class, n);
6333 env_string = env_strings;
6334 while (*env_string != '\0') {
6335 /* weird case that MS seems to skip */
6336 if (*env_string != '=') {
6337 equal_str = wcschr(env_string, '=');
6338 g_assert(equal_str);
6339 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6340 mono_array_setref (names, n, str);
6343 while (*env_string != '\0')
6348 FreeEnvironmentStrings (env_strings);
6360 MONO_ARCH_SAVE_REGS;
6363 for (e = environ; *e != 0; ++ e)
6366 domain = mono_domain_get ();
6367 names = mono_array_new (domain, mono_defaults.string_class, n);
6370 for (e = environ; *e != 0; ++ e) {
6371 parts = g_strsplit (*e, "=", 2);
6373 str = mono_string_new (domain, *parts);
6374 mono_array_setref (names, n, str);
6387 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6389 #if !GLIB_CHECK_VERSION(2,4,0)
6390 #define g_setenv(a,b,c) setenv(a,b,c)
6391 #define g_unsetenv(a) unsetenv(a)
6395 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6400 gunichar2 *utf16_name, *utf16_value;
6402 gchar *utf8_name, *utf8_value;
6405 MONO_ARCH_SAVE_REGS;
6408 utf16_name = mono_string_to_utf16 (name);
6409 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6410 SetEnvironmentVariable (utf16_name, NULL);
6411 g_free (utf16_name);
6415 utf16_value = mono_string_to_utf16 (value);
6417 SetEnvironmentVariable (utf16_name, utf16_value);
6419 g_free (utf16_name);
6420 g_free (utf16_value);
6422 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6424 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6425 g_unsetenv (utf8_name);
6430 utf8_value = mono_string_to_utf8_checked (value, &error);
6431 if (!mono_error_ok (&error)) {
6433 mono_error_raise_exception (&error);
6435 g_setenv (utf8_name, utf8_value, TRUE);
6438 g_free (utf8_value);
6443 ves_icall_System_Environment_Exit (int result)
6445 MONO_ARCH_SAVE_REGS;
6447 mono_threads_set_shutting_down ();
6449 mono_runtime_set_shutting_down ();
6451 /* This will kill the tp threads which cannot be suspended */
6452 mono_thread_pool_cleanup ();
6454 /* Suspend all managed threads since the runtime is going away */
6455 mono_thread_suspend_all_other_threads ();
6457 mono_runtime_quit ();
6459 /* we may need to do some cleanup here... */
6464 ves_icall_System_Environment_GetGacPath (void)
6466 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6470 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6472 #if defined (HOST_WIN32)
6473 #ifndef CSIDL_FLAG_CREATE
6474 #define CSIDL_FLAG_CREATE 0x8000
6477 WCHAR path [MAX_PATH];
6478 /* Create directory if no existing */
6479 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6483 return mono_string_new_utf16 (mono_domain_get (), path, len);
6486 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6488 return mono_string_new (mono_domain_get (), "");
6492 ves_icall_System_Environment_GetLogicalDrives (void)
6494 gunichar2 buf [128], *ptr, *dname;
6496 guint initial_size = 127, size = 128;
6499 MonoString *drivestr;
6500 MonoDomain *domain = mono_domain_get ();
6503 MONO_ARCH_SAVE_REGS;
6508 while (size > initial_size) {
6509 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6510 if (size > initial_size) {
6513 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6514 initial_size = size;
6528 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6533 while (*u16) { u16++; len ++; }
6534 drivestr = mono_string_new_utf16 (domain, dname, len);
6535 mono_array_setref (result, ndrives++, drivestr);
6546 ves_icall_System_Environment_InternalGetHome (void)
6548 MONO_ARCH_SAVE_REGS;
6550 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6553 static const char *encodings [] = {
6555 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6556 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6557 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6559 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6560 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6561 "x_unicode_2_0_utf_7",
6563 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6564 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6566 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6569 "unicodefffe", "utf_16be",
6576 * Returns the internal codepage, if the value of "int_code_page" is
6577 * 1 at entry, and we can not compute a suitable code page number,
6578 * returns the code page as a string
6581 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6586 char *codepage = NULL;
6588 int want_name = *int_code_page;
6591 *int_code_page = -1;
6592 MONO_ARCH_SAVE_REGS;
6594 g_get_charset (&cset);
6595 c = codepage = strdup (cset);
6596 for (c = codepage; *c; c++){
6597 if (isascii (*c) && isalpha (*c))
6602 /* g_print ("charset: %s\n", cset); */
6604 /* handle some common aliases */
6607 for (i = 0; p != 0; ){
6608 if ((gssize) p < 7){
6610 p = encodings [++i];
6613 if (strcmp (p, codepage) == 0){
6614 *int_code_page = code;
6617 p = encodings [++i];
6620 if (strstr (codepage, "utf_8") != NULL)
6621 *int_code_page |= 0x10000000;
6624 if (want_name && *int_code_page == -1)
6625 return mono_string_new (mono_domain_get (), cset);
6631 ves_icall_System_Environment_get_HasShutdownStarted (void)
6633 if (mono_runtime_is_shutting_down ())
6636 if (mono_domain_is_unloading (mono_domain_get ()))
6643 ves_icall_System_Environment_BroadcastSettingChange (void)
6646 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6651 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6652 MonoReflectionMethod *method,
6653 MonoArray *out_args)
6655 MONO_ARCH_SAVE_REGS;
6657 mono_message_init (mono_object_domain (this), this, method, out_args);
6661 ves_icall_IsTransparentProxy (MonoObject *proxy)
6663 MONO_ARCH_SAVE_REGS;
6668 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6674 static MonoReflectionMethod *
6675 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6676 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6680 MonoMethod **vtable;
6681 MonoMethod *res = NULL;
6683 MONO_CHECK_ARG_NULL (rtype);
6684 MONO_CHECK_ARG_NULL (rmethod);
6686 method = rmethod->method;
6687 klass = mono_class_from_mono_type (rtype->type);
6688 mono_class_init_or_throw (klass);
6690 if (MONO_CLASS_IS_INTERFACE (klass))
6693 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6696 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6697 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6703 mono_class_setup_vtable (klass);
6704 vtable = klass->vtable;
6706 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6707 gboolean variance_used = FALSE;
6708 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6709 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6711 res = vtable [offs + method->slot];
6713 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6716 if (method->slot != -1)
6717 res = vtable [method->slot];
6723 return mono_method_get_object (mono_domain_get (), res, NULL);
6727 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6732 MONO_ARCH_SAVE_REGS;
6734 klass = mono_class_from_mono_type (type->type);
6735 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6737 if (enable) vtable->remote = 1;
6738 else vtable->remote = 0;
6742 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6747 MONO_ARCH_SAVE_REGS;
6749 domain = mono_object_domain (type);
6750 klass = mono_class_from_mono_type (type->type);
6751 mono_class_init_or_throw (klass);
6753 if (klass->rank >= 1) {
6754 g_assert (klass->rank == 1);
6755 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6757 /* Bypass remoting object creation check */
6758 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6763 ves_icall_System_IO_get_temp_path (void)
6765 MONO_ARCH_SAVE_REGS;
6767 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6770 #ifndef PLATFORM_NO_DRIVEINFO
6772 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6773 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6777 ULARGE_INTEGER wapi_free_bytes_avail;
6778 ULARGE_INTEGER wapi_total_number_of_bytes;
6779 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6781 MONO_ARCH_SAVE_REGS;
6783 *error = ERROR_SUCCESS;
6784 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6785 &wapi_total_number_of_free_bytes);
6788 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6789 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6790 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6792 *free_bytes_avail = 0;
6793 *total_number_of_bytes = 0;
6794 *total_number_of_free_bytes = 0;
6795 *error = GetLastError ();
6802 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6804 MONO_ARCH_SAVE_REGS;
6806 return GetDriveType (mono_string_chars (root_path_name));
6811 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6813 MONO_ARCH_SAVE_REGS;
6815 return mono_compile_method (method);
6819 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6824 MONO_ARCH_SAVE_REGS;
6826 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6828 #if defined (HOST_WIN32)
6829 /* Avoid mixing '/' and '\\' */
6832 for (i = strlen (path) - 1; i >= 0; i--)
6833 if (path [i] == '/')
6837 mcpath = mono_string_new (mono_domain_get (), path);
6844 get_bundled_machine_config (void)
6846 const gchar *machine_config;
6848 MONO_ARCH_SAVE_REGS;
6850 machine_config = mono_get_machine_config ();
6852 if (!machine_config)
6855 return mono_string_new (mono_domain_get (), machine_config);
6859 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6864 MONO_ARCH_SAVE_REGS;
6866 path = g_path_get_dirname (mono_get_config_dir ());
6868 #if defined (HOST_WIN32)
6869 /* Avoid mixing '/' and '\\' */
6872 for (i = strlen (path) - 1; i >= 0; i--)
6873 if (path [i] == '/')
6877 ipath = mono_string_new (mono_domain_get (), path);
6884 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6886 MonoPEResourceDataEntry *entry;
6889 MONO_ARCH_SAVE_REGS;
6891 if (!assembly || !result || !size)
6896 image = assembly->assembly->image;
6897 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6901 *result = mono_image_rva_map (image, entry->rde_data_offset);
6906 *size = entry->rde_size;
6912 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6914 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6918 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6920 #if defined (HOST_WIN32)
6921 OutputDebugString (mono_string_chars (message));
6923 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6927 /* Only used for value types */
6929 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6934 MONO_ARCH_SAVE_REGS;
6936 domain = mono_object_domain (type);
6937 klass = mono_class_from_mono_type (type->type);
6938 mono_class_init_or_throw (klass);
6940 if (mono_class_is_nullable (klass))
6941 /* No arguments -> null */
6944 return mono_object_new (domain, klass);
6947 static MonoReflectionMethod *
6948 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6950 MonoClass *klass, *parent;
6951 MonoMethod *method = m->method;
6952 MonoMethod *result = NULL;
6954 MONO_ARCH_SAVE_REGS;
6956 if (method->klass == NULL)
6959 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6960 MONO_CLASS_IS_INTERFACE (method->klass) ||
6961 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6964 klass = method->klass;
6965 if (klass->generic_class)
6966 klass = klass->generic_class->container_class;
6969 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6970 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6971 mono_class_setup_vtable (parent);
6972 if (parent->vtable_size <= method->slot)
6977 klass = klass->parent;
6982 if (klass == method->klass)
6985 result = klass->vtable [method->slot];
6986 if (result == NULL) {
6987 /* It is an abstract method */
6988 gpointer iter = NULL;
6989 while ((result = mono_class_get_methods (klass, &iter)))
6990 if (result->slot == method->slot)
6997 return mono_method_get_object (mono_domain_get (), result, NULL);
7001 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7003 MonoMethod *method = m->method;
7005 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7010 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7012 MONO_ARCH_SAVE_REGS;
7014 iter->sig = *(MonoMethodSignature**)argsp;
7016 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7017 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7020 /* FIXME: it's not documented what start is exactly... */
7024 iter->args = argsp + sizeof (gpointer);
7026 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7028 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7032 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7034 guint32 i, arg_size;
7037 MONO_ARCH_SAVE_REGS;
7039 i = iter->sig->sentinelpos + iter->next_arg;
7041 g_assert (i < iter->sig->param_count);
7043 res.type = iter->sig->params [i];
7044 res.klass = mono_class_from_mono_type (res.type);
7045 res.value = iter->args;
7046 arg_size = mono_type_stack_size (res.type, &align);
7047 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7048 if (arg_size <= sizeof (gpointer)) {
7050 int padding = arg_size - mono_type_size (res.type, &dummy);
7051 res.value = (guint8*)res.value + padding;
7054 iter->args = (char*)iter->args + arg_size;
7057 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7063 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7065 guint32 i, arg_size;
7068 MONO_ARCH_SAVE_REGS;
7070 i = iter->sig->sentinelpos + iter->next_arg;
7072 g_assert (i < iter->sig->param_count);
7074 while (i < iter->sig->param_count) {
7075 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7077 res.type = iter->sig->params [i];
7078 res.klass = mono_class_from_mono_type (res.type);
7079 /* FIXME: endianess issue... */
7080 res.value = iter->args;
7081 arg_size = mono_type_stack_size (res.type, &align);
7082 iter->args = (char*)iter->args + arg_size;
7084 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7087 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7096 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7099 MONO_ARCH_SAVE_REGS;
7101 i = iter->sig->sentinelpos + iter->next_arg;
7103 g_assert (i < iter->sig->param_count);
7105 return iter->sig->params [i];
7109 mono_TypedReference_ToObject (MonoTypedRef tref)
7111 MONO_ARCH_SAVE_REGS;
7113 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7114 MonoObject** objp = tref.value;
7118 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7122 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7124 MONO_ARCH_SAVE_REGS;
7126 if (MONO_TYPE_IS_REFERENCE (type)) {
7127 MonoObject** objp = value;
7131 return mono_value_box (mono_domain_get (), klass, value);
7135 prelink_method (MonoMethod *method)
7137 const char *exc_class, *exc_arg;
7138 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7140 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7142 mono_raise_exception(
7143 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7145 /* create the wrapper, too? */
7149 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7151 MONO_ARCH_SAVE_REGS;
7152 prelink_method (method->method);
7156 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7158 MonoClass *klass = mono_class_from_mono_type (type->type);
7160 gpointer iter = NULL;
7161 MONO_ARCH_SAVE_REGS;
7163 mono_class_init_or_throw (klass);
7165 while ((m = mono_class_get_methods (klass, &iter)))
7169 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7171 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7172 gint32 const **exponents,
7173 gunichar2 const **digitLowerTable,
7174 gunichar2 const **digitUpperTable,
7175 gint64 const **tenPowersList,
7176 gint32 const **decHexDigits)
7178 *mantissas = Formatter_MantissaBitsTable;
7179 *exponents = Formatter_TensExponentTable;
7180 *digitLowerTable = Formatter_DigitLowerTable;
7181 *digitUpperTable = Formatter_DigitUpperTable;
7182 *tenPowersList = Formatter_TenPowersList;
7183 *decHexDigits = Formatter_DecHexDigits;
7186 /* These parameters are "readonly" in corlib/System/Char.cs */
7188 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7189 guint8 const **numeric_data,
7190 gdouble const **numeric_data_values,
7191 guint16 const **to_lower_data_low,
7192 guint16 const **to_lower_data_high,
7193 guint16 const **to_upper_data_low,
7194 guint16 const **to_upper_data_high)
7196 *category_data = CategoryData;
7197 *numeric_data = NumericData;
7198 *numeric_data_values = NumericDataValues;
7199 *to_lower_data_low = ToLowerDataLow;
7200 *to_lower_data_high = ToLowerDataHigh;
7201 *to_upper_data_low = ToUpperDataLow;
7202 *to_upper_data_high = ToUpperDataHigh;
7206 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7208 return method->method->token;
7212 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7213 * and avoid useless allocations.
7216 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7220 for (i = 0; i < type->num_mods; ++i) {
7221 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7226 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7228 for (i = 0; i < type->num_mods; ++i) {
7229 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7230 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7231 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7239 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7241 MonoType *type = param->ClassImpl->type;
7242 MonoClass *member_class = mono_object_class (param->MemberImpl);
7243 MonoMethod *method = NULL;
7246 MonoMethodSignature *sig;
7248 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7249 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7250 method = rmethod->method;
7251 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7252 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7253 if (!(method = prop->property->get))
7254 method = prop->property->set;
7257 char *type_name = mono_type_get_full_name (member_class);
7258 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7259 MonoException *ex = mono_get_exception_not_supported (msg);
7262 mono_raise_exception (ex);
7265 image = method->klass->image;
7266 pos = param->PositionImpl;
7267 sig = mono_method_signature (method);
7271 type = sig->params [pos];
7273 return type_array_from_modifiers (image, type, optional);
7277 get_property_type (MonoProperty *prop)
7279 MonoMethodSignature *sig;
7281 sig = mono_method_signature (prop->get);
7283 } else if (prop->set) {
7284 sig = mono_method_signature (prop->set);
7285 return sig->params [sig->param_count - 1];
7291 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7293 MonoType *type = get_property_type (property->property);
7294 MonoImage *image = property->klass->image;
7298 return type_array_from_modifiers (image, type, optional);
7302 *Construct a MonoType suited to be used to decode a constant blob object.
7304 * @type is the target type which will be constructed
7305 * @blob_type is the blob type, for example, that comes from the constant table
7306 * @real_type is the expected constructed type.
7309 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7311 type->type = blob_type;
7312 type->data.klass = NULL;
7313 if (blob_type == MONO_TYPE_CLASS)
7314 type->data.klass = mono_defaults.object_class;
7315 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7316 /* For enums, we need to use the base type */
7317 type->type = MONO_TYPE_VALUETYPE;
7318 type->data.klass = mono_class_from_mono_type (real_type);
7320 type->data.klass = mono_class_from_mono_type (real_type);
7324 property_info_get_default_value (MonoReflectionProperty *property)
7327 MonoProperty *prop = property->property;
7328 MonoType *type = get_property_type (prop);
7329 MonoDomain *domain = mono_object_domain (property);
7330 MonoTypeEnum def_type;
7331 const char *def_value;
7334 g_assert (!prop->parent->image->dynamic);
7336 mono_class_init (prop->parent);
7338 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7339 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7341 def_value = mono_class_get_property_default_value (prop, &def_type);
7343 mono_type_from_blob_type (&blob_type, def_type, type);
7344 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7350 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7352 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7353 MonoCustomAttrInfo *cinfo;
7356 mono_class_init_or_throw (attr_class);
7358 cinfo = mono_reflection_get_custom_attrs_info (obj);
7361 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7363 mono_custom_attrs_free (cinfo);
7368 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7370 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7374 mono_class_init_or_throw (attr_class);
7376 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7378 if (mono_loader_get_last_error ()) {
7379 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7380 g_assert_not_reached ();
7389 ves_icall_Mono_Runtime_GetDisplayName (void)
7392 MonoString *display_name;
7394 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7395 display_name = mono_string_new (mono_domain_get (), info);
7397 return display_name;
7401 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7403 MonoString *message;
7407 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7408 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7411 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7413 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7421 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7422 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7423 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7424 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7425 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7426 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7427 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7428 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7432 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7437 gunichar2 last, prev_last, prev2_last;
7445 last = prev_last = 0, prev2_last = 0;
7446 for (i = 0; i < ilength; i++) {
7448 if (c >= sizeof (dbase64)) {
7449 exc = mono_exception_from_name_msg (mono_get_corlib (),
7450 "System", "FormatException",
7451 "Invalid character found.");
7452 mono_raise_exception (exc);
7453 } else if (isspace (c)) {
7456 prev2_last = prev_last;
7462 olength = ilength - ignored;
7464 if (allowWhitespaceOnly && olength == 0) {
7465 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7468 if ((olength & 3) != 0 || olength <= 0) {
7469 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7470 "FormatException", "Invalid length.");
7471 mono_raise_exception (exc);
7474 if (prev2_last == '=') {
7475 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7476 mono_raise_exception (exc);
7479 olength = (olength * 3) / 4;
7483 if (prev_last == '=')
7486 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7487 res_ptr = mono_array_addr (result, guchar, 0);
7488 for (i = 0; i < ilength; ) {
7491 for (k = 0; k < 4 && i < ilength;) {
7497 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7498 exc = mono_exception_from_name_msg (mono_get_corlib (),
7499 "System", "FormatException",
7500 "Invalid character found.");
7501 mono_raise_exception (exc);
7506 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7508 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7510 *res_ptr++ = (b [2] << 6) | b [3];
7512 while (i < ilength && isspace (start [i]))
7520 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7522 MONO_ARCH_SAVE_REGS;
7524 return base64_to_byte_array (mono_string_chars (str),
7525 mono_string_length (str), allowWhitespaceOnly);
7529 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7531 MONO_ARCH_SAVE_REGS;
7533 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7537 #define ICALL_TYPE(id,name,first)
7538 #define ICALL(id,name,func) Icall_ ## id,
7541 #include "metadata/icall-def.h"
7547 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7548 #define ICALL(id,name,func)
7550 #include "metadata/icall-def.h"
7556 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7557 #define ICALL(id,name,func)
7559 guint16 first_icall;
7562 static const IcallTypeDesc
7563 icall_type_descs [] = {
7564 #include "metadata/icall-def.h"
7568 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7571 #define ICALL_TYPE(id,name,first)
7574 #ifdef HAVE_ARRAY_ELEM_INIT
7575 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7576 #define MSGSTRFIELD1(line) str##line
7578 static const struct msgstrtn_t {
7579 #define ICALL(id,name,func)
7581 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7582 #include "metadata/icall-def.h"
7584 } icall_type_names_str = {
7585 #define ICALL_TYPE(id,name,first) (name),
7586 #include "metadata/icall-def.h"
7589 static const guint16 icall_type_names_idx [] = {
7590 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7591 #include "metadata/icall-def.h"
7594 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7596 static const struct msgstr_t {
7598 #define ICALL_TYPE(id,name,first)
7599 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7600 #include "metadata/icall-def.h"
7602 } icall_names_str = {
7603 #define ICALL(id,name,func) (name),
7604 #include "metadata/icall-def.h"
7607 static const guint16 icall_names_idx [] = {
7608 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7609 #include "metadata/icall-def.h"
7612 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7618 #define ICALL_TYPE(id,name,first) name,
7619 #define ICALL(id,name,func)
7620 static const char* const
7621 icall_type_names [] = {
7622 #include "metadata/icall-def.h"
7626 #define icall_type_name_get(id) (icall_type_names [(id)])
7630 #define ICALL_TYPE(id,name,first)
7631 #define ICALL(id,name,func) name,
7632 static const char* const
7634 #include "metadata/icall-def.h"
7637 #define icall_name_get(id) icall_names [(id)]
7639 #endif /* !HAVE_ARRAY_ELEM_INIT */
7643 #define ICALL_TYPE(id,name,first)
7644 #define ICALL(id,name,func) func,
7645 static const gconstpointer
7646 icall_functions [] = {
7647 #include "metadata/icall-def.h"
7651 static GHashTable *icall_hash = NULL;
7652 static GHashTable *jit_icall_hash_name = NULL;
7653 static GHashTable *jit_icall_hash_addr = NULL;
7656 mono_icall_init (void)
7660 /* check that tables are sorted: disable in release */
7663 const char *prev_class = NULL;
7664 const char *prev_method;
7666 for (i = 0; i < Icall_type_num; ++i) {
7667 const IcallTypeDesc *desc;
7670 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7671 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7672 prev_class = icall_type_name_get (i);
7673 desc = &icall_type_descs [i];
7674 num_icalls = icall_desc_num_icalls (desc);
7675 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7676 for (j = 0; j < num_icalls; ++j) {
7677 const char *methodn = icall_name_get (desc->first_icall + j);
7678 if (prev_method && strcmp (prev_method, methodn) >= 0)
7679 g_print ("method %s should come before method %s\n", methodn, prev_method);
7680 prev_method = methodn;
7685 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7689 mono_icall_cleanup (void)
7691 g_hash_table_destroy (icall_hash);
7692 g_hash_table_destroy (jit_icall_hash_name);
7693 g_hash_table_destroy (jit_icall_hash_addr);
7697 mono_add_internal_call (const char *name, gconstpointer method)
7699 mono_loader_lock ();
7701 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7703 mono_loader_unlock ();
7706 #ifdef HAVE_ARRAY_ELEM_INIT
7708 compare_method_imap (const void *key, const void *elem)
7710 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7711 return strcmp (key, method_name);
7715 find_method_icall (const IcallTypeDesc *imap, const char *name)
7717 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7720 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7724 compare_class_imap (const void *key, const void *elem)
7726 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7727 return strcmp (key, class_name);
7730 static const IcallTypeDesc*
7731 find_class_icalls (const char *name)
7733 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7736 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7741 compare_method_imap (const void *key, const void *elem)
7743 const char** method_name = (const char**)elem;
7744 return strcmp (key, *method_name);
7748 find_method_icall (const IcallTypeDesc *imap, const char *name)
7750 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7753 return (gpointer)icall_functions [(nameslot - icall_names)];
7757 compare_class_imap (const void *key, const void *elem)
7759 const char** class_name = (const char**)elem;
7760 return strcmp (key, *class_name);
7763 static const IcallTypeDesc*
7764 find_class_icalls (const char *name)
7766 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7769 return &icall_type_descs [nameslot - icall_type_names];
7775 * we should probably export this as an helper (handle nested types).
7776 * Returns the number of chars written in buf.
7779 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7781 int nspacelen, cnamelen;
7782 nspacelen = strlen (klass->name_space);
7783 cnamelen = strlen (klass->name);
7784 if (nspacelen + cnamelen + 2 > bufsize)
7787 memcpy (buf, klass->name_space, nspacelen);
7788 buf [nspacelen ++] = '.';
7790 memcpy (buf + nspacelen, klass->name, cnamelen);
7791 buf [nspacelen + cnamelen] = 0;
7792 return nspacelen + cnamelen;
7796 mono_lookup_internal_call (MonoMethod *method)
7801 int typelen = 0, mlen, siglen;
7803 const IcallTypeDesc *imap;
7805 g_assert (method != NULL);
7807 if (method->is_inflated)
7808 method = ((MonoMethodInflated *) method)->declaring;
7810 if (method->klass->nested_in) {
7811 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7815 mname [pos++] = '/';
7818 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7824 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7829 imap = find_class_icalls (mname);
7831 mname [typelen] = ':';
7832 mname [typelen + 1] = ':';
7834 mlen = strlen (method->name);
7835 memcpy (mname + typelen + 2, method->name, mlen);
7836 sigstart = mname + typelen + 2 + mlen;
7839 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7840 siglen = strlen (tmpsig);
7841 if (typelen + mlen + siglen + 6 > sizeof (mname))
7844 memcpy (sigstart + 1, tmpsig, siglen);
7845 sigstart [siglen + 1] = ')';
7846 sigstart [siglen + 2] = 0;
7849 mono_loader_lock ();
7851 res = g_hash_table_lookup (icall_hash, mname);
7853 mono_loader_unlock ();
7856 /* try without signature */
7858 res = g_hash_table_lookup (icall_hash, mname);
7860 mono_loader_unlock ();
7864 /* it wasn't found in the static call tables */
7866 mono_loader_unlock ();
7869 res = find_method_icall (imap, sigstart - mlen);
7871 mono_loader_unlock ();
7874 /* try _with_ signature */
7876 res = find_method_icall (imap, sigstart - mlen);
7878 mono_loader_unlock ();
7882 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7883 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7884 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7885 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7886 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");
7887 g_print ("If you see other errors or faults after this message they are probably related\n");
7888 g_print ("and you need to fix your mono install first.\n");
7890 mono_loader_unlock ();
7896 type_from_typename (char *typename)
7898 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7900 if (!strcmp (typename, "int"))
7901 klass = mono_defaults.int_class;
7902 else if (!strcmp (typename, "ptr"))
7903 klass = mono_defaults.int_class;
7904 else if (!strcmp (typename, "void"))
7905 klass = mono_defaults.void_class;
7906 else if (!strcmp (typename, "int32"))
7907 klass = mono_defaults.int32_class;
7908 else if (!strcmp (typename, "uint32"))
7909 klass = mono_defaults.uint32_class;
7910 else if (!strcmp (typename, "int8"))
7911 klass = mono_defaults.sbyte_class;
7912 else if (!strcmp (typename, "uint8"))
7913 klass = mono_defaults.byte_class;
7914 else if (!strcmp (typename, "int16"))
7915 klass = mono_defaults.int16_class;
7916 else if (!strcmp (typename, "uint16"))
7917 klass = mono_defaults.uint16_class;
7918 else if (!strcmp (typename, "long"))
7919 klass = mono_defaults.int64_class;
7920 else if (!strcmp (typename, "ulong"))
7921 klass = mono_defaults.uint64_class;
7922 else if (!strcmp (typename, "float"))
7923 klass = mono_defaults.single_class;
7924 else if (!strcmp (typename, "double"))
7925 klass = mono_defaults.double_class;
7926 else if (!strcmp (typename, "object"))
7927 klass = mono_defaults.object_class;
7928 else if (!strcmp (typename, "obj"))
7929 klass = mono_defaults.object_class;
7930 else if (!strcmp (typename, "string"))
7931 klass = mono_defaults.string_class;
7932 else if (!strcmp (typename, "bool"))
7933 klass = mono_defaults.boolean_class;
7934 else if (!strcmp (typename, "boolean"))
7935 klass = mono_defaults.boolean_class;
7937 g_error ("%s", typename);
7938 g_assert_not_reached ();
7940 return &klass->byval_arg;
7943 MonoMethodSignature*
7944 mono_create_icall_signature (const char *sigstr)
7949 MonoMethodSignature *res;
7951 mono_loader_lock ();
7952 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7954 mono_loader_unlock ();
7958 parts = g_strsplit (sigstr, " ", 256);
7967 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7972 * Under windows, the default pinvoke calling convention is STDCALL but
7975 res->call_convention = MONO_CALL_C;
7978 res->ret = type_from_typename (parts [0]);
7979 for (i = 1; i < len; ++i) {
7980 res->params [i - 1] = type_from_typename (parts [i]);
7985 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7987 mono_loader_unlock ();
7993 mono_find_jit_icall_by_name (const char *name)
7995 MonoJitICallInfo *info;
7996 g_assert (jit_icall_hash_name);
7998 mono_loader_lock ();
7999 info = g_hash_table_lookup (jit_icall_hash_name, name);
8000 mono_loader_unlock ();
8005 mono_find_jit_icall_by_addr (gconstpointer addr)
8007 MonoJitICallInfo *info;
8008 g_assert (jit_icall_hash_addr);
8010 mono_loader_lock ();
8011 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8012 mono_loader_unlock ();
8018 * mono_get_jit_icall_info:
8020 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8021 * caller should access it while holding the loader lock.
8024 mono_get_jit_icall_info (void)
8026 return jit_icall_hash_name;
8030 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8032 mono_loader_lock ();
8033 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8034 mono_loader_unlock ();
8038 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8040 MonoJitICallInfo *info;
8045 mono_loader_lock ();
8047 if (!jit_icall_hash_name) {
8048 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8049 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8052 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8053 g_warning ("jit icall already defined \"%s\"\n", name);
8054 g_assert_not_reached ();
8057 info = g_new0 (MonoJitICallInfo, 1);
8064 info->wrapper = func;
8066 info->wrapper = NULL;
8069 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8070 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8072 mono_loader_unlock ();