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 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2062 mono_class_setup_interfaces (klass, error);
2063 if (!mono_error_ok (error))
2066 for (i = 0; i < klass->interface_count; i++) {
2067 ic = klass->interfaces [i];
2068 g_hash_table_insert (ifaces, ic, ic);
2070 collect_interfaces (ic, ifaces, error);
2071 if (!mono_error_ok (error))
2077 MonoArray *iface_array;
2078 MonoGenericContext *context;
2082 } FillIfaceArrayData;
2085 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2087 FillIfaceArrayData *data = user_data;
2088 MonoClass *ic = key;
2089 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2091 if (!mono_error_ok (data->error))
2094 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2095 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2096 if (!mono_error_ok (data->error))
2100 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2103 mono_metadata_free_type (inflated);
2107 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2110 MonoClass *class = mono_class_from_mono_type (type->type);
2112 FillIfaceArrayData data = { 0 };
2115 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2117 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2118 data.context = mono_class_get_context (class);
2119 class = class->generic_class->container_class;
2122 for (parent = class; parent; parent = parent->parent) {
2123 mono_class_setup_interfaces (parent, &error);
2124 if (!mono_error_ok (&error))
2126 collect_interfaces (parent, iface_hash, &error);
2127 if (!mono_error_ok (&error))
2131 data.error = &error;
2132 data.domain = mono_object_domain (type);
2134 len = g_hash_table_size (iface_hash);
2136 return mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2138 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2139 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2140 if (!mono_error_ok (&error))
2143 g_hash_table_destroy (iface_hash);
2144 return data.iface_array;
2147 g_hash_table_destroy (iface_hash);
2148 mono_error_raise_exception (&error);
2153 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2155 gboolean variance_used;
2156 MonoClass *class = mono_class_from_mono_type (type->type);
2157 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2158 MonoReflectionMethod *member;
2161 int i = 0, len, ioffset;
2164 MONO_ARCH_SAVE_REGS;
2165 mono_class_init_or_throw (class);
2166 mono_class_init_or_throw (iclass);
2168 mono_class_setup_vtable (class);
2170 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2174 len = mono_class_num_methods (iclass);
2175 domain = mono_object_domain (type);
2176 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2177 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2179 while ((method = mono_class_get_methods (iclass, &iter))) {
2180 member = mono_method_get_object (domain, method, iclass);
2181 mono_array_setref (*methods, i, member);
2182 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2183 mono_array_setref (*targets, i, member);
2190 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2192 MonoClass *klass = mono_class_from_mono_type (type->type);
2193 mono_class_init_or_throw (klass);
2195 if (klass->image->dynamic) {
2196 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2197 *packing = tb->packing_size;
2198 *size = tb->class_size;
2200 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2204 static MonoReflectionType*
2205 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2209 MONO_ARCH_SAVE_REGS;
2211 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2212 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2214 class = mono_class_from_mono_type (type->type);
2215 mono_class_init_or_throw (class);
2217 // GetElementType should only return a type for:
2218 // Array Pointer PassedByRef
2219 if (type->type->byref)
2220 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2221 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2222 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2223 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2224 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2229 static MonoReflectionType*
2230 ves_icall_get_type_parent (MonoReflectionType *type)
2232 MonoClass *class = mono_class_from_mono_type (type->type);
2233 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2237 ves_icall_type_ispointer (MonoReflectionType *type)
2239 MONO_ARCH_SAVE_REGS;
2241 return type->type->type == MONO_TYPE_PTR;
2245 ves_icall_type_isprimitive (MonoReflectionType *type)
2247 MONO_ARCH_SAVE_REGS;
2249 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)));
2253 ves_icall_type_isbyref (MonoReflectionType *type)
2255 MONO_ARCH_SAVE_REGS;
2257 return type->type->byref;
2261 ves_icall_type_iscomobject (MonoReflectionType *type)
2263 MonoClass *klass = mono_class_from_mono_type (type->type);
2264 mono_class_init_or_throw (klass);
2266 return (klass && klass->is_com_object);
2269 static MonoReflectionModule*
2270 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2272 MonoClass *class = mono_class_from_mono_type (type->type);
2273 mono_class_init_or_throw (class);
2275 return mono_module_get_object (mono_object_domain (type), class->image);
2278 static MonoReflectionAssembly*
2279 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2281 MonoDomain *domain = mono_domain_get ();
2282 MonoClass *class = mono_class_from_mono_type (type->type);
2284 mono_class_init_or_throw (class);
2286 return mono_assembly_get_object (domain, class->image->assembly);
2289 static MonoReflectionType*
2290 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2292 MonoDomain *domain = mono_domain_get ();
2295 MONO_ARCH_SAVE_REGS;
2297 if (type->type->byref)
2299 if (type->type->type == MONO_TYPE_VAR)
2300 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2301 else if (type->type->type == MONO_TYPE_MVAR)
2302 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2304 class = mono_class_from_mono_type (type->type)->nested_in;
2306 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2310 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2312 MonoDomain *domain = mono_domain_get ();
2313 MonoClass *class = mono_class_from_mono_type (type->type);
2315 if (type->type->byref) {
2316 char *n = g_strdup_printf ("%s&", class->name);
2317 MonoString *res = mono_string_new (domain, n);
2323 return mono_string_new (domain, class->name);
2328 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2330 MonoDomain *domain = mono_domain_get ();
2331 MonoClass *class = mono_class_from_mono_type (type->type);
2333 while (class->nested_in)
2334 class = class->nested_in;
2336 if (class->name_space [0] == '\0')
2339 return mono_string_new (domain, class->name_space);
2343 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2347 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2348 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2350 class = mono_class_from_mono_type (type->type);
2351 mono_class_init_or_throw (class);
2357 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2360 MonoClass *klass, *pklass;
2361 MonoDomain *domain = mono_object_domain (type);
2362 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2364 MONO_ARCH_SAVE_REGS;
2366 klass = mono_class_from_mono_type (type->type);
2367 mono_class_init_or_throw (klass);
2369 if (klass->generic_container) {
2370 MonoGenericContainer *container = klass->generic_container;
2371 res = mono_array_new_specific (array_vtable, container->type_argc);
2372 for (i = 0; i < container->type_argc; ++i) {
2373 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2374 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2376 } else if (klass->generic_class) {
2377 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2378 res = mono_array_new_specific (array_vtable, inst->type_argc);
2379 for (i = 0; i < inst->type_argc; ++i)
2380 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2382 res = mono_array_new_specific (array_vtable, 0);
2388 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2391 MONO_ARCH_SAVE_REGS;
2393 if (!IS_MONOTYPE (type))
2396 if (type->type->byref)
2399 klass = mono_class_from_mono_type (type->type);
2400 return klass->generic_container != NULL;
2403 static MonoReflectionType*
2404 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2407 MONO_ARCH_SAVE_REGS;
2409 if (type->type->byref)
2412 klass = mono_class_from_mono_type (type->type);
2413 mono_class_init_or_throw (klass);
2415 if (klass->generic_container) {
2416 return type; /* check this one */
2418 if (klass->generic_class) {
2419 MonoClass *generic_class = klass->generic_class->container_class;
2422 tb = mono_class_get_ref_info (generic_class);
2424 if (generic_class->wastypebuilder && tb)
2427 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2432 static MonoReflectionType*
2433 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2435 MonoType *geninst, **types;
2438 g_assert (IS_MONOTYPE (type));
2439 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2441 count = mono_array_length (type_array);
2442 types = g_new0 (MonoType *, count);
2444 for (i = 0; i < count; i++) {
2445 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2446 types [i] = t->type;
2449 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2454 return mono_type_get_object (mono_object_domain (type), geninst);
2458 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2461 MONO_ARCH_SAVE_REGS;
2463 if (type->type->byref)
2466 klass = mono_class_from_mono_type (type->type);
2468 return klass->generic_class != NULL;
2472 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2475 MONO_ARCH_SAVE_REGS;
2477 if (!IS_MONOTYPE (type))
2480 if (type->type->byref)
2483 klass = mono_class_from_mono_type (type->type);
2484 return klass->generic_class != NULL || klass->generic_container != NULL;
2488 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2490 MONO_ARCH_SAVE_REGS;
2492 if (!IS_MONOTYPE (type))
2495 if (is_generic_parameter (type->type))
2496 return mono_type_get_generic_param_num (type->type);
2500 static GenericParameterAttributes
2501 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2503 MONO_ARCH_SAVE_REGS;
2505 g_assert (IS_MONOTYPE (type));
2506 g_assert (is_generic_parameter (type->type));
2507 return mono_generic_param_info (type->type->data.generic_param)->flags;
2511 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2513 MonoGenericParamInfo *param_info;
2519 MONO_ARCH_SAVE_REGS;
2521 g_assert (IS_MONOTYPE (type));
2523 domain = mono_object_domain (type);
2524 param_info = mono_generic_param_info (type->type->data.generic_param);
2525 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2528 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2529 for (i = 0; i < count; i++)
2530 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2537 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2539 MONO_ARCH_SAVE_REGS;
2540 return is_generic_parameter (type->type);
2544 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2546 MONO_ARCH_SAVE_REGS;
2547 return is_generic_parameter (tb->type.type);
2551 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2552 MonoReflectionType *t)
2554 enumtype->type = t->type;
2557 static MonoReflectionMethod*
2558 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2559 MonoReflectionMethod* generic)
2566 MONO_ARCH_SAVE_REGS;
2568 domain = ((MonoObject *)type)->vtable->domain;
2570 klass = mono_class_from_mono_type (type->type);
2571 mono_class_init_or_throw (klass);
2574 while ((method = mono_class_get_methods (klass, &iter))) {
2575 if (method->token == generic->method->token)
2576 return mono_method_get_object (domain, method, klass);
2584 static MonoReflectionMethod *
2585 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2588 MonoType *type = ref_type->type;
2590 MONO_ARCH_SAVE_REGS;
2592 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2593 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2594 if (type->type == MONO_TYPE_VAR)
2597 method = mono_type_get_generic_param_owner (type)->owner.method;
2599 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2602 static MonoReflectionDllImportAttribute*
2603 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2605 static MonoClass *DllImportAttributeClass = NULL;
2606 MonoDomain *domain = mono_domain_get ();
2607 MonoReflectionDllImportAttribute *attr;
2608 MonoImage *image = method->klass->image;
2609 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2610 MonoTableInfo *tables = image->tables;
2611 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2612 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2613 guint32 im_cols [MONO_IMPLMAP_SIZE];
2614 guint32 scope_token;
2615 const char *import = NULL;
2616 const char *scope = NULL;
2619 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2622 if (!DllImportAttributeClass) {
2623 DllImportAttributeClass =
2624 mono_class_from_name (mono_defaults.corlib,
2625 "System.Runtime.InteropServices", "DllImportAttribute");
2626 g_assert (DllImportAttributeClass);
2629 if (method->klass->image->dynamic) {
2630 MonoReflectionMethodAux *method_aux =
2631 g_hash_table_lookup (
2632 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2634 import = method_aux->dllentry;
2635 scope = method_aux->dll;
2638 if (!import || !scope) {
2639 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2644 if (piinfo->implmap_idx) {
2645 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2647 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2648 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2649 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2650 scope = mono_metadata_string_heap (image, scope_token);
2653 flags = piinfo->piflags;
2655 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2657 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2658 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2659 attr->call_conv = (flags & 0x700) >> 8;
2660 attr->charset = ((flags & 0x6) >> 1) + 1;
2661 if (attr->charset == 1)
2663 attr->exact_spelling = (flags & 0x1) != 0;
2664 attr->set_last_error = (flags & 0x40) != 0;
2665 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2666 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2667 attr->preserve_sig = FALSE;
2672 static MonoReflectionMethod *
2673 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2675 MonoMethodInflated *imethod;
2678 MONO_ARCH_SAVE_REGS;
2680 if (method->method->is_generic)
2683 if (!method->method->is_inflated)
2686 imethod = (MonoMethodInflated *) method->method;
2688 result = imethod->declaring;
2689 /* Not a generic method. */
2690 if (!result->is_generic)
2693 if (method->method->klass->image->dynamic) {
2694 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2695 MonoReflectionMethod *res;
2698 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2699 * the dynamic case as well ?
2701 mono_loader_lock ();
2702 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2703 mono_loader_unlock ();
2709 if (imethod->context.class_inst) {
2710 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2711 /*Generic methods gets the context of the GTD.*/
2712 if (mono_class_get_context (klass))
2713 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2716 return mono_method_get_object (mono_object_domain (method), result, NULL);
2720 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2722 MONO_ARCH_SAVE_REGS;
2724 return mono_method_signature (method->method)->generic_param_count != 0;
2728 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2730 MONO_ARCH_SAVE_REGS;
2732 return method->method->is_generic;
2736 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2741 MONO_ARCH_SAVE_REGS;
2743 domain = mono_object_domain (method);
2745 if (method->method->is_inflated) {
2746 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2749 count = inst->type_argc;
2750 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2752 for (i = 0; i < count; i++)
2753 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2759 count = mono_method_signature (method->method)->generic_param_count;
2760 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2762 for (i = 0; i < count; i++) {
2763 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2764 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2765 MonoClass *pklass = mono_class_from_generic_parameter (
2766 param, method->method->klass->image, TRUE);
2767 mono_array_setref (res, i,
2768 mono_type_get_object (domain, &pklass->byval_arg));
2775 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2778 * Invoke from reflection is supposed to always be a virtual call (the API
2779 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2780 * greater flexibility.
2782 MonoMethod *m = method->method;
2786 MONO_ARCH_SAVE_REGS;
2790 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2791 mono_security_core_clr_ensure_reflection_access_method (m);
2793 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2794 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2795 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2800 if (!mono_object_isinst (this, m->klass)) {
2801 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2804 m = mono_object_get_virtual_method (this, m);
2805 /* must pass the pointer to the value for valuetype methods */
2806 if (m->klass->valuetype)
2807 obj = mono_object_unbox (this);
2808 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2809 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2814 pcount = params? mono_array_length (params): 0;
2815 if (pcount != mono_method_signature (m)->param_count) {
2816 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2820 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2821 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."));
2825 if (m->klass->image->assembly->ref_only) {
2826 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."));
2830 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2833 intptr_t *lower_bounds;
2834 pcount = mono_array_length (params);
2835 lengths = alloca (sizeof (uintptr_t) * pcount);
2836 /* Note: the synthetized array .ctors have int32 as argument type */
2837 for (i = 0; i < pcount; ++i)
2838 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2840 if (m->klass->rank == pcount) {
2841 /* Only lengths provided. */
2842 lower_bounds = NULL;
2844 g_assert (pcount == (m->klass->rank * 2));
2845 /* lower bounds are first. */
2846 lower_bounds = (intptr_t*)lengths;
2847 lengths += m->klass->rank;
2850 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2852 return mono_runtime_invoke_array (m, obj, params, NULL);
2856 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2858 MonoDomain *domain = mono_object_domain (method);
2859 MonoMethod *m = method->method;
2860 MonoMethodSignature *sig = mono_method_signature (m);
2861 MonoArray *out_args;
2863 int i, j, outarg_count = 0;
2865 MONO_ARCH_SAVE_REGS;
2867 if (m->klass == mono_defaults.object_class) {
2869 if (!strcmp (m->name, "FieldGetter")) {
2870 MonoClass *k = this->vtable->klass;
2874 /* If this is a proxy, then it must be a CBO */
2875 if (k == mono_defaults.transparent_proxy_class) {
2876 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2877 this = tp->rp->unwrapped_server;
2879 k = this->vtable->klass;
2882 name = mono_array_get (params, MonoString *, 1);
2883 str = mono_string_to_utf8 (name);
2886 MonoClassField* field = mono_class_get_field_from_name (k, str);
2888 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2889 if (field_klass->valuetype)
2890 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2892 result = *((gpointer *)((char *)this + field->offset));
2894 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2895 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2896 mono_array_setref (out_args, 0, result);
2904 g_assert_not_reached ();
2906 } else if (!strcmp (m->name, "FieldSetter")) {
2907 MonoClass *k = this->vtable->klass;
2913 /* If this is a proxy, then it must be a CBO */
2914 if (k == mono_defaults.transparent_proxy_class) {
2915 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2916 this = tp->rp->unwrapped_server;
2918 k = this->vtable->klass;
2921 name = mono_array_get (params, MonoString *, 1);
2922 str = mono_string_to_utf8 (name);
2925 MonoClassField* field = mono_class_get_field_from_name (k, str);
2927 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2928 MonoObject *val = mono_array_get (params, gpointer, 2);
2930 if (field_klass->valuetype) {
2931 size = mono_type_size (field->type, &align);
2932 g_assert (size == mono_class_value_size (field_klass, NULL));
2933 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2935 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2938 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2939 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2949 g_assert_not_reached ();
2954 for (i = 0; i < mono_array_length (params); i++) {
2955 if (sig->params [i]->byref)
2959 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2961 /* handle constructors only for objects already allocated */
2962 if (!strcmp (method->method->name, ".ctor"))
2965 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2966 g_assert (!method->method->klass->valuetype);
2967 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2969 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2970 if (sig->params [i]->byref) {
2972 arg = mono_array_get (params, gpointer, i);
2973 mono_array_setref (out_args, j, arg);
2978 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2984 read_enum_value (char *mem, int type)
2988 return *(guint8*)mem;
2990 return *(gint8*)mem;
2992 return *(guint16*)mem;
2994 return *(gint16*)mem;
2996 return *(guint32*)mem;
2998 return *(gint32*)mem;
3000 return *(guint64*)mem;
3002 return *(gint64*)mem;
3004 g_assert_not_reached ();
3010 write_enum_value (char *mem, int type, guint64 value)
3014 case MONO_TYPE_I1: {
3015 guint8 *p = (guint8*)mem;
3020 case MONO_TYPE_I2: {
3021 guint16 *p = (void*)mem;
3026 case MONO_TYPE_I4: {
3027 guint32 *p = (void*)mem;
3032 case MONO_TYPE_I8: {
3033 guint64 *p = (void*)mem;
3038 g_assert_not_reached ();
3044 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3047 MonoClass *enumc, *objc;
3052 MONO_ARCH_SAVE_REGS;
3054 MONO_CHECK_ARG_NULL (enumType);
3055 MONO_CHECK_ARG_NULL (value);
3057 domain = mono_object_domain (enumType);
3058 enumc = mono_class_from_mono_type (enumType->type);
3060 mono_class_init_or_throw (enumc);
3062 objc = value->vtable->klass;
3064 if (!enumc->enumtype)
3065 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3066 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3067 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."));
3069 etype = mono_class_enum_basetype (enumc);
3071 /* MS throws this for typebuilders */
3072 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3074 res = mono_object_new (domain, enumc);
3075 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3076 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3082 ves_icall_System_Enum_get_value (MonoObject *this)
3090 MONO_ARCH_SAVE_REGS;
3095 g_assert (this->vtable->klass->enumtype);
3097 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3098 res = mono_object_new (mono_object_domain (this), enumc);
3099 dst = (char *)res + sizeof (MonoObject);
3100 src = (char *)this + sizeof (MonoObject);
3101 size = mono_class_value_size (enumc, NULL);
3103 memcpy (dst, src, size);
3108 static MonoReflectionType *
3109 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3114 MONO_ARCH_SAVE_REGS;
3116 klass = mono_class_from_mono_type (type->type);
3117 mono_class_init_or_throw (klass);
3119 etype = mono_class_enum_basetype (klass);
3121 /* MS throws this for typebuilders */
3122 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3124 return mono_type_get_object (mono_object_domain (type), etype);
3128 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3130 gpointer tdata = (char *)this + sizeof (MonoObject);
3131 gpointer odata = (char *)other + sizeof (MonoObject);
3132 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3133 g_assert (basetype);
3135 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3136 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3137 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3140 return me > other ? 1 : -1; \
3143 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3144 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3145 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3148 return me - other; \
3151 switch (basetype->type) {
3153 COMPARE_ENUM_VALUES (guint8);
3155 COMPARE_ENUM_VALUES (gint8);
3156 case MONO_TYPE_CHAR:
3158 COMPARE_ENUM_VALUES_RANGE (guint16);
3160 COMPARE_ENUM_VALUES (gint16);
3162 COMPARE_ENUM_VALUES (guint32);
3164 COMPARE_ENUM_VALUES (gint32);
3166 COMPARE_ENUM_VALUES (guint64);
3168 COMPARE_ENUM_VALUES (gint64);
3170 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3172 #undef COMPARE_ENUM_VALUES_RANGE
3173 #undef COMPARE_ENUM_VALUES
3178 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3180 gpointer data = (char *)this + sizeof (MonoObject);
3181 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3182 g_assert (basetype);
3184 switch (basetype->type) {
3186 return *((gint8*)data);
3188 return *((guint8*)data);
3189 case MONO_TYPE_CHAR:
3191 return *((guint16*)data);
3194 return *((gint16*)data);
3196 return *((guint32*)data);
3198 return *((gint32*)data);
3200 case MONO_TYPE_I8: {
3201 gint64 value = *((gint64*)data);
3202 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3205 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3211 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3213 MonoDomain *domain = mono_object_domain (type);
3214 MonoClass *enumc = mono_class_from_mono_type (type->type);
3215 guint j = 0, nvalues, crow;
3217 MonoClassField *field;
3219 MONO_ARCH_SAVE_REGS;
3221 mono_class_init_or_throw (enumc);
3223 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3224 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3225 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3226 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3230 while ((field = mono_class_get_fields (enumc, &iter))) {
3233 MonoTypeEnum def_type;
3235 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3237 if (mono_field_is_deleted (field))
3239 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3241 p = mono_class_get_field_default_value (field, &def_type);
3242 len = mono_metadata_decode_blob_size (p, &p);
3243 switch (mono_class_enum_basetype (enumc)->type) {
3246 mono_array_set (info->values, gchar, j, *p);
3248 case MONO_TYPE_CHAR:
3251 mono_array_set (info->values, gint16, j, read16 (p));
3255 mono_array_set (info->values, gint32, j, read32 (p));
3259 mono_array_set (info->values, gint64, j, read64 (p));
3262 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3269 BFLAGS_IgnoreCase = 1,
3270 BFLAGS_DeclaredOnly = 2,
3271 BFLAGS_Instance = 4,
3273 BFLAGS_Public = 0x10,
3274 BFLAGS_NonPublic = 0x20,
3275 BFLAGS_FlattenHierarchy = 0x40,
3276 BFLAGS_InvokeMethod = 0x100,
3277 BFLAGS_CreateInstance = 0x200,
3278 BFLAGS_GetField = 0x400,
3279 BFLAGS_SetField = 0x800,
3280 BFLAGS_GetProperty = 0x1000,
3281 BFLAGS_SetProperty = 0x2000,
3282 BFLAGS_ExactBinding = 0x10000,
3283 BFLAGS_SuppressChangeType = 0x20000,
3284 BFLAGS_OptionalParamBinding = 0x40000
3287 static MonoReflectionField *
3288 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3291 MonoClass *startklass, *klass;
3293 MonoClassField *field;
3296 int (*compare_func) (const char *s1, const char *s2) = NULL;
3297 domain = ((MonoObject *)type)->vtable->domain;
3298 klass = startklass = mono_class_from_mono_type (type->type);
3299 mono_class_init_or_throw (klass);
3302 mono_raise_exception (mono_get_exception_argument_null ("name"));
3303 if (type->type->byref)
3306 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3309 if (klass->exception_type != MONO_EXCEPTION_NONE)
3310 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3313 while ((field = mono_class_get_fields (klass, &iter))) {
3316 if (field->type == NULL)
3318 if (mono_field_is_deleted (field))
3320 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3321 if (bflags & BFLAGS_Public)
3323 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3324 if (bflags & BFLAGS_NonPublic) {
3331 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3332 if (bflags & BFLAGS_Static)
3333 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3336 if (bflags & BFLAGS_Instance)
3343 utf8_name = mono_string_to_utf8 (name);
3345 if (compare_func (mono_field_get_name (field), utf8_name)) {
3351 return mono_field_get_object (domain, klass, field);
3353 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3360 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3363 MonoClass *startklass, *klass, *refklass;
3368 MonoClassField *field;
3369 MonoPtrArray tmp_array;
3371 MONO_ARCH_SAVE_REGS;
3373 domain = ((MonoObject *)type)->vtable->domain;
3374 if (type->type->byref)
3375 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3376 klass = startklass = mono_class_from_mono_type (type->type);
3377 refklass = mono_class_from_mono_type (reftype->type);
3379 mono_class_init_or_throw (klass);
3380 mono_class_init_or_throw (refklass);
3382 mono_ptr_array_init (tmp_array, 2);
3385 if (klass->exception_type != MONO_EXCEPTION_NONE)
3386 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3389 while ((field = mono_class_get_fields (klass, &iter))) {
3391 if (mono_field_is_deleted (field))
3393 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3394 if (bflags & BFLAGS_Public)
3396 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3397 if (bflags & BFLAGS_NonPublic) {
3404 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3405 if (bflags & BFLAGS_Static)
3406 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3409 if (bflags & BFLAGS_Instance)
3415 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3416 mono_ptr_array_append (tmp_array, member);
3418 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3421 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3423 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3424 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3426 mono_ptr_array_destroy (tmp_array);
3432 method_nonpublic (MonoMethod* method, gboolean start_klass)
3434 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3435 case METHOD_ATTRIBUTE_ASSEM:
3436 return (start_klass || mono_defaults.generic_ilist_class);
3437 case METHOD_ATTRIBUTE_PRIVATE:
3439 case METHOD_ATTRIBUTE_PUBLIC:
3447 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3449 static MonoClass *MethodInfo_array;
3451 MonoClass *startklass, *klass, *refklass;
3456 int i, len, match, nslots;
3457 /*FIXME, use MonoBitSet*/
3458 guint32 method_slots_default [8];
3459 guint32 *method_slots = NULL;
3460 gchar *mname = NULL;
3461 int (*compare_func) (const char *s1, const char *s2) = NULL;
3462 MonoVTable *array_vtable;
3464 MonoPtrArray tmp_array;
3466 mono_ptr_array_init (tmp_array, 4);
3468 if (!MethodInfo_array) {
3469 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3470 mono_memory_barrier ();
3471 MethodInfo_array = klass;
3474 domain = ((MonoObject *)type)->vtable->domain;
3475 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3476 if (type->type->byref)
3477 return mono_array_new_specific (array_vtable, 0);
3478 klass = startklass = mono_class_from_mono_type (type->type);
3479 refklass = mono_class_from_mono_type (reftype->type);
3481 mono_class_init_or_throw (klass);
3482 mono_class_init_or_throw (refklass);
3486 mname = mono_string_to_utf8 (name);
3487 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3490 /* An optimization for calls made from Delegate:CreateDelegate () */
3491 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3492 method = mono_get_delegate_invoke (klass);
3493 if (mono_loader_get_last_error ())
3496 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3498 res = mono_array_new_specific (array_vtable, 1);
3499 mono_array_setref (res, 0, member);
3504 mono_class_setup_vtable (klass);
3505 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3508 if (is_generic_parameter (type->type))
3509 nslots = mono_class_get_vtable_size (klass->parent);
3511 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3512 if (nslots >= sizeof (method_slots_default) * 8) {
3513 method_slots = g_new0 (guint32, nslots / 32 + 1);
3515 method_slots = method_slots_default;
3516 memset (method_slots, 0, sizeof (method_slots_default));
3519 mono_class_setup_vtable (klass);
3520 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3524 while ((method = mono_class_get_methods (klass, &iter))) {
3526 if (method->slot != -1) {
3527 g_assert (method->slot < nslots);
3528 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3530 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3531 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3534 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3536 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3537 if (bflags & BFLAGS_Public)
3539 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3545 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3546 if (bflags & BFLAGS_Static)
3547 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3550 if (bflags & BFLAGS_Instance)
3558 if (compare_func (mname, method->name))
3564 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3566 mono_ptr_array_append (tmp_array, member);
3568 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3572 if (method_slots != method_slots_default)
3573 g_free (method_slots);
3575 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3577 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3578 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3580 mono_ptr_array_destroy (tmp_array);
3585 if (method_slots != method_slots_default)
3586 g_free (method_slots);
3587 mono_ptr_array_destroy (tmp_array);
3588 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3589 ex = mono_class_get_exception_for_failure (klass);
3591 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3592 mono_loader_clear_error ();
3594 mono_raise_exception (ex);
3599 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3602 static MonoClass *System_Reflection_ConstructorInfo;
3603 MonoClass *startklass, *klass, *refklass;
3608 gpointer iter = NULL;
3609 MonoPtrArray tmp_array;
3611 MONO_ARCH_SAVE_REGS;
3613 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3615 domain = ((MonoObject *)type)->vtable->domain;
3616 if (type->type->byref)
3617 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3618 klass = startklass = mono_class_from_mono_type (type->type);
3619 refklass = mono_class_from_mono_type (reftype->type);
3621 mono_class_init_or_throw (klass);
3622 mono_class_init_or_throw (refklass);
3624 if (klass->exception_type != MONO_EXCEPTION_NONE)
3625 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3627 if (!System_Reflection_ConstructorInfo)
3628 System_Reflection_ConstructorInfo = mono_class_from_name (
3629 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3632 while ((method = mono_class_get_methods (klass, &iter))) {
3634 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3636 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3637 if (bflags & BFLAGS_Public)
3640 if (bflags & BFLAGS_NonPublic)
3646 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3647 if (bflags & BFLAGS_Static)
3648 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3651 if (bflags & BFLAGS_Instance)
3657 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3659 mono_ptr_array_append (tmp_array, member);
3662 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3664 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3665 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3667 mono_ptr_array_destroy (tmp_array);
3673 property_hash (gconstpointer data)
3675 MonoProperty *prop = (MonoProperty*)data;
3677 return g_str_hash (prop->name);
3681 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3683 // Properties are hide-by-name-and-signature
3684 if (!g_str_equal (prop1->name, prop2->name))
3687 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3689 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3695 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3700 return method_nonpublic (accessor, start_klass);
3704 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3707 static MonoClass *System_Reflection_PropertyInfo;
3708 MonoClass *startklass, *klass;
3714 gchar *propname = NULL;
3715 int (*compare_func) (const char *s1, const char *s2) = NULL;
3717 GHashTable *properties;
3718 MonoPtrArray tmp_array;
3720 MONO_ARCH_SAVE_REGS;
3722 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3724 if (!System_Reflection_PropertyInfo)
3725 System_Reflection_PropertyInfo = mono_class_from_name (
3726 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3728 domain = ((MonoObject *)type)->vtable->domain;
3729 if (type->type->byref)
3730 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3731 klass = startklass = mono_class_from_mono_type (type->type);
3732 mono_class_init_or_throw (klass);
3737 propname = mono_string_to_utf8 (name);
3738 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3741 mono_class_setup_vtable (klass);
3743 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3745 mono_class_setup_vtable (klass);
3746 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3747 g_hash_table_destroy (properties);
3750 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3754 while ((prop = mono_class_get_properties (klass, &iter))) {
3760 flags = method->flags;
3763 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3764 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3765 if (bflags & BFLAGS_Public)
3767 } else if (bflags & BFLAGS_NonPublic) {
3768 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3769 property_accessor_nonpublic(prop->set, startklass == klass)) {
3776 if (flags & METHOD_ATTRIBUTE_STATIC) {
3777 if (bflags & BFLAGS_Static)
3778 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3781 if (bflags & BFLAGS_Instance)
3790 if (compare_func (propname, prop->name))
3794 if (g_hash_table_lookup (properties, prop))
3797 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3799 g_hash_table_insert (properties, prop, prop);
3801 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3804 g_hash_table_destroy (properties);
3807 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3808 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3809 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3811 mono_ptr_array_destroy (tmp_array);
3816 static MonoReflectionEvent *
3817 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3820 MonoClass *klass, *startklass;
3826 MONO_ARCH_SAVE_REGS;
3828 event_name = mono_string_to_utf8 (name);
3829 if (type->type->byref)
3831 klass = startklass = mono_class_from_mono_type (type->type);
3832 domain = mono_object_domain (type);
3834 mono_class_init_or_throw (klass);
3837 if (klass->exception_type != MONO_EXCEPTION_NONE)
3838 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3841 while ((event = mono_class_get_events (klass, &iter))) {
3842 if (strcmp (event->name, event_name))
3845 method = event->add;
3847 method = event->remove;
3849 method = event->raise;
3851 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3852 if (!(bflags & BFLAGS_Public))
3855 if (!(bflags & BFLAGS_NonPublic))
3857 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3861 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3862 if (!(bflags & BFLAGS_Static))
3864 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3867 if (!(bflags & BFLAGS_Instance))
3871 if (!(bflags & BFLAGS_NonPublic))
3874 g_free (event_name);
3875 return mono_event_get_object (domain, startklass, event);
3878 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3881 g_free (event_name);
3886 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3889 static MonoClass *System_Reflection_EventInfo;
3890 MonoClass *startklass, *klass;
3897 MonoPtrArray tmp_array;
3899 MONO_ARCH_SAVE_REGS;
3901 mono_ptr_array_init (tmp_array, 4);
3903 if (!System_Reflection_EventInfo)
3904 System_Reflection_EventInfo = mono_class_from_name (
3905 mono_defaults.corlib, "System.Reflection", "EventInfo");
3907 domain = mono_object_domain (type);
3908 if (type->type->byref)
3909 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3910 klass = startklass = mono_class_from_mono_type (type->type);
3911 mono_class_init_or_throw (klass);
3915 if (klass->exception_type != MONO_EXCEPTION_NONE)
3916 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3919 while ((event = mono_class_get_events (klass, &iter))) {
3921 method = event->add;
3923 method = event->remove;
3925 method = event->raise;
3927 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3928 if (bflags & BFLAGS_Public)
3930 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3931 if (bflags & BFLAGS_NonPublic)
3936 if (bflags & BFLAGS_NonPublic)
3942 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3943 if (bflags & BFLAGS_Static)
3944 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3947 if (bflags & BFLAGS_Instance)
3952 if (bflags & BFLAGS_Instance)
3956 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3958 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3961 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3963 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3964 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3966 mono_ptr_array_destroy (tmp_array);
3971 static MonoReflectionType *
3972 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3980 MONO_ARCH_SAVE_REGS;
3983 mono_raise_exception (mono_get_exception_argument_null ("name"));
3985 domain = ((MonoObject *)type)->vtable->domain;
3986 if (type->type->byref)
3988 klass = mono_class_from_mono_type (type->type);
3989 mono_class_init_or_throw (klass);
3991 str = mono_string_to_utf8 (name);
3994 if (klass->exception_type != MONO_EXCEPTION_NONE)
3995 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3998 * If a nested type is generic, return its generic type definition.
3999 * Note that this means that the return value is essentially a
4000 * nested type of the generic type definition of @klass.
4002 * A note in MSDN claims that a generic type definition can have
4003 * nested types that aren't generic. In any case, the container of that
4004 * nested type would be the generic type definition.
4006 if (klass->generic_class)
4007 klass = klass->generic_class->container_class;
4010 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4012 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4013 if (bflags & BFLAGS_Public)
4016 if (bflags & BFLAGS_NonPublic)
4021 if (strcmp (nested->name, str) == 0){
4023 return mono_type_get_object (domain, &nested->byval_arg);
4026 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4033 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4042 MonoPtrArray tmp_array;
4044 MONO_ARCH_SAVE_REGS;
4046 domain = ((MonoObject *)type)->vtable->domain;
4047 if (type->type->byref)
4048 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4049 klass = mono_class_from_mono_type (type->type);
4050 mono_class_init_or_throw (klass);
4053 * If a nested type is generic, return its generic type definition.
4054 * Note that this means that the return value is essentially the set
4055 * of nested types of the generic type definition of @klass.
4057 * A note in MSDN claims that a generic type definition can have
4058 * nested types that aren't generic. In any case, the container of that
4059 * nested type would be the generic type definition.
4061 if (klass->generic_class)
4062 klass = klass->generic_class->container_class;
4064 mono_ptr_array_init (tmp_array, 1);
4066 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4068 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4069 if (bflags & BFLAGS_Public)
4072 if (bflags & BFLAGS_NonPublic)
4077 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4078 mono_ptr_array_append (tmp_array, member);
4081 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4083 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4084 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4086 mono_ptr_array_destroy (tmp_array);
4091 static MonoReflectionType*
4092 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4095 MonoType *type = NULL;
4096 MonoTypeNameParse info;
4097 gboolean type_resolve;
4099 MONO_ARCH_SAVE_REGS;
4101 /* On MS.NET, this does not fire a TypeResolve event */
4102 type_resolve = TRUE;
4103 str = mono_string_to_utf8 (name);
4104 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4105 if (!mono_reflection_parse_type (str, &info)) {
4107 mono_reflection_free_type_info (&info);
4108 if (throwOnError) /* uhm: this is a parse error, though... */
4109 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4110 /*g_print ("failed parse\n");*/
4114 if (info.assembly.name) {
4116 mono_reflection_free_type_info (&info);
4118 /* 1.0 and 2.0 throw different exceptions */
4119 if (mono_defaults.generic_ilist_class)
4120 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4122 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4127 if (module != NULL) {
4129 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4134 if (assembly->assembly->dynamic) {
4135 /* Enumerate all modules */
4136 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4140 if (abuilder->modules) {
4141 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4142 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4143 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4149 if (!type && abuilder->loaded_modules) {
4150 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4151 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4152 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4159 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4161 mono_reflection_free_type_info (&info);
4163 MonoException *e = NULL;
4166 e = mono_get_exception_type_load (name, NULL);
4168 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4169 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4171 mono_loader_clear_error ();
4174 mono_raise_exception (e);
4179 if (type->type == MONO_TYPE_CLASS) {
4180 MonoClass *klass = mono_type_get_class (type);
4182 if (mono_is_security_manager_active () && !klass->exception_type)
4183 /* Some security problems are detected during generic vtable construction */
4184 mono_class_setup_vtable (klass);
4185 /* need to report exceptions ? */
4186 if (throwOnError && klass->exception_type) {
4187 /* report SecurityException (or others) that occured when loading the assembly */
4188 MonoException *exc = mono_class_get_exception_for_failure (klass);
4189 mono_loader_clear_error ();
4190 mono_raise_exception (exc);
4191 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4196 /* g_print ("got it\n"); */
4197 return mono_type_get_object (mono_object_domain (assembly), type);
4201 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4204 gchar *shadow_ini_file;
4207 /* Check for shadow-copied assembly */
4208 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4209 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4211 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4212 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4218 g_free (shadow_ini_file);
4219 if (content != NULL) {
4222 *filename = content;
4230 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4232 MonoDomain *domain = mono_object_domain (assembly);
4233 MonoAssembly *mass = assembly->assembly;
4234 MonoString *res = NULL;
4239 MONO_ARCH_SAVE_REGS;
4241 if (g_path_is_absolute (mass->image->name)) {
4242 absolute = g_strdup (mass->image->name);
4243 dirname = g_path_get_dirname (absolute);
4245 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4246 dirname = g_strdup (mass->basedir);
4249 replace_shadow_path (domain, dirname, &absolute);
4254 for (i = strlen (absolute) - 1; i >= 0; i--)
4255 if (absolute [i] == '\\')
4260 uri = g_filename_to_uri (absolute, NULL, NULL);
4262 const char *prepend = "file://";
4264 if (*absolute == '/' && *(absolute + 1) == '/') {
4267 prepend = "file:///";
4270 uri = g_strconcat (prepend, absolute, NULL);
4274 res = mono_string_new (domain, uri);
4282 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4284 MonoAssembly *mass = assembly->assembly;
4286 MONO_ARCH_SAVE_REGS;
4288 return mass->in_gac;
4291 static MonoReflectionAssembly*
4292 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4296 MonoImageOpenStatus status;
4298 MONO_ARCH_SAVE_REGS;
4300 name = mono_string_to_utf8 (mname);
4301 res = mono_assembly_load_with_partial_name (name, &status);
4307 return mono_assembly_get_object (mono_domain_get (), res);
4311 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4313 MonoDomain *domain = mono_object_domain (assembly);
4316 MONO_ARCH_SAVE_REGS;
4318 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4324 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4326 MONO_ARCH_SAVE_REGS;
4328 return assembly->assembly->ref_only;
4332 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4334 MonoDomain *domain = mono_object_domain (assembly);
4336 MONO_ARCH_SAVE_REGS;
4338 return mono_string_new (domain, assembly->assembly->image->version);
4341 static MonoReflectionMethod*
4342 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4344 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4346 MONO_ARCH_SAVE_REGS;
4350 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4353 static MonoReflectionModule*
4354 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4356 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4360 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4362 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4363 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4367 MONO_ARCH_SAVE_REGS;
4369 for (i = 0; i < table->rows; ++i) {
4370 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4371 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4377 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4379 static MonoClass *System_Version = NULL;
4380 static MonoMethod *create_version = NULL;
4384 if (!System_Version) {
4385 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4386 g_assert (System_Version);
4389 if (!create_version) {
4390 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4391 create_version = mono_method_desc_search_in_class (desc, System_Version);
4392 g_assert (create_version);
4393 mono_method_desc_free (desc);
4399 args [3] = &revision;
4400 result = mono_object_new (domain, System_Version);
4401 mono_runtime_invoke (create_version, result, args, NULL);
4407 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4409 static MonoClass *System_Reflection_AssemblyName;
4411 MonoDomain *domain = mono_object_domain (assembly);
4413 static MonoMethod *create_culture = NULL;
4414 MonoImage *image = assembly->assembly->image;
4417 MONO_ARCH_SAVE_REGS;
4419 if (!System_Reflection_AssemblyName)
4420 System_Reflection_AssemblyName = mono_class_from_name (
4421 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4423 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4426 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4428 if (count > 0 && !create_culture) {
4429 MonoMethodDesc *desc = mono_method_desc_new (
4430 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4431 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4432 g_assert (create_culture);
4433 mono_method_desc_free (desc);
4436 for (i = 0; i < count; i++) {
4437 MonoReflectionAssemblyName *aname;
4438 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4440 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4442 aname = (MonoReflectionAssemblyName *) mono_object_new (
4443 domain, System_Reflection_AssemblyName);
4445 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4447 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4448 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4449 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4450 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4451 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4452 aname->versioncompat = 1; /* SameMachine (default) */
4453 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4454 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4456 if (create_culture) {
4458 MonoBoolean assembly_ref = 1;
4459 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4460 args [1] = &assembly_ref;
4461 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4464 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4465 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4466 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4468 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4469 /* public key token isn't copied - the class library will
4470 automatically generate it from the public key if required */
4471 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4472 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4474 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4475 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4478 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4481 /* note: this function doesn't return the codebase on purpose (i.e. it can
4482 be used under partial trust as path information isn't present). */
4484 mono_array_setref (result, i, aname);
4495 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4497 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4499 mono_array_setref (info->res, info->idx, name);
4504 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4506 MonoImage *img = assembly->assembly->image;
4511 MONO_ARCH_SAVE_REGS;
4513 mono_image_lock (img);
4514 mono_image_init_name_cache (img);
4517 len = g_hash_table_size (img->name_cache);
4518 mono_image_unlock (img);
4520 /*we can't create objects holding the image lock */
4521 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4523 mono_image_lock (img);
4524 /*len might have changed, create a new array*/
4525 if (len != g_hash_table_size (img->name_cache))
4530 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4531 mono_image_unlock (img);
4536 /* move this in some file in mono/util/ */
4538 g_concat_dir_and_file (const char *dir, const char *file)
4540 g_return_val_if_fail (dir != NULL, NULL);
4541 g_return_val_if_fail (file != NULL, NULL);
4544 * If the directory name doesn't have a / on the end, we need
4545 * to add one so we get a proper path to the file
4547 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4548 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4550 return g_strconcat (dir, file, NULL);
4554 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4556 char *n = mono_string_to_utf8 (name);
4557 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4559 guint32 cols [MONO_MANIFEST_SIZE];
4560 guint32 impl, file_idx;
4564 MONO_ARCH_SAVE_REGS;
4566 for (i = 0; i < table->rows; ++i) {
4567 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4568 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4569 if (strcmp (val, n) == 0)
4573 if (i == table->rows)
4576 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4579 * this code should only be called after obtaining the
4580 * ResourceInfo and handling the other cases.
4582 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4583 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4585 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4590 module = assembly->assembly->image;
4592 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4594 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4598 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4600 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4602 guint32 cols [MONO_MANIFEST_SIZE];
4603 guint32 file_cols [MONO_FILE_SIZE];
4607 MONO_ARCH_SAVE_REGS;
4609 n = mono_string_to_utf8 (name);
4610 for (i = 0; i < table->rows; ++i) {
4611 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4612 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4613 if (strcmp (val, n) == 0)
4617 if (i == table->rows)
4620 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4621 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4624 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4625 case MONO_IMPLEMENTATION_FILE:
4626 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4627 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4628 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4629 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4630 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4631 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4634 info->location = RESOURCE_LOCATION_EMBEDDED;
4637 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4638 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4639 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4640 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4641 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4642 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4644 mono_raise_exception (ex);
4646 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4648 /* Obtain info recursively */
4649 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4650 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4653 case MONO_IMPLEMENTATION_EXP_TYPE:
4654 g_assert_not_reached ();
4663 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4665 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4666 MonoArray *result = NULL;
4671 MONO_ARCH_SAVE_REGS;
4673 /* check hash if needed */
4675 n = mono_string_to_utf8 (name);
4676 for (i = 0; i < table->rows; ++i) {
4677 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4678 if (strcmp (val, n) == 0) {
4681 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4682 fn = mono_string_new (mono_object_domain (assembly), n);
4684 return (MonoObject*)fn;
4692 for (i = 0; i < table->rows; ++i) {
4693 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4697 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4700 for (i = 0; i < table->rows; ++i) {
4701 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4702 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4703 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4704 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4709 return (MonoObject*)result;
4713 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4715 MonoDomain *domain = mono_domain_get();
4718 int i, j, file_count = 0;
4719 MonoImage **modules;
4720 guint32 module_count, real_module_count;
4721 MonoTableInfo *table;
4722 guint32 cols [MONO_FILE_SIZE];
4723 MonoImage *image = assembly->assembly->image;
4725 g_assert (image != NULL);
4726 g_assert (!assembly->assembly->dynamic);
4728 table = &image->tables [MONO_TABLE_FILE];
4729 file_count = table->rows;
4731 modules = image->modules;
4732 module_count = image->module_count;
4734 real_module_count = 0;
4735 for (i = 0; i < module_count; ++i)
4737 real_module_count ++;
4739 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4740 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4742 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4744 for (i = 0; i < module_count; ++i)
4746 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4750 for (i = 0; i < file_count; ++i, ++j) {
4751 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4752 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4753 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4755 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4757 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4758 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4760 mono_array_setref (res, j, mono_module_get_object (domain, m));
4767 static MonoReflectionMethod*
4768 ves_icall_GetCurrentMethod (void)
4770 MonoMethod *m = mono_method_get_last_managed ();
4772 while (m->is_inflated)
4773 m = ((MonoMethodInflated*)m)->declaring;
4775 return mono_method_get_object (mono_domain_get (), m, NULL);
4780 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4783 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4784 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4785 //method is inflated, we should inflate it on the other class
4786 MonoGenericContext ctx;
4787 ctx.method_inst = inflated->context.method_inst;
4788 ctx.class_inst = inflated->context.class_inst;
4789 if (klass->generic_class)
4790 ctx.class_inst = klass->generic_class->context.class_inst;
4791 else if (klass->generic_container)
4792 ctx.class_inst = klass->generic_container->context.class_inst;
4793 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4796 mono_class_setup_methods (method->klass);
4797 if (method->klass->exception_type)
4799 for (i = 0; i < method->klass->method.count; ++i) {
4800 if (method->klass->methods [i] == method) {
4805 mono_class_setup_methods (klass);
4806 if (klass->exception_type)
4808 g_assert (offset >= 0 && offset < klass->method.count);
4809 return klass->methods [offset];
4812 static MonoReflectionMethod*
4813 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4817 klass = mono_class_from_mono_type (type);
4818 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4820 if (method->klass != klass) {
4821 method = mono_method_get_equivalent_method (method, klass);
4826 klass = method->klass;
4827 return mono_method_get_object (mono_domain_get (), method, klass);
4830 static MonoReflectionMethod*
4831 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4833 return mono_method_get_object (mono_domain_get (), method, NULL);
4836 static MonoReflectionMethodBody*
4837 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4839 return mono_method_body_get_object (mono_domain_get (), method);
4842 static MonoReflectionAssembly*
4843 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4845 MonoMethod *dest = NULL;
4847 MONO_ARCH_SAVE_REGS;
4849 mono_stack_walk_no_il (get_executing, &dest);
4850 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4854 static MonoReflectionAssembly*
4855 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4857 MonoDomain* domain = mono_domain_get ();
4859 MONO_ARCH_SAVE_REGS;
4861 if (!domain->entry_assembly)
4864 return mono_assembly_get_object (domain, domain->entry_assembly);
4867 static MonoReflectionAssembly*
4868 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4873 MONO_ARCH_SAVE_REGS;
4876 mono_stack_walk_no_il (get_executing, &dest);
4878 mono_stack_walk_no_il (get_caller, &dest);
4881 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4885 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4886 gboolean assembly_qualified)
4888 MonoDomain *domain = mono_object_domain (object);
4889 MonoTypeNameFormat format;
4894 format = assembly_qualified ?
4895 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4896 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4898 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4900 name = mono_type_get_name_full (object->type, format);
4904 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4909 res = mono_string_new (domain, name);
4916 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4918 MonoClass *klass = mono_class_from_mono_type (this->type);
4919 mono_class_init_or_throw (klass);
4920 return mono_security_core_clr_class_level (klass);
4924 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4926 static MonoMethod *create_culture = NULL;
4929 const char *pkey_ptr;
4931 MonoBoolean assembly_ref = 0;
4933 MONO_ARCH_SAVE_REGS;
4935 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4936 aname->major = name->major;
4937 aname->minor = name->minor;
4938 aname->build = name->build;
4939 aname->flags = name->flags;
4940 aname->revision = name->revision;
4941 aname->hashalg = name->hash_alg;
4942 aname->versioncompat = 1; /* SameMachine (default) */
4944 if (by_default_version)
4945 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4948 if (absolute != NULL && *absolute != '\0') {
4949 const gchar *prepend = "file://";
4952 codebase = g_strdup (absolute);
4957 for (i = strlen (codebase) - 1; i >= 0; i--)
4958 if (codebase [i] == '\\')
4961 if (*codebase == '/' && *(codebase + 1) == '/') {
4964 prepend = "file:///";
4968 result = g_strconcat (prepend, codebase, NULL);
4974 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4978 if (!create_culture) {
4979 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4980 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4981 g_assert (create_culture);
4982 mono_method_desc_free (desc);
4985 if (name->culture) {
4986 args [0] = mono_string_new (domain, name->culture);
4987 args [1] = &assembly_ref;
4988 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4991 if (name->public_key) {
4992 pkey_ptr = (char*)name->public_key;
4993 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4995 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4996 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4997 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4998 } else if (default_publickey) {
4999 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5000 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5003 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5004 if (name->public_key_token [0]) {
5008 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5009 p = mono_array_addr (aname->keyToken, char, 0);
5011 for (i = 0, j = 0; i < 8; i++) {
5012 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5013 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5016 } else if (default_token) {
5017 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5022 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5024 MonoDomain *domain = mono_object_domain (assembly);
5025 MonoAssembly *mass = assembly->assembly;
5029 name = g_strdup_printf (
5030 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5032 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5033 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5034 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5035 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5037 res = mono_string_new (domain, name);
5044 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5047 MonoAssembly *mass = assembly->assembly;
5049 MONO_ARCH_SAVE_REGS;
5051 if (g_path_is_absolute (mass->image->name)) {
5052 fill_reflection_assembly_name (mono_object_domain (assembly),
5053 aname, &mass->aname, mass->image->name, TRUE,
5057 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5059 fill_reflection_assembly_name (mono_object_domain (assembly),
5060 aname, &mass->aname, absolute, TRUE, TRUE,
5067 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5070 MonoImageOpenStatus status = MONO_IMAGE_OK;
5073 MonoAssemblyName name;
5076 MONO_ARCH_SAVE_REGS;
5078 filename = mono_string_to_utf8 (fname);
5080 dirname = g_path_get_dirname (filename);
5081 replace_shadow_path (mono_domain_get (), dirname, &filename);
5084 image = mono_image_open (filename, &status);
5090 if (status == MONO_IMAGE_IMAGE_INVALID)
5091 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5093 exc = mono_get_exception_file_not_found2 (NULL, fname);
5094 mono_raise_exception (exc);
5097 res = mono_assembly_fill_assembly_name (image, &name);
5099 mono_image_close (image);
5101 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5104 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5108 mono_image_close (image);
5112 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5113 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5115 MonoBoolean result = FALSE;
5116 MonoDeclSecurityEntry entry;
5118 /* SecurityAction.RequestMinimum */
5119 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5120 *minimum = entry.blob;
5121 *minLength = entry.size;
5124 /* SecurityAction.RequestOptional */
5125 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5126 *optional = entry.blob;
5127 *optLength = entry.size;
5130 /* SecurityAction.RequestRefuse */
5131 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5132 *refused = entry.blob;
5133 *refLength = entry.size;
5141 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5145 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5147 guint32 attrs, visibility;
5149 /* we start the count from 1 because we skip the special type <Module> */
5152 for (i = 1; i < tdef->rows; ++i) {
5153 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5154 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5155 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5159 count = tdef->rows - 1;
5161 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5162 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5164 for (i = 1; i < tdef->rows; ++i) {
5165 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5166 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5167 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5168 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5170 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5172 MonoLoaderError *error;
5175 error = mono_loader_get_last_error ();
5176 g_assert (error != NULL);
5178 ex = mono_loader_error_prepare_exception (error);
5179 mono_array_setref (*exceptions, count, ex);
5181 if (mono_loader_get_last_error ())
5182 mono_loader_clear_error ();
5191 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5193 MonoArray *res = NULL;
5194 MonoArray *exceptions = NULL;
5195 MonoImage *image = NULL;
5196 MonoTableInfo *table = NULL;
5199 int i, len, ex_count;
5201 MONO_ARCH_SAVE_REGS;
5203 domain = mono_object_domain (assembly);
5205 g_assert (!assembly->assembly->dynamic);
5206 image = assembly->assembly->image;
5207 table = &image->tables [MONO_TABLE_FILE];
5208 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5210 /* Append data from all modules in the assembly */
5211 for (i = 0; i < table->rows; ++i) {
5212 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5213 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5216 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5217 /* Append the new types to the end of the array */
5218 if (mono_array_length (res2) > 0) {
5220 MonoArray *res3, *ex3;
5222 len1 = mono_array_length (res);
5223 len2 = mono_array_length (res2);
5225 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5226 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5227 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5230 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5231 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5232 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5239 /* the ReflectionTypeLoadException must have all the types (Types property),
5240 * NULL replacing types which throws an exception. The LoaderException must
5241 * contain all exceptions for NULL items.
5244 len = mono_array_length (res);
5247 for (i = 0; i < len; i++) {
5248 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5252 klass = mono_type_get_class (t->type);
5253 if ((klass != NULL) && klass->exception_type) {
5254 /* keep the class in the list */
5255 list = g_list_append (list, klass);
5256 /* and replace Type with NULL */
5257 mono_array_setref (res, i, NULL);
5264 if (list || ex_count) {
5266 MonoException *exc = NULL;
5267 MonoArray *exl = NULL;
5268 int j, length = g_list_length (list) + ex_count;
5270 mono_loader_clear_error ();
5272 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5273 /* Types for which mono_class_get () succeeded */
5274 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5275 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5276 mono_array_setref (exl, i, exc);
5278 /* Types for which it don't */
5279 for (j = 0; j < mono_array_length (exceptions); ++j) {
5280 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5282 g_assert (i < length);
5283 mono_array_setref (exl, i, exc);
5290 exc = mono_get_exception_reflection_type_load (res, exl);
5291 mono_loader_clear_error ();
5292 mono_raise_exception (exc);
5299 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5301 MonoAssemblyName aname;
5302 MonoDomain *domain = mono_object_domain (name);
5304 gboolean is_version_defined;
5305 gboolean is_token_defined;
5307 aname.public_key = NULL;
5308 val = mono_string_to_utf8 (assname);
5309 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5310 g_free ((guint8*) aname.public_key);
5315 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5316 FALSE, is_token_defined);
5318 mono_assembly_name_free (&aname);
5319 g_free ((guint8*) aname.public_key);
5325 static MonoReflectionType*
5326 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5328 MonoDomain *domain = mono_object_domain (module);
5331 MONO_ARCH_SAVE_REGS;
5333 g_assert (module->image);
5335 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5336 /* These images do not have a global type */
5339 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5340 return mono_type_get_object (domain, &klass->byval_arg);
5344 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5346 /*if (module->image)
5347 mono_image_close (module->image);*/
5351 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5353 MonoDomain *domain = mono_object_domain (module);
5355 MONO_ARCH_SAVE_REGS;
5357 g_assert (module->image);
5358 return mono_string_new (domain, module->image->guid);
5362 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5365 if (module->image && module->image->is_module_handle)
5366 return module->image->raw_data;
5369 return (gpointer) (-1);
5373 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5375 if (image->dynamic) {
5376 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5377 *pe_kind = dyn->pe_kind;
5378 *machine = dyn->machine;
5381 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5382 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5387 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5389 return (image->md_version_major << 16) | (image->md_version_minor);
5393 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5395 MonoArray *exceptions;
5398 MONO_ARCH_SAVE_REGS;
5401 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5403 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5404 for (i = 0; i < mono_array_length (exceptions); ++i) {
5405 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5407 mono_raise_exception (ex);
5414 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5416 guint32 cols [MONO_MEMBERREF_SIZE];
5418 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5419 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5420 mono_metadata_decode_blob_size (sig, &sig);
5421 return (*sig != 0x6);
5425 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5428 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5429 mono_array_addr (type_args, MonoType*, 0));
5431 context->class_inst = NULL;
5433 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5434 mono_array_addr (method_args, MonoType*, 0));
5436 context->method_inst = NULL;
5440 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5443 int table = mono_metadata_token_table (token);
5444 int index = mono_metadata_token_index (token);
5445 MonoGenericContext context;
5447 *error = ResolveTokenError_Other;
5449 /* Validate token */
5450 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5451 (table != MONO_TABLE_TYPESPEC)) {
5452 *error = ResolveTokenError_BadTable;
5456 if (image->dynamic) {
5457 if (type_args || method_args)
5458 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5459 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5462 return &klass->byval_arg;
5465 if ((index <= 0) || (index > image->tables [table].rows)) {
5466 *error = ResolveTokenError_OutOfRange;
5470 init_generic_context_from_args (&context, type_args, method_args);
5471 klass = mono_class_get_full (image, token, &context);
5473 if (mono_loader_get_last_error ())
5474 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5477 return &klass->byval_arg;
5483 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5485 int table = mono_metadata_token_table (token);
5486 int index = mono_metadata_token_index (token);
5487 MonoGenericContext context;
5490 *error = ResolveTokenError_Other;
5492 /* Validate token */
5493 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5494 (table != MONO_TABLE_MEMBERREF)) {
5495 *error = ResolveTokenError_BadTable;
5499 if (image->dynamic) {
5500 if (type_args || method_args)
5501 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5502 /* FIXME: validate memberref token type */
5503 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5506 if ((index <= 0) || (index > image->tables [table].rows)) {
5507 *error = ResolveTokenError_OutOfRange;
5510 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5511 *error = ResolveTokenError_BadTable;
5515 init_generic_context_from_args (&context, type_args, method_args);
5516 method = mono_get_method_full (image, token, NULL, &context);
5518 if (mono_loader_get_last_error ())
5519 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5525 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5527 int index = mono_metadata_token_index (token);
5529 *error = ResolveTokenError_Other;
5531 /* Validate token */
5532 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5533 *error = ResolveTokenError_BadTable;
5538 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5540 if ((index <= 0) || (index >= image->heap_us.size)) {
5541 *error = ResolveTokenError_OutOfRange;
5545 /* FIXME: What to do if the index points into the middle of a string ? */
5547 return mono_ldstr (mono_domain_get (), image, index);
5550 static MonoClassField*
5551 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5554 int table = mono_metadata_token_table (token);
5555 int index = mono_metadata_token_index (token);
5556 MonoGenericContext context;
5557 MonoClassField *field;
5559 *error = ResolveTokenError_Other;
5561 /* Validate token */
5562 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5563 *error = ResolveTokenError_BadTable;
5567 if (image->dynamic) {
5568 if (type_args || method_args)
5569 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5570 /* FIXME: validate memberref token type */
5571 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5574 if ((index <= 0) || (index > image->tables [table].rows)) {
5575 *error = ResolveTokenError_OutOfRange;
5578 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5579 *error = ResolveTokenError_BadTable;
5583 init_generic_context_from_args (&context, type_args, method_args);
5584 field = mono_field_from_token (image, token, &klass, &context);
5586 if (mono_loader_get_last_error ())
5587 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5594 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5596 int table = mono_metadata_token_table (token);
5598 *error = ResolveTokenError_Other;
5601 case MONO_TABLE_TYPEDEF:
5602 case MONO_TABLE_TYPEREF:
5603 case MONO_TABLE_TYPESPEC: {
5604 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5606 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5610 case MONO_TABLE_METHOD:
5611 case MONO_TABLE_METHODSPEC: {
5612 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5614 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5618 case MONO_TABLE_FIELD: {
5619 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5621 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5625 case MONO_TABLE_MEMBERREF:
5626 if (mono_metadata_memberref_is_method (image, token)) {
5627 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5629 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5634 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5636 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5643 *error = ResolveTokenError_BadTable;
5650 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5652 int table = mono_metadata_token_table (token);
5653 int idx = mono_metadata_token_index (token);
5654 MonoTableInfo *tables = image->tables;
5659 *error = ResolveTokenError_OutOfRange;
5661 /* FIXME: Support other tables ? */
5662 if (table != MONO_TABLE_STANDALONESIG)
5668 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5671 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5673 ptr = mono_metadata_blob_heap (image, sig);
5674 len = mono_metadata_decode_blob_size (ptr, &ptr);
5676 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5677 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5681 static MonoReflectionType*
5682 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5685 int isbyref = 0, rank;
5686 char *str = mono_string_to_utf8 (smodifiers);
5689 MONO_ARCH_SAVE_REGS;
5691 klass = mono_class_from_mono_type (tb->type.type);
5693 /* logic taken from mono_reflection_parse_type(): keep in sync */
5697 if (isbyref) { /* only one level allowed by the spec */
5704 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5707 klass = mono_ptr_class_get (&klass->byval_arg);
5708 mono_class_init (klass);
5719 else if (*p != '*') { /* '*' means unknown lower bound */
5730 klass = mono_array_class_get (klass, rank);
5731 mono_class_init (klass);
5738 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5742 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5747 MONO_ARCH_SAVE_REGS;
5750 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5755 static MonoReflectionType *
5756 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5758 MonoClass *klass, *aklass;
5760 MONO_ARCH_SAVE_REGS;
5762 klass = mono_class_from_mono_type (type->type);
5763 mono_class_init_or_throw (klass);
5765 if (rank == 0) //single dimentional array
5766 aklass = mono_array_class_get (klass, 1);
5768 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5770 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5773 static MonoReflectionType *
5774 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5778 MONO_ARCH_SAVE_REGS;
5780 klass = mono_class_from_mono_type (type->type);
5781 mono_class_init_or_throw (klass);
5783 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5786 static MonoReflectionType *
5787 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5791 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
5793 pklass = mono_ptr_class_get (type->type);
5795 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5799 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5800 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5802 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5803 MonoObject *delegate;
5805 MonoMethod *method = info->method;
5807 MONO_ARCH_SAVE_REGS;
5809 mono_class_init_or_throw (delegate_class);
5811 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5813 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5814 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5818 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5820 if (method->dynamic) {
5821 /* Creating a trampoline would leak memory */
5822 func = mono_compile_method (method);
5824 func = mono_create_ftnptr (mono_domain_get (),
5825 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5828 mono_delegate_ctor_with_method (delegate, target, func, method);
5834 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5836 /* Reset the invoke impl to the default one */
5837 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5841 * Magic number to convert a time which is relative to
5842 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5844 #define EPOCH_ADJUST ((guint64)62135596800LL)
5847 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5849 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5852 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5854 convert_to_absolute_date(SYSTEMTIME *date)
5856 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5857 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5858 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5859 /* from the calendar FAQ */
5860 int a = (14 - date->wMonth) / 12;
5861 int y = date->wYear - a;
5862 int m = date->wMonth + 12 * a - 2;
5863 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5865 /* d is now the day of the week for the first of the month (0 == Sunday) */
5867 int day_of_week = date->wDayOfWeek;
5869 /* set day_in_month to the first day in the month which falls on day_of_week */
5870 int day_in_month = 1 + (day_of_week - d);
5871 if (day_in_month <= 0)
5874 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5875 date->wDay = day_in_month + (date->wDay - 1) * 7;
5876 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5883 * Return's the offset from GMT of a local time.
5885 * tm is a local time
5886 * t is the same local time as seconds.
5889 gmt_offset(struct tm *tm, time_t t)
5891 #if defined (HAVE_TM_GMTOFF)
5892 return tm->tm_gmtoff;
5897 g.tm_isdst = tm->tm_isdst;
5899 return (int)difftime(t, t2);
5904 * This is heavily based on zdump.c from glibc 2.2.
5906 * * data[0]: start of daylight saving time (in DateTime ticks).
5907 * * data[1]: end of daylight saving time (in DateTime ticks).
5908 * * data[2]: utcoffset (in TimeSpan ticks).
5909 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5910 * * name[0]: name of this timezone when not daylight saving.
5911 * * name[1]: name of this timezone when daylight saving.
5913 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5914 * the class library allows years between 1 and 9999.
5916 * Returns true on success and zero on failure.
5919 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5922 MonoDomain *domain = mono_domain_get ();
5923 struct tm start, tt;
5927 int is_daylight = 0, day;
5930 MONO_ARCH_SAVE_REGS;
5932 MONO_CHECK_ARG_NULL (data);
5933 MONO_CHECK_ARG_NULL (names);
5935 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5936 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5939 * no info is better than crashing: we'll need our own tz data
5940 * to make this work properly, anyway. The range is probably
5941 * reduced to 1970 .. 2037 because that is what mktime is
5942 * guaranteed to support (we get into an infinite loop
5946 memset (&start, 0, sizeof (start));
5949 start.tm_year = year-1900;
5951 t = mktime (&start);
5953 if ((year < 1970) || (year > 2037) || (t == -1)) {
5955 tt = *localtime (&t);
5956 strftime (tzone, sizeof (tzone), "%Z", &tt);
5957 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5958 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5962 gmtoff = gmt_offset (&start, t);
5964 /* For each day of the year, calculate the tm_gmtoff. */
5965 for (day = 0; day < 365; day++) {
5968 tt = *localtime (&t);
5970 /* Daylight saving starts or ends here. */
5971 if (gmt_offset (&tt, t) != gmtoff) {
5975 /* Try to find the exact hour when daylight saving starts/ends. */
5979 tt1 = *localtime (&t1);
5980 } while (gmt_offset (&tt1, t1) != gmtoff);
5982 /* Try to find the exact minute when daylight saving starts/ends. */
5985 tt1 = *localtime (&t1);
5986 } while (gmt_offset (&tt1, t1) == gmtoff);
5988 strftime (tzone, sizeof (tzone), "%Z", &tt);
5990 /* Write data, if we're already in daylight saving, we're done. */
5992 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5993 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5996 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5997 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6001 /* This is only set once when we enter daylight saving. */
6002 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6003 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6005 gmtoff = gmt_offset (&tt, t);
6010 strftime (tzone, sizeof (tzone), "%Z", &tt);
6011 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6012 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6013 mono_array_set ((*data), gint64, 0, 0);
6014 mono_array_set ((*data), gint64, 1, 0);
6015 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6016 mono_array_set ((*data), gint64, 3, 0);
6021 MonoDomain *domain = mono_domain_get ();
6022 TIME_ZONE_INFORMATION tz_info;
6027 tz_id = GetTimeZoneInformation (&tz_info);
6028 if (tz_id == TIME_ZONE_ID_INVALID)
6031 MONO_CHECK_ARG_NULL (data);
6032 MONO_CHECK_ARG_NULL (names);
6034 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6035 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6037 for (i = 0; i < 32; ++i)
6038 if (!tz_info.DaylightName [i])
6040 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6041 for (i = 0; i < 32; ++i)
6042 if (!tz_info.StandardName [i])
6044 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6046 if ((year <= 1601) || (year > 30827)) {
6048 * According to MSDN, the MS time functions can't handle dates outside
6054 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6055 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6056 tz_info.StandardDate.wYear = year;
6057 convert_to_absolute_date(&tz_info.StandardDate);
6058 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6063 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6064 tz_info.DaylightDate.wYear = year;
6065 convert_to_absolute_date(&tz_info.DaylightDate);
6066 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6071 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6073 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6074 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6081 ves_icall_System_Object_obj_address (MonoObject *this)
6083 MONO_ARCH_SAVE_REGS;
6090 static inline gint32
6091 mono_array_get_byte_length (MonoArray *array)
6097 klass = array->obj.vtable->klass;
6099 if (array->bounds == NULL)
6100 length = array->max_length;
6103 for (i = 0; i < klass->rank; ++ i)
6104 length *= array->bounds [i].length;
6107 switch (klass->element_class->byval_arg.type) {
6110 case MONO_TYPE_BOOLEAN:
6114 case MONO_TYPE_CHAR:
6122 return length * sizeof (gpointer);
6133 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6135 MONO_ARCH_SAVE_REGS;
6137 return mono_array_get_byte_length (array);
6141 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6143 MONO_ARCH_SAVE_REGS;
6145 return mono_array_get (array, gint8, idx);
6149 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6151 MONO_ARCH_SAVE_REGS;
6153 mono_array_set (array, gint8, idx, value);
6157 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6159 guint8 *src_buf, *dest_buf;
6161 MONO_ARCH_SAVE_REGS;
6163 /* watch out for integer overflow */
6164 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6167 src_buf = (guint8 *)src->vector + src_offset;
6168 dest_buf = (guint8 *)dest->vector + dest_offset;
6171 memcpy (dest_buf, src_buf, count);
6173 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6179 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6181 MonoDomain *domain = mono_object_domain (this);
6183 MonoRealProxy *rp = ((MonoRealProxy *)this);
6184 MonoTransparentProxy *tp;
6188 MONO_ARCH_SAVE_REGS;
6190 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6191 tp = (MonoTransparentProxy*) res;
6193 MONO_OBJECT_SETREF (tp, rp, rp);
6194 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6195 klass = mono_class_from_mono_type (type);
6197 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6198 tp->remote_class = mono_remote_class (domain, class_name, klass);
6200 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6204 static MonoReflectionType *
6205 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6207 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6210 /* System.Environment */
6213 ves_icall_System_Environment_get_UserName (void)
6215 MONO_ARCH_SAVE_REGS;
6217 /* using glib is more portable */
6218 return mono_string_new (mono_domain_get (), g_get_user_name ());
6223 ves_icall_System_Environment_get_MachineName (void)
6225 #if defined (HOST_WIN32)
6230 len = MAX_COMPUTERNAME_LENGTH + 1;
6231 buf = g_new (gunichar2, len);
6234 if (GetComputerName (buf, (PDWORD) &len))
6235 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6239 #elif !defined(DISABLE_SOCKETS)
6243 if (gethostname (buf, sizeof (buf)) == 0)
6244 result = mono_string_new (mono_domain_get (), buf);
6250 return mono_string_new (mono_domain_get (), "mono");
6255 ves_icall_System_Environment_get_Platform (void)
6257 #if defined (TARGET_WIN32)
6260 #elif defined(__MACH__)
6263 // For compatibility with our client code, this will be 4 for a while.
6264 // We will eventually move to 6 to match .NET, but it requires all client
6265 // code to be updated and the documentation everywhere to be updated
6276 ves_icall_System_Environment_get_NewLine (void)
6278 MONO_ARCH_SAVE_REGS;
6280 #if defined (HOST_WIN32)
6281 return mono_string_new (mono_domain_get (), "\r\n");
6283 return mono_string_new (mono_domain_get (), "\n");
6288 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6293 MONO_ARCH_SAVE_REGS;
6298 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6299 value = g_getenv (utf8_name);
6306 return mono_string_new (mono_domain_get (), value);
6310 * There is no standard way to get at environ.
6313 #ifndef __MINGW32_VERSION
6315 /* Apple defines this in crt_externs.h but doesn't provide that header for
6316 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6317 * in fact exist on all implementations (so far)
6319 gchar ***_NSGetEnviron(void);
6320 #define environ (*_NSGetEnviron())
6329 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6340 env_strings = GetEnvironmentStrings();
6343 env_string = env_strings;
6344 while (*env_string != '\0') {
6345 /* weird case that MS seems to skip */
6346 if (*env_string != '=')
6348 while (*env_string != '\0')
6354 domain = mono_domain_get ();
6355 names = mono_array_new (domain, mono_defaults.string_class, n);
6359 env_string = env_strings;
6360 while (*env_string != '\0') {
6361 /* weird case that MS seems to skip */
6362 if (*env_string != '=') {
6363 equal_str = wcschr(env_string, '=');
6364 g_assert(equal_str);
6365 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6366 mono_array_setref (names, n, str);
6369 while (*env_string != '\0')
6374 FreeEnvironmentStrings (env_strings);
6386 MONO_ARCH_SAVE_REGS;
6389 for (e = environ; *e != 0; ++ e)
6392 domain = mono_domain_get ();
6393 names = mono_array_new (domain, mono_defaults.string_class, n);
6396 for (e = environ; *e != 0; ++ e) {
6397 parts = g_strsplit (*e, "=", 2);
6399 str = mono_string_new (domain, *parts);
6400 mono_array_setref (names, n, str);
6413 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6415 #if !GLIB_CHECK_VERSION(2,4,0)
6416 #define g_setenv(a,b,c) setenv(a,b,c)
6417 #define g_unsetenv(a) unsetenv(a)
6421 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6426 gunichar2 *utf16_name, *utf16_value;
6428 gchar *utf8_name, *utf8_value;
6431 MONO_ARCH_SAVE_REGS;
6434 utf16_name = mono_string_to_utf16 (name);
6435 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6436 SetEnvironmentVariable (utf16_name, NULL);
6437 g_free (utf16_name);
6441 utf16_value = mono_string_to_utf16 (value);
6443 SetEnvironmentVariable (utf16_name, utf16_value);
6445 g_free (utf16_name);
6446 g_free (utf16_value);
6448 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6450 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6451 g_unsetenv (utf8_name);
6456 utf8_value = mono_string_to_utf8_checked (value, &error);
6457 if (!mono_error_ok (&error)) {
6459 mono_error_raise_exception (&error);
6461 g_setenv (utf8_name, utf8_value, TRUE);
6464 g_free (utf8_value);
6469 ves_icall_System_Environment_Exit (int result)
6471 MONO_ARCH_SAVE_REGS;
6473 mono_threads_set_shutting_down ();
6475 mono_runtime_set_shutting_down ();
6477 /* This will kill the tp threads which cannot be suspended */
6478 mono_thread_pool_cleanup ();
6480 /* Suspend all managed threads since the runtime is going away */
6481 mono_thread_suspend_all_other_threads ();
6483 mono_runtime_quit ();
6485 /* we may need to do some cleanup here... */
6490 ves_icall_System_Environment_GetGacPath (void)
6492 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6496 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6498 #if defined (HOST_WIN32)
6499 #ifndef CSIDL_FLAG_CREATE
6500 #define CSIDL_FLAG_CREATE 0x8000
6503 WCHAR path [MAX_PATH];
6504 /* Create directory if no existing */
6505 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6509 return mono_string_new_utf16 (mono_domain_get (), path, len);
6512 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6514 return mono_string_new (mono_domain_get (), "");
6518 ves_icall_System_Environment_GetLogicalDrives (void)
6520 gunichar2 buf [128], *ptr, *dname;
6522 guint initial_size = 127, size = 128;
6525 MonoString *drivestr;
6526 MonoDomain *domain = mono_domain_get ();
6529 MONO_ARCH_SAVE_REGS;
6534 while (size > initial_size) {
6535 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6536 if (size > initial_size) {
6539 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6540 initial_size = size;
6554 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6559 while (*u16) { u16++; len ++; }
6560 drivestr = mono_string_new_utf16 (domain, dname, len);
6561 mono_array_setref (result, ndrives++, drivestr);
6572 ves_icall_System_Environment_InternalGetHome (void)
6574 MONO_ARCH_SAVE_REGS;
6576 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6579 static const char *encodings [] = {
6581 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6582 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6583 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6585 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6586 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6587 "x_unicode_2_0_utf_7",
6589 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6590 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6592 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6595 "unicodefffe", "utf_16be",
6602 * Returns the internal codepage, if the value of "int_code_page" is
6603 * 1 at entry, and we can not compute a suitable code page number,
6604 * returns the code page as a string
6607 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6612 char *codepage = NULL;
6614 int want_name = *int_code_page;
6617 *int_code_page = -1;
6618 MONO_ARCH_SAVE_REGS;
6620 g_get_charset (&cset);
6621 c = codepage = strdup (cset);
6622 for (c = codepage; *c; c++){
6623 if (isascii (*c) && isalpha (*c))
6628 /* g_print ("charset: %s\n", cset); */
6630 /* handle some common aliases */
6633 for (i = 0; p != 0; ){
6634 if ((gssize) p < 7){
6636 p = encodings [++i];
6639 if (strcmp (p, codepage) == 0){
6640 *int_code_page = code;
6643 p = encodings [++i];
6646 if (strstr (codepage, "utf_8") != NULL)
6647 *int_code_page |= 0x10000000;
6650 if (want_name && *int_code_page == -1)
6651 return mono_string_new (mono_domain_get (), cset);
6657 ves_icall_System_Environment_get_HasShutdownStarted (void)
6659 if (mono_runtime_is_shutting_down ())
6662 if (mono_domain_is_unloading (mono_domain_get ()))
6669 ves_icall_System_Environment_BroadcastSettingChange (void)
6672 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6677 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6678 MonoReflectionMethod *method,
6679 MonoArray *out_args)
6681 MONO_ARCH_SAVE_REGS;
6683 mono_message_init (mono_object_domain (this), this, method, out_args);
6687 ves_icall_IsTransparentProxy (MonoObject *proxy)
6689 MONO_ARCH_SAVE_REGS;
6694 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6700 static MonoReflectionMethod *
6701 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6702 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6706 MonoMethod **vtable;
6707 MonoMethod *res = NULL;
6709 MONO_CHECK_ARG_NULL (rtype);
6710 MONO_CHECK_ARG_NULL (rmethod);
6712 method = rmethod->method;
6713 klass = mono_class_from_mono_type (rtype->type);
6714 mono_class_init_or_throw (klass);
6716 if (MONO_CLASS_IS_INTERFACE (klass))
6719 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6722 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6723 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6729 mono_class_setup_vtable (klass);
6730 vtable = klass->vtable;
6732 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6733 gboolean variance_used = FALSE;
6734 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6735 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6737 res = vtable [offs + method->slot];
6739 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6742 if (method->slot != -1)
6743 res = vtable [method->slot];
6749 return mono_method_get_object (mono_domain_get (), res, NULL);
6753 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6758 MONO_ARCH_SAVE_REGS;
6760 klass = mono_class_from_mono_type (type->type);
6761 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6763 if (enable) vtable->remote = 1;
6764 else vtable->remote = 0;
6768 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6773 MONO_ARCH_SAVE_REGS;
6775 domain = mono_object_domain (type);
6776 klass = mono_class_from_mono_type (type->type);
6777 mono_class_init_or_throw (klass);
6779 if (klass->rank >= 1) {
6780 g_assert (klass->rank == 1);
6781 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6783 /* Bypass remoting object creation check */
6784 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6789 ves_icall_System_IO_get_temp_path (void)
6791 MONO_ARCH_SAVE_REGS;
6793 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6796 #ifndef PLATFORM_NO_DRIVEINFO
6798 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6799 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6803 ULARGE_INTEGER wapi_free_bytes_avail;
6804 ULARGE_INTEGER wapi_total_number_of_bytes;
6805 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6807 MONO_ARCH_SAVE_REGS;
6809 *error = ERROR_SUCCESS;
6810 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6811 &wapi_total_number_of_free_bytes);
6814 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6815 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6816 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6818 *free_bytes_avail = 0;
6819 *total_number_of_bytes = 0;
6820 *total_number_of_free_bytes = 0;
6821 *error = GetLastError ();
6828 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6830 MONO_ARCH_SAVE_REGS;
6832 return GetDriveType (mono_string_chars (root_path_name));
6837 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6839 MONO_ARCH_SAVE_REGS;
6841 return mono_compile_method (method);
6845 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6850 MONO_ARCH_SAVE_REGS;
6852 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6854 #if defined (HOST_WIN32)
6855 /* Avoid mixing '/' and '\\' */
6858 for (i = strlen (path) - 1; i >= 0; i--)
6859 if (path [i] == '/')
6863 mcpath = mono_string_new (mono_domain_get (), path);
6870 get_bundled_machine_config (void)
6872 const gchar *machine_config;
6874 MONO_ARCH_SAVE_REGS;
6876 machine_config = mono_get_machine_config ();
6878 if (!machine_config)
6881 return mono_string_new (mono_domain_get (), machine_config);
6885 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6890 MONO_ARCH_SAVE_REGS;
6892 path = g_path_get_dirname (mono_get_config_dir ());
6894 #if defined (HOST_WIN32)
6895 /* Avoid mixing '/' and '\\' */
6898 for (i = strlen (path) - 1; i >= 0; i--)
6899 if (path [i] == '/')
6903 ipath = mono_string_new (mono_domain_get (), path);
6910 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6912 MonoPEResourceDataEntry *entry;
6915 MONO_ARCH_SAVE_REGS;
6917 if (!assembly || !result || !size)
6922 image = assembly->assembly->image;
6923 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6927 *result = mono_image_rva_map (image, entry->rde_data_offset);
6932 *size = entry->rde_size;
6938 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6940 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6944 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6946 #if defined (HOST_WIN32)
6947 OutputDebugString (mono_string_chars (message));
6949 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6953 /* Only used for value types */
6955 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6960 MONO_ARCH_SAVE_REGS;
6962 domain = mono_object_domain (type);
6963 klass = mono_class_from_mono_type (type->type);
6964 mono_class_init_or_throw (klass);
6966 if (mono_class_is_nullable (klass))
6967 /* No arguments -> null */
6970 return mono_object_new (domain, klass);
6973 static MonoReflectionMethod *
6974 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6976 MonoClass *klass, *parent;
6977 MonoMethod *method = m->method;
6978 MonoMethod *result = NULL;
6980 MONO_ARCH_SAVE_REGS;
6982 if (method->klass == NULL)
6985 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6986 MONO_CLASS_IS_INTERFACE (method->klass) ||
6987 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6990 klass = method->klass;
6991 if (klass->generic_class)
6992 klass = klass->generic_class->container_class;
6995 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6996 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6997 mono_class_setup_vtable (parent);
6998 if (parent->vtable_size <= method->slot)
7003 klass = klass->parent;
7008 if (klass == method->klass)
7011 result = klass->vtable [method->slot];
7012 if (result == NULL) {
7013 /* It is an abstract method */
7014 gpointer iter = NULL;
7015 while ((result = mono_class_get_methods (klass, &iter)))
7016 if (result->slot == method->slot)
7023 return mono_method_get_object (mono_domain_get (), result, NULL);
7027 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7029 MonoMethod *method = m->method;
7031 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7036 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7038 MONO_ARCH_SAVE_REGS;
7040 iter->sig = *(MonoMethodSignature**)argsp;
7042 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7043 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7046 /* FIXME: it's not documented what start is exactly... */
7050 iter->args = argsp + sizeof (gpointer);
7052 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7054 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7058 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7060 guint32 i, arg_size;
7063 MONO_ARCH_SAVE_REGS;
7065 i = iter->sig->sentinelpos + iter->next_arg;
7067 g_assert (i < iter->sig->param_count);
7069 res.type = iter->sig->params [i];
7070 res.klass = mono_class_from_mono_type (res.type);
7071 res.value = iter->args;
7072 arg_size = mono_type_stack_size (res.type, &align);
7073 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7074 if (arg_size <= sizeof (gpointer)) {
7076 int padding = arg_size - mono_type_size (res.type, &dummy);
7077 res.value = (guint8*)res.value + padding;
7080 iter->args = (char*)iter->args + arg_size;
7083 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7089 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7091 guint32 i, arg_size;
7094 MONO_ARCH_SAVE_REGS;
7096 i = iter->sig->sentinelpos + iter->next_arg;
7098 g_assert (i < iter->sig->param_count);
7100 while (i < iter->sig->param_count) {
7101 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7103 res.type = iter->sig->params [i];
7104 res.klass = mono_class_from_mono_type (res.type);
7105 /* FIXME: endianess issue... */
7106 res.value = iter->args;
7107 arg_size = mono_type_stack_size (res.type, &align);
7108 iter->args = (char*)iter->args + arg_size;
7110 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7113 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7122 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7125 MONO_ARCH_SAVE_REGS;
7127 i = iter->sig->sentinelpos + iter->next_arg;
7129 g_assert (i < iter->sig->param_count);
7131 return iter->sig->params [i];
7135 mono_TypedReference_ToObject (MonoTypedRef tref)
7137 MONO_ARCH_SAVE_REGS;
7139 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7140 MonoObject** objp = tref.value;
7144 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7148 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7150 MONO_ARCH_SAVE_REGS;
7152 if (MONO_TYPE_IS_REFERENCE (type)) {
7153 MonoObject** objp = value;
7157 return mono_value_box (mono_domain_get (), klass, value);
7161 prelink_method (MonoMethod *method)
7163 const char *exc_class, *exc_arg;
7164 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7166 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7168 mono_raise_exception(
7169 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7171 /* create the wrapper, too? */
7175 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7177 MONO_ARCH_SAVE_REGS;
7178 prelink_method (method->method);
7182 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7184 MonoClass *klass = mono_class_from_mono_type (type->type);
7186 gpointer iter = NULL;
7187 MONO_ARCH_SAVE_REGS;
7189 mono_class_init_or_throw (klass);
7191 while ((m = mono_class_get_methods (klass, &iter)))
7195 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7197 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7198 gint32 const **exponents,
7199 gunichar2 const **digitLowerTable,
7200 gunichar2 const **digitUpperTable,
7201 gint64 const **tenPowersList,
7202 gint32 const **decHexDigits)
7204 *mantissas = Formatter_MantissaBitsTable;
7205 *exponents = Formatter_TensExponentTable;
7206 *digitLowerTable = Formatter_DigitLowerTable;
7207 *digitUpperTable = Formatter_DigitUpperTable;
7208 *tenPowersList = Formatter_TenPowersList;
7209 *decHexDigits = Formatter_DecHexDigits;
7212 /* These parameters are "readonly" in corlib/System/Char.cs */
7214 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7215 guint8 const **numeric_data,
7216 gdouble const **numeric_data_values,
7217 guint16 const **to_lower_data_low,
7218 guint16 const **to_lower_data_high,
7219 guint16 const **to_upper_data_low,
7220 guint16 const **to_upper_data_high)
7222 *category_data = CategoryData;
7223 *numeric_data = NumericData;
7224 *numeric_data_values = NumericDataValues;
7225 *to_lower_data_low = ToLowerDataLow;
7226 *to_lower_data_high = ToLowerDataHigh;
7227 *to_upper_data_low = ToUpperDataLow;
7228 *to_upper_data_high = ToUpperDataHigh;
7232 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7234 return method->method->token;
7238 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7239 * and avoid useless allocations.
7242 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7246 for (i = 0; i < type->num_mods; ++i) {
7247 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7252 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7254 for (i = 0; i < type->num_mods; ++i) {
7255 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7256 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7257 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7265 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7267 MonoType *type = param->ClassImpl->type;
7268 MonoClass *member_class = mono_object_class (param->MemberImpl);
7269 MonoMethod *method = NULL;
7272 MonoMethodSignature *sig;
7274 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7275 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7276 method = rmethod->method;
7277 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7278 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7279 if (!(method = prop->property->get))
7280 method = prop->property->set;
7283 char *type_name = mono_type_get_full_name (member_class);
7284 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7285 MonoException *ex = mono_get_exception_not_supported (msg);
7288 mono_raise_exception (ex);
7291 image = method->klass->image;
7292 pos = param->PositionImpl;
7293 sig = mono_method_signature (method);
7297 type = sig->params [pos];
7299 return type_array_from_modifiers (image, type, optional);
7303 get_property_type (MonoProperty *prop)
7305 MonoMethodSignature *sig;
7307 sig = mono_method_signature (prop->get);
7309 } else if (prop->set) {
7310 sig = mono_method_signature (prop->set);
7311 return sig->params [sig->param_count - 1];
7317 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7319 MonoType *type = get_property_type (property->property);
7320 MonoImage *image = property->klass->image;
7324 return type_array_from_modifiers (image, type, optional);
7328 *Construct a MonoType suited to be used to decode a constant blob object.
7330 * @type is the target type which will be constructed
7331 * @blob_type is the blob type, for example, that comes from the constant table
7332 * @real_type is the expected constructed type.
7335 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7337 type->type = blob_type;
7338 type->data.klass = NULL;
7339 if (blob_type == MONO_TYPE_CLASS)
7340 type->data.klass = mono_defaults.object_class;
7341 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7342 /* For enums, we need to use the base type */
7343 type->type = MONO_TYPE_VALUETYPE;
7344 type->data.klass = mono_class_from_mono_type (real_type);
7346 type->data.klass = mono_class_from_mono_type (real_type);
7350 property_info_get_default_value (MonoReflectionProperty *property)
7353 MonoProperty *prop = property->property;
7354 MonoType *type = get_property_type (prop);
7355 MonoDomain *domain = mono_object_domain (property);
7356 MonoTypeEnum def_type;
7357 const char *def_value;
7360 g_assert (!prop->parent->image->dynamic);
7362 mono_class_init (prop->parent);
7364 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7365 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7367 def_value = mono_class_get_property_default_value (prop, &def_type);
7369 mono_type_from_blob_type (&blob_type, def_type, type);
7370 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7376 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7378 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7379 MonoCustomAttrInfo *cinfo;
7382 mono_class_init_or_throw (attr_class);
7384 cinfo = mono_reflection_get_custom_attrs_info (obj);
7387 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7389 mono_custom_attrs_free (cinfo);
7394 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7396 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7400 mono_class_init_or_throw (attr_class);
7402 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7404 if (mono_loader_get_last_error ()) {
7405 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7406 g_assert_not_reached ();
7415 ves_icall_Mono_Runtime_GetDisplayName (void)
7418 MonoString *display_name;
7420 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7421 display_name = mono_string_new (mono_domain_get (), info);
7423 return display_name;
7427 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7429 MonoString *message;
7433 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7434 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7437 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7439 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7447 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7448 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7449 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7450 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7451 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7452 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7453 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7454 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7458 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7463 gunichar2 last, prev_last, prev2_last;
7471 last = prev_last = 0, prev2_last = 0;
7472 for (i = 0; i < ilength; i++) {
7474 if (c >= sizeof (dbase64)) {
7475 exc = mono_exception_from_name_msg (mono_get_corlib (),
7476 "System", "FormatException",
7477 "Invalid character found.");
7478 mono_raise_exception (exc);
7479 } else if (isspace (c)) {
7482 prev2_last = prev_last;
7488 olength = ilength - ignored;
7490 if (allowWhitespaceOnly && olength == 0) {
7491 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7494 if ((olength & 3) != 0 || olength <= 0) {
7495 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7496 "FormatException", "Invalid length.");
7497 mono_raise_exception (exc);
7500 if (prev2_last == '=') {
7501 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7502 mono_raise_exception (exc);
7505 olength = (olength * 3) / 4;
7509 if (prev_last == '=')
7512 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7513 res_ptr = mono_array_addr (result, guchar, 0);
7514 for (i = 0; i < ilength; ) {
7517 for (k = 0; k < 4 && i < ilength;) {
7523 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7524 exc = mono_exception_from_name_msg (mono_get_corlib (),
7525 "System", "FormatException",
7526 "Invalid character found.");
7527 mono_raise_exception (exc);
7532 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7534 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7536 *res_ptr++ = (b [2] << 6) | b [3];
7538 while (i < ilength && isspace (start [i]))
7546 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7548 MONO_ARCH_SAVE_REGS;
7550 return base64_to_byte_array (mono_string_chars (str),
7551 mono_string_length (str), allowWhitespaceOnly);
7555 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7557 MONO_ARCH_SAVE_REGS;
7559 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7563 #define ICALL_TYPE(id,name,first)
7564 #define ICALL(id,name,func) Icall_ ## id,
7567 #include "metadata/icall-def.h"
7573 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7574 #define ICALL(id,name,func)
7576 #include "metadata/icall-def.h"
7582 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7583 #define ICALL(id,name,func)
7585 guint16 first_icall;
7588 static const IcallTypeDesc
7589 icall_type_descs [] = {
7590 #include "metadata/icall-def.h"
7594 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7597 #define ICALL_TYPE(id,name,first)
7600 #ifdef HAVE_ARRAY_ELEM_INIT
7601 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7602 #define MSGSTRFIELD1(line) str##line
7604 static const struct msgstrtn_t {
7605 #define ICALL(id,name,func)
7607 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7608 #include "metadata/icall-def.h"
7610 } icall_type_names_str = {
7611 #define ICALL_TYPE(id,name,first) (name),
7612 #include "metadata/icall-def.h"
7615 static const guint16 icall_type_names_idx [] = {
7616 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7617 #include "metadata/icall-def.h"
7620 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7622 static const struct msgstr_t {
7624 #define ICALL_TYPE(id,name,first)
7625 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7626 #include "metadata/icall-def.h"
7628 } icall_names_str = {
7629 #define ICALL(id,name,func) (name),
7630 #include "metadata/icall-def.h"
7633 static const guint16 icall_names_idx [] = {
7634 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7635 #include "metadata/icall-def.h"
7638 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7644 #define ICALL_TYPE(id,name,first) name,
7645 #define ICALL(id,name,func)
7646 static const char* const
7647 icall_type_names [] = {
7648 #include "metadata/icall-def.h"
7652 #define icall_type_name_get(id) (icall_type_names [(id)])
7656 #define ICALL_TYPE(id,name,first)
7657 #define ICALL(id,name,func) name,
7658 static const char* const
7660 #include "metadata/icall-def.h"
7663 #define icall_name_get(id) icall_names [(id)]
7665 #endif /* !HAVE_ARRAY_ELEM_INIT */
7669 #define ICALL_TYPE(id,name,first)
7670 #define ICALL(id,name,func) func,
7671 static const gconstpointer
7672 icall_functions [] = {
7673 #include "metadata/icall-def.h"
7677 static GHashTable *icall_hash = NULL;
7678 static GHashTable *jit_icall_hash_name = NULL;
7679 static GHashTable *jit_icall_hash_addr = NULL;
7682 mono_icall_init (void)
7686 /* check that tables are sorted: disable in release */
7689 const char *prev_class = NULL;
7690 const char *prev_method;
7692 for (i = 0; i < Icall_type_num; ++i) {
7693 const IcallTypeDesc *desc;
7696 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7697 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7698 prev_class = icall_type_name_get (i);
7699 desc = &icall_type_descs [i];
7700 num_icalls = icall_desc_num_icalls (desc);
7701 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7702 for (j = 0; j < num_icalls; ++j) {
7703 const char *methodn = icall_name_get (desc->first_icall + j);
7704 if (prev_method && strcmp (prev_method, methodn) >= 0)
7705 g_print ("method %s should come before method %s\n", methodn, prev_method);
7706 prev_method = methodn;
7711 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7715 mono_icall_cleanup (void)
7717 g_hash_table_destroy (icall_hash);
7718 g_hash_table_destroy (jit_icall_hash_name);
7719 g_hash_table_destroy (jit_icall_hash_addr);
7723 mono_add_internal_call (const char *name, gconstpointer method)
7725 mono_loader_lock ();
7727 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7729 mono_loader_unlock ();
7732 #ifdef HAVE_ARRAY_ELEM_INIT
7734 compare_method_imap (const void *key, const void *elem)
7736 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7737 return strcmp (key, method_name);
7741 find_method_icall (const IcallTypeDesc *imap, const char *name)
7743 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7746 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7750 compare_class_imap (const void *key, const void *elem)
7752 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7753 return strcmp (key, class_name);
7756 static const IcallTypeDesc*
7757 find_class_icalls (const char *name)
7759 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7762 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7767 compare_method_imap (const void *key, const void *elem)
7769 const char** method_name = (const char**)elem;
7770 return strcmp (key, *method_name);
7774 find_method_icall (const IcallTypeDesc *imap, const char *name)
7776 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7779 return (gpointer)icall_functions [(nameslot - icall_names)];
7783 compare_class_imap (const void *key, const void *elem)
7785 const char** class_name = (const char**)elem;
7786 return strcmp (key, *class_name);
7789 static const IcallTypeDesc*
7790 find_class_icalls (const char *name)
7792 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7795 return &icall_type_descs [nameslot - icall_type_names];
7801 * we should probably export this as an helper (handle nested types).
7802 * Returns the number of chars written in buf.
7805 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7807 int nspacelen, cnamelen;
7808 nspacelen = strlen (klass->name_space);
7809 cnamelen = strlen (klass->name);
7810 if (nspacelen + cnamelen + 2 > bufsize)
7813 memcpy (buf, klass->name_space, nspacelen);
7814 buf [nspacelen ++] = '.';
7816 memcpy (buf + nspacelen, klass->name, cnamelen);
7817 buf [nspacelen + cnamelen] = 0;
7818 return nspacelen + cnamelen;
7822 mono_lookup_internal_call (MonoMethod *method)
7827 int typelen = 0, mlen, siglen;
7829 const IcallTypeDesc *imap;
7831 g_assert (method != NULL);
7833 if (method->is_inflated)
7834 method = ((MonoMethodInflated *) method)->declaring;
7836 if (method->klass->nested_in) {
7837 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7841 mname [pos++] = '/';
7844 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7850 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7855 imap = find_class_icalls (mname);
7857 mname [typelen] = ':';
7858 mname [typelen + 1] = ':';
7860 mlen = strlen (method->name);
7861 memcpy (mname + typelen + 2, method->name, mlen);
7862 sigstart = mname + typelen + 2 + mlen;
7865 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7866 siglen = strlen (tmpsig);
7867 if (typelen + mlen + siglen + 6 > sizeof (mname))
7870 memcpy (sigstart + 1, tmpsig, siglen);
7871 sigstart [siglen + 1] = ')';
7872 sigstart [siglen + 2] = 0;
7875 mono_loader_lock ();
7877 res = g_hash_table_lookup (icall_hash, mname);
7879 mono_loader_unlock ();
7882 /* try without signature */
7884 res = g_hash_table_lookup (icall_hash, mname);
7886 mono_loader_unlock ();
7890 /* it wasn't found in the static call tables */
7892 mono_loader_unlock ();
7895 res = find_method_icall (imap, sigstart - mlen);
7897 mono_loader_unlock ();
7900 /* try _with_ signature */
7902 res = find_method_icall (imap, sigstart - mlen);
7904 mono_loader_unlock ();
7908 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7909 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7910 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7911 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7912 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");
7913 g_print ("If you see other errors or faults after this message they are probably related\n");
7914 g_print ("and you need to fix your mono install first.\n");
7916 mono_loader_unlock ();
7922 type_from_typename (char *typename)
7924 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7926 if (!strcmp (typename, "int"))
7927 klass = mono_defaults.int_class;
7928 else if (!strcmp (typename, "ptr"))
7929 klass = mono_defaults.int_class;
7930 else if (!strcmp (typename, "void"))
7931 klass = mono_defaults.void_class;
7932 else if (!strcmp (typename, "int32"))
7933 klass = mono_defaults.int32_class;
7934 else if (!strcmp (typename, "uint32"))
7935 klass = mono_defaults.uint32_class;
7936 else if (!strcmp (typename, "int8"))
7937 klass = mono_defaults.sbyte_class;
7938 else if (!strcmp (typename, "uint8"))
7939 klass = mono_defaults.byte_class;
7940 else if (!strcmp (typename, "int16"))
7941 klass = mono_defaults.int16_class;
7942 else if (!strcmp (typename, "uint16"))
7943 klass = mono_defaults.uint16_class;
7944 else if (!strcmp (typename, "long"))
7945 klass = mono_defaults.int64_class;
7946 else if (!strcmp (typename, "ulong"))
7947 klass = mono_defaults.uint64_class;
7948 else if (!strcmp (typename, "float"))
7949 klass = mono_defaults.single_class;
7950 else if (!strcmp (typename, "double"))
7951 klass = mono_defaults.double_class;
7952 else if (!strcmp (typename, "object"))
7953 klass = mono_defaults.object_class;
7954 else if (!strcmp (typename, "obj"))
7955 klass = mono_defaults.object_class;
7956 else if (!strcmp (typename, "string"))
7957 klass = mono_defaults.string_class;
7958 else if (!strcmp (typename, "bool"))
7959 klass = mono_defaults.boolean_class;
7960 else if (!strcmp (typename, "boolean"))
7961 klass = mono_defaults.boolean_class;
7963 g_error ("%s", typename);
7964 g_assert_not_reached ();
7966 return &klass->byval_arg;
7969 MonoMethodSignature*
7970 mono_create_icall_signature (const char *sigstr)
7975 MonoMethodSignature *res;
7977 mono_loader_lock ();
7978 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7980 mono_loader_unlock ();
7984 parts = g_strsplit (sigstr, " ", 256);
7993 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7998 * Under windows, the default pinvoke calling convention is STDCALL but
8001 res->call_convention = MONO_CALL_C;
8004 res->ret = type_from_typename (parts [0]);
8005 for (i = 1; i < len; ++i) {
8006 res->params [i - 1] = type_from_typename (parts [i]);
8011 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8013 mono_loader_unlock ();
8019 mono_find_jit_icall_by_name (const char *name)
8021 MonoJitICallInfo *info;
8022 g_assert (jit_icall_hash_name);
8024 mono_loader_lock ();
8025 info = g_hash_table_lookup (jit_icall_hash_name, name);
8026 mono_loader_unlock ();
8031 mono_find_jit_icall_by_addr (gconstpointer addr)
8033 MonoJitICallInfo *info;
8034 g_assert (jit_icall_hash_addr);
8036 mono_loader_lock ();
8037 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8038 mono_loader_unlock ();
8044 * mono_get_jit_icall_info:
8046 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8047 * caller should access it while holding the loader lock.
8050 mono_get_jit_icall_info (void)
8052 return jit_icall_hash_name;
8056 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8058 mono_loader_lock ();
8059 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8060 mono_loader_unlock ();
8064 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8066 MonoJitICallInfo *info;
8071 mono_loader_lock ();
8073 if (!jit_icall_hash_name) {
8074 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8075 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8078 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8079 g_warning ("jit icall already defined \"%s\"\n", name);
8080 g_assert_not_reached ();
8083 info = g_new0 (MonoJitICallInfo, 1);
8090 info->wrapper = func;
8092 info->wrapper = NULL;
8095 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8096 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8098 mono_loader_unlock ();