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 * We expect a pointer to a char, not a string
145 mono_double_ParseImpl (char *ptr, double *result)
147 gchar *endptr = NULL;
154 *result = strtod (ptr, &endptr);
158 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
159 EnterCriticalSection (&mono_strtod_mutex);
160 *result = mono_strtod (ptr, &endptr);
161 LeaveCriticalSection (&mono_strtod_mutex);
163 *result = mono_strtod (ptr, &endptr);
168 if (!*ptr || (endptr && *endptr))
175 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
184 ao = (MonoArray *)this;
185 ac = (MonoClass *)ao->obj.vtable->klass;
187 esize = mono_array_element_size (ac);
188 ea = (gpointer*)((char*)ao->vector + (pos * esize));
190 if (ac->element_class->valuetype)
191 return mono_value_box (this->vtable->domain, ac->element_class, ea);
197 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
205 MONO_CHECK_ARG_NULL (idxs);
207 io = (MonoArray *)idxs;
208 ic = (MonoClass *)io->obj.vtable->klass;
210 ao = (MonoArray *)this;
211 ac = (MonoClass *)ao->obj.vtable->klass;
213 g_assert (ic->rank == 1);
214 if (io->bounds != NULL || io->max_length != ac->rank)
215 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
217 ind = (gint32 *)io->vector;
219 if (ao->bounds == NULL) {
220 if (*ind < 0 || *ind >= ao->max_length)
221 mono_raise_exception (mono_get_exception_index_out_of_range ());
223 return ves_icall_System_Array_GetValueImpl (this, *ind);
226 for (i = 0; i < ac->rank; i++)
227 if ((ind [i] < ao->bounds [i].lower_bound) ||
228 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
229 mono_raise_exception (mono_get_exception_index_out_of_range ());
231 pos = ind [0] - ao->bounds [0].lower_bound;
232 for (i = 1; i < ac->rank; i++)
233 pos = pos*ao->bounds [i].length + ind [i] -
234 ao->bounds [i].lower_bound;
236 return ves_icall_System_Array_GetValueImpl (this, pos);
240 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
242 MonoClass *ac, *vc, *ec;
254 vc = value->vtable->klass;
258 ac = this->obj.vtable->klass;
259 ec = ac->element_class;
261 esize = mono_array_element_size (ac);
262 ea = (gpointer*)((char*)this->vector + (pos * esize));
263 va = (gpointer*)((char*)value + sizeof (MonoObject));
265 if (mono_class_is_nullable (ec)) {
266 mono_nullable_init ((guint8*)ea, value, ec);
271 memset (ea, 0, esize);
275 #define NO_WIDENING_CONVERSION G_STMT_START{\
276 mono_raise_exception (mono_get_exception_argument ( \
277 "value", "not a widening conversion")); \
280 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
281 if (esize < vsize + (extra)) \
282 mono_raise_exception (mono_get_exception_argument ( \
283 "value", "not a widening conversion")); \
286 #define INVALID_CAST G_STMT_START{\
287 mono_raise_exception (mono_get_exception_invalid_cast ()); \
290 /* Check element (destination) type. */
291 switch (ec->byval_arg.type) {
292 case MONO_TYPE_STRING:
293 switch (vc->byval_arg.type) {
294 case MONO_TYPE_STRING:
300 case MONO_TYPE_BOOLEAN:
301 switch (vc->byval_arg.type) {
302 case MONO_TYPE_BOOLEAN:
315 NO_WIDENING_CONVERSION;
322 if (!ec->valuetype) {
323 if (!mono_object_isinst (value, ec))
325 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
329 if (mono_object_isinst (value, ec)) {
330 if (ec->has_references)
331 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
333 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
340 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
342 et = ec->byval_arg.type;
343 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
344 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
346 vt = vc->byval_arg.type;
347 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
348 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
350 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
356 case MONO_TYPE_CHAR: \
357 CHECK_WIDENING_CONVERSION(0); \
358 *(etype *) ea = (etype) u64; \
360 /* You can't assign a signed value to an unsigned array. */ \
365 /* You can't assign a floating point number to an integer array. */ \
368 NO_WIDENING_CONVERSION; \
372 #define ASSIGN_SIGNED(etype) G_STMT_START{\
378 CHECK_WIDENING_CONVERSION(0); \
379 *(etype *) ea = (etype) i64; \
381 /* You can assign an unsigned value to a signed array if the array's */ \
382 /* element size is larger than the value size. */ \
387 case MONO_TYPE_CHAR: \
388 CHECK_WIDENING_CONVERSION(1); \
389 *(etype *) ea = (etype) u64; \
391 /* You can't assign a floating point number to an integer array. */ \
394 NO_WIDENING_CONVERSION; \
398 #define ASSIGN_REAL(etype) G_STMT_START{\
402 CHECK_WIDENING_CONVERSION(0); \
403 *(etype *) ea = (etype) r64; \
405 /* All integer values fit into a floating point array, so we don't */ \
406 /* need to CHECK_WIDENING_CONVERSION here. */ \
411 *(etype *) ea = (etype) i64; \
417 case MONO_TYPE_CHAR: \
418 *(etype *) ea = (etype) u64; \
425 u64 = *(guint8 *) va;
428 u64 = *(guint16 *) va;
431 u64 = *(guint32 *) va;
434 u64 = *(guint64 *) va;
440 i64 = *(gint16 *) va;
443 i64 = *(gint32 *) va;
446 i64 = *(gint64 *) va;
449 r64 = *(gfloat *) va;
452 r64 = *(gdouble *) va;
455 u64 = *(guint16 *) va;
457 case MONO_TYPE_BOOLEAN:
458 /* Boolean is only compatible with itself. */
471 NO_WIDENING_CONVERSION;
478 /* If we can't do a direct copy, let's try a widening conversion. */
481 ASSIGN_UNSIGNED (guint16);
483 ASSIGN_UNSIGNED (guint8);
485 ASSIGN_UNSIGNED (guint16);
487 ASSIGN_UNSIGNED (guint32);
489 ASSIGN_UNSIGNED (guint64);
491 ASSIGN_SIGNED (gint8);
493 ASSIGN_SIGNED (gint16);
495 ASSIGN_SIGNED (gint32);
497 ASSIGN_SIGNED (gint64);
499 ASSIGN_REAL (gfloat);
501 ASSIGN_REAL (gdouble);
505 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
509 #undef NO_WIDENING_CONVERSION
510 #undef CHECK_WIDENING_CONVERSION
511 #undef ASSIGN_UNSIGNED
517 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
525 MONO_CHECK_ARG_NULL (idxs);
527 ic = idxs->obj.vtable->klass;
528 ac = this->obj.vtable->klass;
530 g_assert (ic->rank == 1);
531 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
532 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
534 ind = (gint32 *)idxs->vector;
536 if (this->bounds == NULL) {
537 if (*ind < 0 || *ind >= this->max_length)
538 mono_raise_exception (mono_get_exception_index_out_of_range ());
540 ves_icall_System_Array_SetValueImpl (this, value, *ind);
544 for (i = 0; i < ac->rank; i++)
545 if ((ind [i] < this->bounds [i].lower_bound) ||
546 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
547 mono_raise_exception (mono_get_exception_index_out_of_range ());
549 pos = ind [0] - this->bounds [0].lower_bound;
550 for (i = 1; i < ac->rank; i++)
551 pos = pos * this->bounds [i].length + ind [i] -
552 this->bounds [i].lower_bound;
554 ves_icall_System_Array_SetValueImpl (this, value, pos);
558 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
563 gboolean bounded = FALSE;
567 MONO_CHECK_ARG_NULL (type);
568 MONO_CHECK_ARG_NULL (lengths);
570 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
572 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
574 for (i = 0; i < mono_array_length (lengths); i++)
575 if (mono_array_get (lengths, gint32, i) < 0)
576 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
578 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
579 /* vectors are not the same as one dimensional arrays with no-zero bounds */
584 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
586 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
587 for (i = 0; i < aklass->rank; ++i) {
588 sizes [i] = mono_array_get (lengths, guint32, i);
590 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
592 sizes [i + aklass->rank] = 0;
595 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
601 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
606 gboolean bounded = FALSE;
610 MONO_CHECK_ARG_NULL (type);
611 MONO_CHECK_ARG_NULL (lengths);
613 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
615 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
617 for (i = 0; i < mono_array_length (lengths); i++)
618 if ((mono_array_get (lengths, gint64, i) < 0) ||
619 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
620 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
622 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
623 /* vectors are not the same as one dimensional arrays with no-zero bounds */
628 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
630 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
631 for (i = 0; i < aklass->rank; ++i) {
632 sizes [i] = mono_array_get (lengths, guint64, i);
634 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
636 sizes [i + aklass->rank] = 0;
639 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
645 ves_icall_System_Array_GetRank (MonoObject *this)
649 return this->vtable->klass->rank;
653 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
655 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
660 if ((dimension < 0) || (dimension >= rank))
661 mono_raise_exception (mono_get_exception_index_out_of_range ());
663 if (this->bounds == NULL)
664 length = this->max_length;
666 length = this->bounds [dimension].length;
668 #ifdef MONO_BIG_ARRAYS
669 if (length > G_MAXINT32)
670 mono_raise_exception (mono_get_exception_overflow ());
676 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
678 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
682 if ((dimension < 0) || (dimension >= rank))
683 mono_raise_exception (mono_get_exception_index_out_of_range ());
685 if (this->bounds == NULL)
686 return this->max_length;
688 return this->bounds [dimension].length;
692 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
694 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
698 if ((dimension < 0) || (dimension >= rank))
699 mono_raise_exception (mono_get_exception_index_out_of_range ());
701 if (this->bounds == NULL)
704 return this->bounds [dimension].lower_bound;
708 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
710 int sz = mono_array_element_size (mono_object_class (arr));
711 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
715 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
720 MonoClass *src_class;
721 MonoClass *dest_class;
726 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
729 if (source->bounds || dest->bounds)
732 /* there's no integer overflow since mono_array_length returns an unsigned integer */
733 if ((dest_idx + length > mono_array_length (dest)) ||
734 (source_idx + length > mono_array_length (source)))
737 src_class = source->obj.vtable->klass->element_class;
738 dest_class = dest->obj.vtable->klass->element_class;
741 * Handle common cases.
744 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
745 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
746 int has_refs = dest_class->has_references;
747 for (i = source_idx; i < source_idx + length; ++i) {
748 MonoObject *elem = mono_array_get (source, MonoObject*, i);
749 if (elem && !mono_object_isinst (elem, dest_class))
753 element_size = mono_array_element_size (dest->obj.vtable->klass);
754 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
755 for (i = 0; i < length; ++i) {
756 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
757 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
761 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
763 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
768 /* Check if we're copying a char[] <==> (u)short[] */
769 if (src_class != dest_class) {
770 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
773 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
775 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
776 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
777 for (i = source_idx; i < source_idx + length; ++i) {
778 MonoObject *elem = mono_array_get (source, MonoObject*, i);
779 if (elem && !mono_object_isinst (elem, dest_class))
786 if (dest_class->valuetype) {
787 element_size = mono_array_element_size (source->obj.vtable->klass);
788 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
789 if (dest_class->has_references) {
790 mono_value_copy_array (dest, dest_idx, source_addr, length);
792 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
793 memmove (dest_addr, source_addr, element_size * length);
796 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
803 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
812 ao = (MonoArray *)this;
813 ac = (MonoClass *)ao->obj.vtable->klass;
815 esize = mono_array_element_size (ac);
816 ea = (gpointer*)((char*)ao->vector + (pos * esize));
818 memcpy (value, ea, esize);
822 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
831 ao = (MonoArray *)this;
832 ac = (MonoClass *)ao->obj.vtable->klass;
833 ec = ac->element_class;
835 esize = mono_array_element_size (ac);
836 ea = (gpointer*)((char*)ao->vector + (pos * esize));
838 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
839 g_assert (esize == sizeof (gpointer));
840 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
842 g_assert (ec->inited);
843 g_assert (esize == mono_class_value_size (ec, NULL));
844 if (ec->has_references)
845 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
847 memcpy (ea, value, esize);
852 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
854 MonoClass *klass = array->obj.vtable->klass;
855 guint32 size = mono_array_element_size (klass);
856 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
858 const char *field_data;
860 if (MONO_TYPE_IS_REFERENCE (type) ||
861 (type->type == MONO_TYPE_VALUETYPE &&
862 (!mono_type_get_class (type) ||
863 mono_type_get_class (type)->has_references))) {
864 MonoException *exc = mono_get_exception_argument("array",
865 "Cannot initialize array containing references");
866 mono_raise_exception (exc);
869 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
870 MonoException *exc = mono_get_exception_argument("field_handle",
871 "Field doesn't have an RVA");
872 mono_raise_exception (exc);
875 size *= array->max_length;
876 field_data = mono_field_get_data (field_handle);
878 if (size > mono_type_size (field_handle->type, &align)) {
879 MonoException *exc = mono_get_exception_argument("field_handle",
880 "Field not large enough to fill array");
881 mono_raise_exception (exc);
884 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
886 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
887 guint ## n *src = (guint ## n *) field_data; \
888 guint ## n *end = (guint ## n *)((char*)src + size); \
890 for (; src < end; data++, src++) { \
891 *data = read ## n (src); \
895 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
897 switch (type->type) {
914 memcpy (mono_array_addr (array, char, 0), field_data, size);
918 memcpy (mono_array_addr (array, char, 0), field_data, size);
920 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
923 double *data = (double*)mono_array_addr (array, double, 0);
925 for (i = 0; i < size; i++, data++) {
935 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
939 return offsetof (MonoString, chars);
943 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
947 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
950 return mono_object_clone (obj);
954 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
959 MONO_CHECK_ARG_NULL (handle);
961 klass = mono_class_from_mono_type (handle);
962 MONO_CHECK_ARG (handle, klass);
964 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
966 /* This will call the type constructor */
967 mono_runtime_class_init (vtable);
971 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
975 mono_image_check_for_module_cctor (image);
976 if (image->has_module_cctor) {
977 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
978 /*It's fine to raise the exception here*/
979 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
984 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
989 /* later make this configurable and per-arch */
990 int min_size = 4096 * 4 * sizeof (void*);
991 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
992 /* if we have no info we are optimistic and assume there is enough room */
995 current = (guint8 *)&stack_addr;
996 if (current > stack_addr) {
997 if ((current - stack_addr) < min_size)
1000 if (current - (stack_addr - stack_size) < min_size)
1007 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
1009 MONO_ARCH_SAVE_REGS;
1011 return mono_object_clone (this);
1015 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
1018 MonoObject **values = NULL;
1022 MonoClassField* field;
1025 MONO_ARCH_SAVE_REGS;
1027 klass = mono_object_class (this);
1029 if (mono_class_num_fields (klass) == 0)
1030 return mono_object_hash (this);
1033 * Compute the starting value of the hashcode for fields of primitive
1034 * types, and return the remaining fields in an array to the managed side.
1035 * This way, we can avoid costly reflection operations in managed code.
1038 while ((field = mono_class_get_fields (klass, &iter))) {
1039 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1041 if (mono_field_is_deleted (field))
1043 /* FIXME: Add more types */
1044 switch (field->type->type) {
1046 result ^= *(gint32*)((guint8*)this + field->offset);
1048 case MONO_TYPE_STRING: {
1050 s = *(MonoString**)((guint8*)this + field->offset);
1052 result ^= mono_string_hash (s);
1057 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1058 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1059 values [count++] = o;
1065 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1066 for (i = 0; i < count; ++i)
1067 mono_array_setref (*fields, i, values [i]);
1075 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1078 MonoObject **values = NULL;
1080 MonoClassField* field;
1084 MONO_ARCH_SAVE_REGS;
1086 MONO_CHECK_ARG_NULL (that);
1088 if (this->vtable != that->vtable)
1091 klass = mono_object_class (this);
1093 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1094 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1097 * Do the comparison for fields of primitive type and return a result if
1098 * possible. Otherwise, return the remaining fields in an array to the
1099 * managed side. This way, we can avoid costly reflection operations in
1104 while ((field = mono_class_get_fields (klass, &iter))) {
1105 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1107 if (mono_field_is_deleted (field))
1109 /* FIXME: Add more types */
1110 switch (field->type->type) {
1113 case MONO_TYPE_BOOLEAN:
1114 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1119 case MONO_TYPE_CHAR:
1120 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1125 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1130 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1134 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1138 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1143 case MONO_TYPE_STRING: {
1144 MonoString *s1, *s2;
1145 guint32 s1len, s2len;
1146 s1 = *(MonoString**)((guint8*)this + field->offset);
1147 s2 = *(MonoString**)((guint8*)that + field->offset);
1150 if ((s1 == NULL) || (s2 == NULL))
1152 s1len = mono_string_length (s1);
1153 s2len = mono_string_length (s2);
1157 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1163 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1164 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1165 values [count++] = o;
1166 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1167 values [count++] = o;
1170 if (klass->enumtype)
1171 /* enums only have one non-static field */
1177 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1178 for (i = 0; i < count; ++i)
1179 mono_array_setref (*fields, i, values [i]);
1186 static MonoReflectionType *
1187 ves_icall_System_Object_GetType (MonoObject *obj)
1189 MONO_ARCH_SAVE_REGS;
1191 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1192 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1194 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1198 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1200 MONO_ARCH_SAVE_REGS;
1202 mtype->type = &obj->vtable->klass->byval_arg;
1203 g_assert (mtype->type->type);
1207 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1209 MONO_ARCH_SAVE_REGS;
1211 MONO_CHECK_ARG_NULL (obj);
1213 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1217 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1218 MonoReflectionMethod *method,
1219 MonoArray *opt_param_types)
1221 MONO_ARCH_SAVE_REGS;
1223 MONO_CHECK_ARG_NULL (method);
1225 return mono_image_create_method_token (
1226 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1230 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1232 MONO_ARCH_SAVE_REGS;
1234 mono_image_create_pefile (mb, file);
1238 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1240 MONO_ARCH_SAVE_REGS;
1242 mono_image_build_metadata (mb);
1246 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1248 MONO_ARCH_SAVE_REGS;
1250 mono_image_register_token (mb->dynamic_image, token, obj);
1254 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1256 MonoMethod **dest = data;
1258 /* skip unmanaged frames */
1274 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1276 MonoMethod **dest = data;
1278 /* skip unmanaged frames */
1283 if (!strcmp (m->klass->name_space, "System.Reflection"))
1292 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1294 MonoMethod **dest = data;
1296 /* skip unmanaged frames */
1300 if (m->wrapper_type != MONO_WRAPPER_NONE)
1303 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1317 static MonoReflectionType *
1318 type_from_name (const char *str, MonoBoolean ignoreCase)
1320 MonoType *type = NULL;
1321 MonoAssembly *assembly = NULL;
1322 MonoTypeNameParse info;
1323 char *temp_str = g_strdup (str);
1324 gboolean type_resolve = FALSE;
1326 MONO_ARCH_SAVE_REGS;
1328 /* mono_reflection_parse_type() mangles the string */
1329 if (!mono_reflection_parse_type (temp_str, &info)) {
1330 mono_reflection_free_type_info (&info);
1335 if (info.assembly.name) {
1336 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1338 MonoMethod *m = mono_method_get_last_managed ();
1339 MonoMethod *dest = m;
1341 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1346 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1347 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1348 * to crash. This only seems to happen in some strange remoting
1349 * scenarios and I was unable to figure out what's happening there.
1350 * Dec 10, 2005 - Martin.
1354 assembly = dest->klass->image->assembly;
1355 type_resolve = TRUE;
1357 g_warning (G_STRLOC);
1362 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1363 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1366 if (!info.assembly.name && !type) /* try mscorlib */
1367 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1369 if (assembly && !type && type_resolve) {
1370 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1371 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1374 mono_reflection_free_type_info (&info);
1380 return mono_type_get_object (mono_domain_get (), type);
1384 MonoReflectionType *
1385 mono_type_get (const char *str)
1387 char *copy = g_strdup (str);
1388 MonoReflectionType *type = type_from_name (copy, FALSE);
1395 static MonoReflectionType*
1396 ves_icall_type_from_name (MonoString *name,
1397 MonoBoolean throwOnError,
1398 MonoBoolean ignoreCase)
1400 char *str = mono_string_to_utf8 (name);
1401 MonoReflectionType *type;
1403 type = type_from_name (str, ignoreCase);
1406 MonoException *e = NULL;
1409 e = mono_get_exception_type_load (name, NULL);
1411 mono_loader_clear_error ();
1413 mono_raise_exception (e);
1420 static MonoReflectionType*
1421 ves_icall_type_from_handle (MonoType *handle)
1423 MonoDomain *domain = mono_domain_get ();
1424 MonoClass *klass = mono_class_from_mono_type (handle);
1426 MONO_ARCH_SAVE_REGS;
1428 mono_class_init (klass);
1429 return mono_type_get_object (domain, handle);
1433 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1435 MONO_ARCH_SAVE_REGS;
1437 if (c && type->type && c->type)
1438 return mono_metadata_type_equal (type->type, c->type);
1440 return (type == c) ? TRUE : FALSE;
1443 /* System.TypeCode */
1462 TYPECODE_STRING = 18
1466 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1468 int t = type->type->type;
1470 MONO_ARCH_SAVE_REGS;
1472 if (type->type->byref)
1473 return TYPECODE_OBJECT;
1477 case MONO_TYPE_VOID:
1478 return TYPECODE_OBJECT;
1479 case MONO_TYPE_BOOLEAN:
1480 return TYPECODE_BOOLEAN;
1482 return TYPECODE_BYTE;
1484 return TYPECODE_SBYTE;
1486 return TYPECODE_UINT16;
1488 return TYPECODE_INT16;
1489 case MONO_TYPE_CHAR:
1490 return TYPECODE_CHAR;
1494 return TYPECODE_OBJECT;
1496 return TYPECODE_UINT32;
1498 return TYPECODE_INT32;
1500 return TYPECODE_UINT64;
1502 return TYPECODE_INT64;
1504 return TYPECODE_SINGLE;
1506 return TYPECODE_DOUBLE;
1507 case MONO_TYPE_VALUETYPE:
1508 if (type->type->data.klass->enumtype) {
1509 t = mono_class_enum_basetype (type->type->data.klass)->type;
1512 MonoClass *k = type->type->data.klass;
1513 if (strcmp (k->name_space, "System") == 0) {
1514 if (strcmp (k->name, "Decimal") == 0)
1515 return TYPECODE_DECIMAL;
1516 else if (strcmp (k->name, "DateTime") == 0)
1517 return TYPECODE_DATETIME;
1520 return TYPECODE_OBJECT;
1521 case MONO_TYPE_STRING:
1522 return TYPECODE_STRING;
1523 case MONO_TYPE_SZARRAY:
1524 case MONO_TYPE_ARRAY:
1525 case MONO_TYPE_OBJECT:
1527 case MONO_TYPE_MVAR:
1528 case MONO_TYPE_TYPEDBYREF:
1529 return TYPECODE_OBJECT;
1530 case MONO_TYPE_CLASS:
1532 MonoClass *k = type->type->data.klass;
1533 if (strcmp (k->name_space, "System") == 0) {
1534 if (strcmp (k->name, "DBNull") == 0)
1535 return TYPECODE_DBNULL;
1538 return TYPECODE_OBJECT;
1539 case MONO_TYPE_GENERICINST:
1540 return TYPECODE_OBJECT;
1542 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1548 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1554 MONO_ARCH_SAVE_REGS;
1556 g_assert (type != NULL);
1558 domain = ((MonoObject *)type)->vtable->domain;
1560 if (!c) /* FIXME: dont know what do do here */
1563 klass = mono_class_from_mono_type (type->type);
1564 klassc = mono_class_from_mono_type (c->type);
1566 if (type->type->byref)
1567 return klassc == mono_defaults.object_class;
1569 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1573 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1579 MONO_ARCH_SAVE_REGS;
1581 g_assert (type != NULL);
1583 domain = ((MonoObject *)type)->vtable->domain;
1585 klass = mono_class_from_mono_type (type->type);
1586 klassc = mono_class_from_mono_type (c->type);
1588 if (type->type->byref && !c->type->byref)
1591 return mono_class_is_assignable_from (klass, klassc);
1595 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1597 MonoClass *klass = mono_class_from_mono_type (type->type);
1598 return mono_object_isinst (obj, klass) != NULL;
1602 ves_icall_get_attributes (MonoReflectionType *type)
1604 MonoClass *klass = mono_class_from_mono_type (type->type);
1606 MONO_ARCH_SAVE_REGS;
1608 return klass->flags;
1611 static MonoReflectionMarshal*
1612 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1614 MonoClass *klass = field->field->parent;
1615 MonoMarshalType *info;
1618 if (klass->generic_container ||
1619 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1622 info = mono_marshal_load_type_info (klass);
1624 for (i = 0; i < info->num_fields; ++i) {
1625 if (info->fields [i].field == field->field) {
1626 if (!info->fields [i].mspec)
1629 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1636 static MonoReflectionField*
1637 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1639 gboolean found = FALSE;
1646 klass = handle->parent;
1648 klass = mono_class_from_mono_type (type);
1650 /* Check that the field belongs to the class */
1651 for (k = klass; k; k = k->parent) {
1652 if (k == handle->parent) {
1659 /* The managed code will throw the exception */
1663 return mono_field_get_object (mono_domain_get (), klass, handle);
1667 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1669 MonoType *type = field->field->type;
1671 return type_array_from_modifiers (field->field->parent->image, type, optional);
1675 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1677 MonoDomain *domain = mono_domain_get ();
1678 MonoMethodSignature* sig;
1679 MONO_ARCH_SAVE_REGS;
1681 sig = mono_method_signature (method);
1683 g_assert (mono_loader_get_last_error ());
1684 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1687 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1688 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1689 info->attrs = method->flags;
1690 info->implattrs = method->iflags;
1691 if (sig->call_convention == MONO_CALL_DEFAULT)
1692 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1694 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1699 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1703 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1705 MonoDomain *domain = mono_domain_get ();
1707 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1710 static MonoReflectionMarshal*
1711 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1713 MonoDomain *domain = mono_domain_get ();
1714 MonoReflectionMarshal* res = NULL;
1715 MonoMarshalSpec **mspecs;
1718 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1719 mono_method_get_marshal_info (method, mspecs);
1722 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1724 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1726 mono_metadata_free_marshal_spec (mspecs [i]);
1733 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1735 return field->field->offset - sizeof (MonoObject);
1738 static MonoReflectionType*
1739 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1742 MONO_ARCH_SAVE_REGS;
1744 parent = declaring? field->field->parent: field->klass;
1746 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1750 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1753 MonoClassField *cf = field->field;
1757 MonoDomain *domain = mono_object_domain (field);
1759 gboolean is_static = FALSE;
1760 gboolean is_ref = FALSE;
1762 MONO_ARCH_SAVE_REGS;
1764 if (field->klass->image->assembly->ref_only)
1765 mono_raise_exception (mono_get_exception_invalid_operation (
1766 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1768 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1769 mono_security_core_clr_ensure_reflection_access_field (cf);
1771 mono_class_init (field->klass);
1773 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1776 if (obj && !is_static) {
1777 /* Check that the field belongs to the object */
1778 gboolean found = FALSE;
1781 for (k = obj->vtable->klass; k; k = k->parent) {
1782 if (k == cf->parent) {
1789 char *msg = g_strdup_printf ("Field '%s' defined on type '%s' is not a field on the target object which is of type '%s'.", mono_field_get_name (cf), cf->parent->name, obj->vtable->klass->name);
1790 MonoException *ex = mono_get_exception_argument (NULL, msg);
1792 mono_raise_exception (ex);
1796 t = mono_type_get_underlying_type (cf->type);
1798 case MONO_TYPE_STRING:
1799 case MONO_TYPE_OBJECT:
1800 case MONO_TYPE_CLASS:
1801 case MONO_TYPE_ARRAY:
1802 case MONO_TYPE_SZARRAY:
1807 case MONO_TYPE_BOOLEAN:
1810 case MONO_TYPE_CHAR:
1819 case MONO_TYPE_VALUETYPE:
1822 case MONO_TYPE_GENERICINST:
1823 if (mono_type_generic_inst_is_valuetype (t)) {
1830 g_error ("type 0x%x not handled in "
1831 "ves_icall_Monofield_GetValue", t->type);
1837 vtable = mono_class_vtable_full (domain, cf->parent, TRUE);
1838 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1839 mono_runtime_class_init (vtable);
1844 mono_field_static_get_value (vtable, cf, &o);
1846 mono_field_get_value (obj, cf, &o);
1851 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1852 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1855 /* Convert the Nullable structure into a boxed vtype */
1857 buf = (guint8*)vtable->data + cf->offset;
1859 buf = (guint8*)obj + cf->offset;
1861 return mono_nullable_box (buf, nklass);
1864 /* boxed value type */
1865 klass = mono_class_from_mono_type (cf->type);
1866 o = mono_object_new (domain, klass);
1867 v = ((gchar *) o) + sizeof (MonoObject);
1869 mono_field_static_get_value (vtable, cf, v);
1871 mono_field_get_value (obj, cf, v);
1878 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1880 MonoClassField *cf = field->field;
1883 MONO_ARCH_SAVE_REGS;
1885 if (field->klass->image->assembly->ref_only)
1886 mono_raise_exception (mono_get_exception_invalid_operation (
1887 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1889 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1890 mono_security_core_clr_ensure_reflection_access_field (cf);
1892 v = (gchar *) value;
1893 if (!cf->type->byref) {
1894 switch (cf->type->type) {
1897 case MONO_TYPE_BOOLEAN:
1900 case MONO_TYPE_CHAR:
1909 case MONO_TYPE_VALUETYPE:
1911 v += sizeof (MonoObject);
1913 case MONO_TYPE_STRING:
1914 case MONO_TYPE_OBJECT:
1915 case MONO_TYPE_CLASS:
1916 case MONO_TYPE_ARRAY:
1917 case MONO_TYPE_SZARRAY:
1920 case MONO_TYPE_GENERICINST: {
1921 MonoGenericClass *gclass = cf->type->data.generic_class;
1922 g_assert (!gclass->context.class_inst->is_open);
1924 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1925 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1926 MonoObject *nullable;
1929 * Convert the boxed vtype into a Nullable structure.
1930 * This is complicated by the fact that Nullables have
1931 * a variable structure.
1933 nullable = mono_object_new (mono_domain_get (), nklass);
1935 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1937 v = mono_object_unbox (nullable);
1940 if (gclass->container_class->valuetype && (v != NULL))
1941 v += sizeof (MonoObject);
1945 g_error ("type 0x%x not handled in "
1946 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1951 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1952 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1953 if (!vtable->initialized)
1954 mono_runtime_class_init (vtable);
1955 mono_field_static_set_value (vtable, cf, v);
1957 mono_field_set_value (obj, cf, v);
1962 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1964 MonoObject *o = NULL;
1965 MonoClassField *field = this->field;
1967 MonoDomain *domain = mono_object_domain (this);
1969 MonoTypeEnum def_type;
1970 const char *def_value;
1972 MONO_ARCH_SAVE_REGS;
1974 mono_class_init (field->parent);
1976 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1977 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1979 if (field->parent->image->dynamic) {
1981 g_assert_not_reached ();
1984 def_value = mono_class_get_field_default_value (field, &def_type);
1986 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1990 case MONO_TYPE_BOOLEAN:
1993 case MONO_TYPE_CHAR:
2001 case MONO_TYPE_R8: {
2004 /* boxed value type */
2005 t = g_new0 (MonoType, 1);
2007 klass = mono_class_from_mono_type (t);
2009 o = mono_object_new (domain, klass);
2010 v = ((gchar *) o) + sizeof (MonoObject);
2011 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
2014 case MONO_TYPE_STRING:
2015 case MONO_TYPE_CLASS:
2016 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
2019 g_assert_not_reached ();
2025 static MonoReflectionType*
2026 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
2028 MonoMethod *method = rmethod->method.method;
2030 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
2033 /* From MonoProperty.cs */
2035 PInfo_Attributes = 1,
2036 PInfo_GetMethod = 1 << 1,
2037 PInfo_SetMethod = 1 << 2,
2038 PInfo_ReflectedType = 1 << 3,
2039 PInfo_DeclaringType = 1 << 4,
2044 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2046 MonoDomain *domain = mono_object_domain (property);
2048 MONO_ARCH_SAVE_REGS;
2050 if ((req_info & PInfo_ReflectedType) != 0)
2051 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2052 else if ((req_info & PInfo_DeclaringType) != 0)
2053 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2055 if ((req_info & PInfo_Name) != 0)
2056 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2058 if ((req_info & PInfo_Attributes) != 0)
2059 info->attrs = property->property->attrs;
2061 if ((req_info & PInfo_GetMethod) != 0)
2062 MONO_STRUCT_SETREF (info, get, property->property->get ?
2063 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2065 if ((req_info & PInfo_SetMethod) != 0)
2066 MONO_STRUCT_SETREF (info, set, property->property->set ?
2067 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2069 * There may be other methods defined for properties, though, it seems they are not exposed
2070 * in the reflection API
2075 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2077 MonoDomain *domain = mono_object_domain (event);
2079 MONO_ARCH_SAVE_REGS;
2081 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2082 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2084 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2085 info->attrs = event->event->attrs;
2086 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2087 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2088 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2090 #ifndef MONO_SMALL_CONFIG
2091 if (event->event->other) {
2093 while (event->event->other [n])
2095 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2097 for (i = 0; i < n; i++)
2098 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2104 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2107 MonoDomain *domain = mono_object_domain (type);
2109 GPtrArray *ifaces = NULL;
2111 MonoClass *class = mono_class_from_mono_type (type->type);
2114 MonoGenericContext *context = NULL;
2116 MONO_ARCH_SAVE_REGS;
2118 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2119 context = mono_class_get_context (class);
2120 class = class->generic_class->container_class;
2123 mono_class_setup_vtable (class);
2125 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2127 for (parent = class; parent; parent = parent->parent) {
2128 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent, &error);
2129 if (!mono_error_ok (&error)) {
2130 mono_bitset_free (slots);
2131 mono_error_raise_exception (&error);
2133 } else if (tmp_ifaces) {
2134 for (i = 0; i < tmp_ifaces->len; ++i) {
2135 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2137 if (mono_bitset_test (slots, ic->interface_id))
2140 mono_bitset_set (slots, ic->interface_id);
2142 ifaces = g_ptr_array_new ();
2143 g_ptr_array_add (ifaces, ic);
2145 g_ptr_array_free (tmp_ifaces, TRUE);
2148 mono_bitset_free (slots);
2151 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2153 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2154 for (i = 0; i < ifaces->len; ++i) {
2155 MonoClass *ic = g_ptr_array_index (ifaces, i);
2156 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2157 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2158 inflated = ret = mono_class_inflate_generic_type (ret, context);
2160 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2162 mono_metadata_free_type (inflated);
2164 g_ptr_array_free (ifaces, TRUE);
2170 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2172 gboolean variance_used;
2173 MonoClass *class = mono_class_from_mono_type (type->type);
2174 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2175 MonoReflectionMethod *member;
2178 int i = 0, len, ioffset;
2181 MONO_ARCH_SAVE_REGS;
2183 mono_class_setup_vtable (class);
2185 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2189 len = mono_class_num_methods (iclass);
2190 domain = mono_object_domain (type);
2191 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2192 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2194 while ((method = mono_class_get_methods (iclass, &iter))) {
2195 member = mono_method_get_object (domain, method, iclass);
2196 mono_array_setref (*methods, i, member);
2197 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2198 mono_array_setref (*targets, i, member);
2205 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2207 MonoClass *klass = mono_class_from_mono_type (type->type);
2209 if (klass->image->dynamic) {
2210 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2211 *packing = tb->packing_size;
2212 *size = tb->class_size;
2214 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2218 static MonoReflectionType*
2219 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2223 MONO_ARCH_SAVE_REGS;
2225 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2226 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2228 class = mono_class_from_mono_type (type->type);
2230 // GetElementType should only return a type for:
2231 // Array Pointer PassedByRef
2232 if (type->type->byref)
2233 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2234 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2235 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2236 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2237 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2242 static MonoReflectionType*
2243 ves_icall_get_type_parent (MonoReflectionType *type)
2245 MonoClass *class = mono_class_from_mono_type (type->type);
2247 MONO_ARCH_SAVE_REGS;
2249 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2253 ves_icall_type_ispointer (MonoReflectionType *type)
2255 MONO_ARCH_SAVE_REGS;
2257 return type->type->type == MONO_TYPE_PTR;
2261 ves_icall_type_isprimitive (MonoReflectionType *type)
2263 MONO_ARCH_SAVE_REGS;
2265 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)));
2269 ves_icall_type_isbyref (MonoReflectionType *type)
2271 MONO_ARCH_SAVE_REGS;
2273 return type->type->byref;
2277 ves_icall_type_iscomobject (MonoReflectionType *type)
2279 MonoClass *klass = mono_class_from_mono_type (type->type);
2280 MONO_ARCH_SAVE_REGS;
2282 return (klass && klass->is_com_object);
2285 static MonoReflectionModule*
2286 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2288 MonoClass *class = mono_class_from_mono_type (type->type);
2290 MONO_ARCH_SAVE_REGS;
2292 return mono_module_get_object (mono_object_domain (type), class->image);
2295 static MonoReflectionAssembly*
2296 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2298 MonoDomain *domain = mono_domain_get ();
2299 MonoClass *class = mono_class_from_mono_type (type->type);
2301 MONO_ARCH_SAVE_REGS;
2303 return mono_assembly_get_object (domain, class->image->assembly);
2306 static MonoReflectionType*
2307 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2309 MonoDomain *domain = mono_domain_get ();
2312 MONO_ARCH_SAVE_REGS;
2314 if (type->type->byref)
2316 if (type->type->type == MONO_TYPE_VAR)
2317 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2318 else if (type->type->type == MONO_TYPE_MVAR)
2319 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2321 class = mono_class_from_mono_type (type->type)->nested_in;
2323 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2326 static MonoReflectionType*
2327 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2329 MonoDomain *domain = mono_domain_get ();
2330 MonoClass *class = mono_class_from_mono_type (type->type);
2332 MONO_ARCH_SAVE_REGS;
2334 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2335 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2336 else if (class->element_class)
2337 return mono_type_get_object (domain, &class->element_class->byval_arg);
2343 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2345 MonoDomain *domain = mono_domain_get ();
2346 MonoClass *class = mono_class_from_mono_type (type->type);
2348 MONO_ARCH_SAVE_REGS;
2350 if (type->type->byref) {
2351 char *n = g_strdup_printf ("%s&", class->name);
2352 MonoString *res = mono_string_new (domain, n);
2358 return mono_string_new (domain, class->name);
2363 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2365 MonoDomain *domain = mono_domain_get ();
2366 MonoClass *class = mono_class_from_mono_type (type->type);
2368 MONO_ARCH_SAVE_REGS;
2370 while (class->nested_in)
2371 class = class->nested_in;
2373 if (class->name_space [0] == '\0')
2376 return mono_string_new (domain, class->name_space);
2380 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2384 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2385 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2387 class = mono_class_from_mono_type (type->type);
2392 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2395 MonoClass *klass, *pklass;
2396 MonoDomain *domain = mono_object_domain (type);
2397 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2399 MONO_ARCH_SAVE_REGS;
2401 klass = mono_class_from_mono_type (type->type);
2403 if (klass->generic_container) {
2404 MonoGenericContainer *container = klass->generic_container;
2405 res = mono_array_new_specific (array_vtable, container->type_argc);
2406 for (i = 0; i < container->type_argc; ++i) {
2407 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2408 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2410 } else if (klass->generic_class) {
2411 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2412 res = mono_array_new_specific (array_vtable, inst->type_argc);
2413 for (i = 0; i < inst->type_argc; ++i)
2414 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2416 res = mono_array_new_specific (array_vtable, 0);
2422 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2425 MONO_ARCH_SAVE_REGS;
2427 if (!IS_MONOTYPE (type))
2430 if (type->type->byref)
2433 klass = mono_class_from_mono_type (type->type);
2435 return klass->generic_container != NULL;
2438 static MonoReflectionType*
2439 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2442 MONO_ARCH_SAVE_REGS;
2444 if (type->type->byref)
2447 klass = mono_class_from_mono_type (type->type);
2448 if (klass->generic_container) {
2449 return type; /* check this one */
2451 if (klass->generic_class) {
2452 MonoClass *generic_class = klass->generic_class->container_class;
2455 tb = mono_class_get_ref_info (generic_class);
2457 if (generic_class->wastypebuilder && tb)
2460 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2465 static MonoReflectionType*
2466 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2468 MonoType *geninst, **types;
2471 MONO_ARCH_SAVE_REGS;
2473 count = mono_array_length (type_array);
2474 types = g_new0 (MonoType *, count);
2476 for (i = 0; i < count; i++) {
2477 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2478 types [i] = t->type;
2481 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2486 return mono_type_get_object (mono_object_domain (type), geninst);
2490 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2493 MONO_ARCH_SAVE_REGS;
2495 if (type->type->byref)
2498 klass = mono_class_from_mono_type (type->type);
2499 return klass->generic_class != NULL;
2503 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2506 MONO_ARCH_SAVE_REGS;
2508 if (!IS_MONOTYPE (type))
2511 if (type->type->byref)
2514 klass = mono_class_from_mono_type (type->type);
2515 return klass->generic_class != NULL || klass->generic_container != NULL;
2519 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2521 MONO_ARCH_SAVE_REGS;
2523 if (!IS_MONOTYPE (type))
2526 if (is_generic_parameter (type->type))
2527 return mono_type_get_generic_param_num (type->type);
2531 static GenericParameterAttributes
2532 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2534 MONO_ARCH_SAVE_REGS;
2536 g_assert (IS_MONOTYPE (type));
2537 g_assert (is_generic_parameter (type->type));
2538 return mono_generic_param_info (type->type->data.generic_param)->flags;
2542 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2544 MonoGenericParamInfo *param_info;
2550 MONO_ARCH_SAVE_REGS;
2552 g_assert (IS_MONOTYPE (type));
2554 domain = mono_object_domain (type);
2555 param_info = mono_generic_param_info (type->type->data.generic_param);
2556 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2559 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2560 for (i = 0; i < count; i++)
2561 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2568 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2570 MONO_ARCH_SAVE_REGS;
2571 return is_generic_parameter (type->type);
2575 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2577 MONO_ARCH_SAVE_REGS;
2578 return is_generic_parameter (tb->type.type);
2582 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2583 MonoReflectionType *t)
2585 enumtype->type = t->type;
2588 static MonoReflectionMethod*
2589 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2590 MonoReflectionMethod* generic)
2597 MONO_ARCH_SAVE_REGS;
2599 domain = ((MonoObject *)type)->vtable->domain;
2601 klass = mono_class_from_mono_type (type->type);
2604 while ((method = mono_class_get_methods (klass, &iter))) {
2605 if (method->token == generic->method->token)
2606 return mono_method_get_object (domain, method, klass);
2614 static MonoReflectionMethod *
2615 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2618 MonoType *type = ref_type->type;
2620 MONO_ARCH_SAVE_REGS;
2622 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2623 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2624 if (type->type == MONO_TYPE_VAR)
2627 method = mono_type_get_generic_param_owner (type)->owner.method;
2629 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2632 static MonoReflectionDllImportAttribute*
2633 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2635 static MonoClass *DllImportAttributeClass = NULL;
2636 MonoDomain *domain = mono_domain_get ();
2637 MonoReflectionDllImportAttribute *attr;
2638 MonoImage *image = method->klass->image;
2639 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2640 MonoTableInfo *tables = image->tables;
2641 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2642 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2643 guint32 im_cols [MONO_IMPLMAP_SIZE];
2644 guint32 scope_token;
2645 const char *import = NULL;
2646 const char *scope = NULL;
2649 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2652 if (!DllImportAttributeClass) {
2653 DllImportAttributeClass =
2654 mono_class_from_name (mono_defaults.corlib,
2655 "System.Runtime.InteropServices", "DllImportAttribute");
2656 g_assert (DllImportAttributeClass);
2659 if (method->klass->image->dynamic) {
2660 MonoReflectionMethodAux *method_aux =
2661 g_hash_table_lookup (
2662 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2664 import = method_aux->dllentry;
2665 scope = method_aux->dll;
2668 if (!import || !scope) {
2669 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2674 if (piinfo->implmap_idx) {
2675 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2677 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2678 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2679 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2680 scope = mono_metadata_string_heap (image, scope_token);
2683 flags = piinfo->piflags;
2685 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2687 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2688 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2689 attr->call_conv = (flags & 0x700) >> 8;
2690 attr->charset = ((flags & 0x6) >> 1) + 1;
2691 if (attr->charset == 1)
2693 attr->exact_spelling = (flags & 0x1) != 0;
2694 attr->set_last_error = (flags & 0x40) != 0;
2695 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2696 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2697 attr->preserve_sig = FALSE;
2702 static MonoReflectionMethod *
2703 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2705 MonoMethodInflated *imethod;
2708 MONO_ARCH_SAVE_REGS;
2710 if (method->method->is_generic)
2713 if (!method->method->is_inflated)
2716 imethod = (MonoMethodInflated *) method->method;
2718 result = imethod->declaring;
2719 /* Not a generic method. */
2720 if (!result->is_generic)
2723 if (method->method->klass->image->dynamic) {
2724 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2725 MonoReflectionMethod *res;
2728 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2729 * the dynamic case as well ?
2731 mono_loader_lock ();
2732 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2733 mono_loader_unlock ();
2739 if (imethod->context.class_inst) {
2740 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2741 /*Generic methods gets the context of the GTD.*/
2742 if (mono_class_get_context (klass))
2743 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2746 return mono_method_get_object (mono_object_domain (method), result, NULL);
2750 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2752 MONO_ARCH_SAVE_REGS;
2754 return mono_method_signature (method->method)->generic_param_count != 0;
2758 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2760 MONO_ARCH_SAVE_REGS;
2762 return method->method->is_generic;
2766 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2771 MONO_ARCH_SAVE_REGS;
2773 domain = mono_object_domain (method);
2775 if (method->method->is_inflated) {
2776 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2779 count = inst->type_argc;
2780 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2782 for (i = 0; i < count; i++)
2783 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2789 count = mono_method_signature (method->method)->generic_param_count;
2790 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2792 for (i = 0; i < count; i++) {
2793 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2794 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2795 MonoClass *pklass = mono_class_from_generic_parameter (
2796 param, method->method->klass->image, TRUE);
2797 mono_array_setref (res, i,
2798 mono_type_get_object (domain, &pklass->byval_arg));
2805 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2808 * Invoke from reflection is supposed to always be a virtual call (the API
2809 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2810 * greater flexibility.
2812 MonoMethod *m = method->method;
2816 MONO_ARCH_SAVE_REGS;
2820 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2821 mono_security_core_clr_ensure_reflection_access_method (m);
2823 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2825 if (!mono_object_isinst (this, m->klass)) {
2826 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2829 m = mono_object_get_virtual_method (this, m);
2830 /* must pass the pointer to the value for valuetype methods */
2831 if (m->klass->valuetype)
2832 obj = mono_object_unbox (this);
2833 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2834 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2839 pcount = params? mono_array_length (params): 0;
2840 if (pcount != mono_method_signature (m)->param_count) {
2841 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2845 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2846 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."));
2850 if (m->klass->image->assembly->ref_only) {
2851 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."));
2855 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2858 intptr_t *lower_bounds;
2859 pcount = mono_array_length (params);
2860 lengths = alloca (sizeof (uintptr_t) * pcount);
2861 /* Note: the synthetized array .ctors have int32 as argument type */
2862 for (i = 0; i < pcount; ++i)
2863 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2865 if (m->klass->rank == pcount) {
2866 /* Only lengths provided. */
2867 lower_bounds = NULL;
2869 g_assert (pcount == (m->klass->rank * 2));
2870 /* lower bounds are first. */
2871 lower_bounds = (intptr_t*)lengths;
2872 lengths += m->klass->rank;
2875 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2877 return mono_runtime_invoke_array (m, obj, params, NULL);
2881 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2883 MonoDomain *domain = mono_object_domain (method);
2884 MonoMethod *m = method->method;
2885 MonoMethodSignature *sig = mono_method_signature (m);
2886 MonoArray *out_args;
2888 int i, j, outarg_count = 0;
2890 MONO_ARCH_SAVE_REGS;
2892 if (m->klass == mono_defaults.object_class) {
2894 if (!strcmp (m->name, "FieldGetter")) {
2895 MonoClass *k = this->vtable->klass;
2899 /* If this is a proxy, then it must be a CBO */
2900 if (k == mono_defaults.transparent_proxy_class) {
2901 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2902 this = tp->rp->unwrapped_server;
2904 k = this->vtable->klass;
2907 name = mono_array_get (params, MonoString *, 1);
2908 str = mono_string_to_utf8 (name);
2911 MonoClassField* field = mono_class_get_field_from_name (k, str);
2913 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2914 if (field_klass->valuetype)
2915 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2917 result = *((gpointer *)((char *)this + field->offset));
2919 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2920 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2921 mono_array_setref (out_args, 0, result);
2929 g_assert_not_reached ();
2931 } else if (!strcmp (m->name, "FieldSetter")) {
2932 MonoClass *k = this->vtable->klass;
2938 /* If this is a proxy, then it must be a CBO */
2939 if (k == mono_defaults.transparent_proxy_class) {
2940 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2941 this = tp->rp->unwrapped_server;
2943 k = this->vtable->klass;
2946 name = mono_array_get (params, MonoString *, 1);
2947 str = mono_string_to_utf8 (name);
2950 MonoClassField* field = mono_class_get_field_from_name (k, str);
2952 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2953 MonoObject *val = mono_array_get (params, gpointer, 2);
2955 if (field_klass->valuetype) {
2956 size = mono_type_size (field->type, &align);
2957 g_assert (size == mono_class_value_size (field_klass, NULL));
2958 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2960 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2963 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2964 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2974 g_assert_not_reached ();
2979 for (i = 0; i < mono_array_length (params); i++) {
2980 if (sig->params [i]->byref)
2984 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2986 /* handle constructors only for objects already allocated */
2987 if (!strcmp (method->method->name, ".ctor"))
2990 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2991 g_assert (!method->method->klass->valuetype);
2992 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2994 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2995 if (sig->params [i]->byref) {
2997 arg = mono_array_get (params, gpointer, i);
2998 mono_array_setref (out_args, j, arg);
3003 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3009 read_enum_value (char *mem, int type)
3013 return *(guint8*)mem;
3015 return *(gint8*)mem;
3017 return *(guint16*)mem;
3019 return *(gint16*)mem;
3021 return *(guint32*)mem;
3023 return *(gint32*)mem;
3025 return *(guint64*)mem;
3027 return *(gint64*)mem;
3029 g_assert_not_reached ();
3035 write_enum_value (char *mem, int type, guint64 value)
3039 case MONO_TYPE_I1: {
3040 guint8 *p = (guint8*)mem;
3045 case MONO_TYPE_I2: {
3046 guint16 *p = (void*)mem;
3051 case MONO_TYPE_I4: {
3052 guint32 *p = (void*)mem;
3057 case MONO_TYPE_I8: {
3058 guint64 *p = (void*)mem;
3063 g_assert_not_reached ();
3069 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3072 MonoClass *enumc, *objc;
3076 MONO_ARCH_SAVE_REGS;
3078 MONO_CHECK_ARG_NULL (enumType);
3079 MONO_CHECK_ARG_NULL (value);
3081 domain = mono_object_domain (enumType);
3082 enumc = mono_class_from_mono_type (enumType->type);
3083 objc = value->vtable->klass;
3085 if (!enumc->enumtype)
3086 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3087 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3088 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."));
3090 res = mono_object_new (domain, enumc);
3091 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3092 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3098 ves_icall_System_Enum_get_value (MonoObject *this)
3106 MONO_ARCH_SAVE_REGS;
3111 g_assert (this->vtable->klass->enumtype);
3113 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3114 res = mono_object_new (mono_object_domain (this), enumc);
3115 dst = (char *)res + sizeof (MonoObject);
3116 src = (char *)this + sizeof (MonoObject);
3117 size = mono_class_value_size (enumc, NULL);
3119 memcpy (dst, src, size);
3124 static MonoReflectionType *
3125 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3129 MONO_ARCH_SAVE_REGS;
3131 etype = mono_class_enum_basetype (mono_class_from_mono_type (type->type));
3133 /* MS throws this for typebuilders */
3134 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3136 return mono_type_get_object (mono_object_domain (type), etype);
3140 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3142 gpointer tdata = (char *)this + sizeof (MonoObject);
3143 gpointer odata = (char *)other + sizeof (MonoObject);
3144 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3145 g_assert (basetype);
3147 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3148 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3149 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3152 return me > other ? 1 : -1; \
3155 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3156 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3157 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3160 return me - other; \
3163 switch (basetype->type) {
3165 COMPARE_ENUM_VALUES (guint8);
3167 COMPARE_ENUM_VALUES (gint8);
3168 case MONO_TYPE_CHAR:
3170 COMPARE_ENUM_VALUES_RANGE (guint16);
3172 COMPARE_ENUM_VALUES (gint16);
3174 COMPARE_ENUM_VALUES (guint32);
3176 COMPARE_ENUM_VALUES (gint32);
3178 COMPARE_ENUM_VALUES (guint64);
3180 COMPARE_ENUM_VALUES (gint64);
3182 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3184 #undef COMPARE_ENUM_VALUES_RANGE
3185 #undef COMPARE_ENUM_VALUES
3190 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3192 gpointer data = (char *)this + sizeof (MonoObject);
3193 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3194 g_assert (basetype);
3196 switch (basetype->type) {
3198 return *((gint8*)data);
3200 return *((guint8*)data);
3201 case MONO_TYPE_CHAR:
3203 return *((guint16*)data);
3206 return *((gint16*)data);
3208 return *((guint32*)data);
3210 return *((gint32*)data);
3212 case MONO_TYPE_I8: {
3213 gint64 value = *((gint64*)data);
3214 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3217 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3223 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3225 MonoDomain *domain = mono_object_domain (type);
3226 MonoClass *enumc = mono_class_from_mono_type (type->type);
3227 guint j = 0, nvalues, crow;
3229 MonoClassField *field;
3231 MONO_ARCH_SAVE_REGS;
3233 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3234 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3235 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3236 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3240 while ((field = mono_class_get_fields (enumc, &iter))) {
3243 MonoTypeEnum def_type;
3245 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3247 if (mono_field_is_deleted (field))
3249 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3251 p = mono_class_get_field_default_value (field, &def_type);
3252 len = mono_metadata_decode_blob_size (p, &p);
3253 switch (mono_class_enum_basetype (enumc)->type) {
3256 mono_array_set (info->values, gchar, j, *p);
3258 case MONO_TYPE_CHAR:
3261 mono_array_set (info->values, gint16, j, read16 (p));
3265 mono_array_set (info->values, gint32, j, read32 (p));
3269 mono_array_set (info->values, gint64, j, read64 (p));
3272 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3279 BFLAGS_IgnoreCase = 1,
3280 BFLAGS_DeclaredOnly = 2,
3281 BFLAGS_Instance = 4,
3283 BFLAGS_Public = 0x10,
3284 BFLAGS_NonPublic = 0x20,
3285 BFLAGS_FlattenHierarchy = 0x40,
3286 BFLAGS_InvokeMethod = 0x100,
3287 BFLAGS_CreateInstance = 0x200,
3288 BFLAGS_GetField = 0x400,
3289 BFLAGS_SetField = 0x800,
3290 BFLAGS_GetProperty = 0x1000,
3291 BFLAGS_SetProperty = 0x2000,
3292 BFLAGS_ExactBinding = 0x10000,
3293 BFLAGS_SuppressChangeType = 0x20000,
3294 BFLAGS_OptionalParamBinding = 0x40000
3297 static MonoReflectionField *
3298 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3301 MonoClass *startklass, *klass;
3303 MonoClassField *field;
3306 int (*compare_func) (const char *s1, const char *s2) = NULL;
3307 domain = ((MonoObject *)type)->vtable->domain;
3308 klass = startklass = mono_class_from_mono_type (type->type);
3310 MONO_ARCH_SAVE_REGS;
3313 mono_raise_exception (mono_get_exception_argument_null ("name"));
3314 if (type->type->byref)
3317 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3320 if (klass->exception_type != MONO_EXCEPTION_NONE)
3321 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3324 while ((field = mono_class_get_fields (klass, &iter))) {
3327 if (field->type == NULL)
3329 if (mono_field_is_deleted (field))
3331 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3332 if (bflags & BFLAGS_Public)
3334 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3335 if (bflags & BFLAGS_NonPublic) {
3342 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3343 if (bflags & BFLAGS_Static)
3344 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3347 if (bflags & BFLAGS_Instance)
3354 utf8_name = mono_string_to_utf8 (name);
3356 if (compare_func (mono_field_get_name (field), utf8_name)) {
3362 return mono_field_get_object (domain, klass, field);
3364 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3371 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3374 MonoClass *startklass, *klass, *refklass;
3379 MonoClassField *field;
3380 MonoPtrArray tmp_array;
3382 MONO_ARCH_SAVE_REGS;
3384 domain = ((MonoObject *)type)->vtable->domain;
3385 if (type->type->byref)
3386 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3387 klass = startklass = mono_class_from_mono_type (type->type);
3388 refklass = mono_class_from_mono_type (reftype->type);
3390 mono_ptr_array_init (tmp_array, 2);
3393 if (klass->exception_type != MONO_EXCEPTION_NONE)
3394 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3397 while ((field = mono_class_get_fields (klass, &iter))) {
3399 if (mono_field_is_deleted (field))
3401 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3402 if (bflags & BFLAGS_Public)
3404 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3405 if (bflags & BFLAGS_NonPublic) {
3412 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3413 if (bflags & BFLAGS_Static)
3414 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3417 if (bflags & BFLAGS_Instance)
3423 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3424 mono_ptr_array_append (tmp_array, member);
3426 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3429 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3431 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3432 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3434 mono_ptr_array_destroy (tmp_array);
3440 method_nonpublic (MonoMethod* method, gboolean start_klass)
3442 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3443 case METHOD_ATTRIBUTE_ASSEM:
3444 return (start_klass || mono_defaults.generic_ilist_class);
3445 case METHOD_ATTRIBUTE_PRIVATE:
3447 case METHOD_ATTRIBUTE_PUBLIC:
3455 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3457 static MonoClass *MethodInfo_array;
3459 MonoClass *startklass, *klass, *refklass;
3464 int i, len, match, nslots;
3465 /*FIXME, use MonoBitSet*/
3466 guint32 method_slots_default [8];
3467 guint32 *method_slots = NULL;
3468 gchar *mname = NULL;
3469 int (*compare_func) (const char *s1, const char *s2) = NULL;
3470 MonoVTable *array_vtable;
3472 MonoPtrArray tmp_array;
3474 MONO_ARCH_SAVE_REGS;
3476 mono_ptr_array_init (tmp_array, 4);
3478 if (!MethodInfo_array) {
3479 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3480 mono_memory_barrier ();
3481 MethodInfo_array = klass;
3484 domain = ((MonoObject *)type)->vtable->domain;
3485 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3486 if (type->type->byref)
3487 return mono_array_new_specific (array_vtable, 0);
3488 klass = startklass = mono_class_from_mono_type (type->type);
3489 refklass = mono_class_from_mono_type (reftype->type);
3492 mname = mono_string_to_utf8 (name);
3493 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3496 /* An optimization for calls made from Delegate:CreateDelegate () */
3497 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3498 method = mono_get_delegate_invoke (klass);
3499 if (mono_loader_get_last_error ())
3502 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3504 res = mono_array_new_specific (array_vtable, 1);
3505 mono_array_setref (res, 0, member);
3510 mono_class_setup_vtable (klass);
3511 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3514 if (is_generic_parameter (type->type))
3515 nslots = mono_class_get_vtable_size (klass->parent);
3517 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3518 if (nslots >= sizeof (method_slots_default) * 8) {
3519 method_slots = g_new0 (guint32, nslots / 32 + 1);
3521 method_slots = method_slots_default;
3522 memset (method_slots, 0, sizeof (method_slots_default));
3525 mono_class_setup_vtable (klass);
3526 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3530 while ((method = mono_class_get_methods (klass, &iter))) {
3532 if (method->slot != -1) {
3533 g_assert (method->slot < nslots);
3534 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3536 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3537 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3540 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3542 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3543 if (bflags & BFLAGS_Public)
3545 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3551 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3552 if (bflags & BFLAGS_Static)
3553 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3556 if (bflags & BFLAGS_Instance)
3564 if (compare_func (mname, method->name))
3570 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3572 mono_ptr_array_append (tmp_array, member);
3574 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3578 if (method_slots != method_slots_default)
3579 g_free (method_slots);
3581 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3583 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3584 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3586 mono_ptr_array_destroy (tmp_array);
3591 if (method_slots != method_slots_default)
3592 g_free (method_slots);
3593 mono_ptr_array_destroy (tmp_array);
3594 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3595 ex = mono_class_get_exception_for_failure (klass);
3597 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3598 mono_loader_clear_error ();
3600 mono_raise_exception (ex);
3605 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3608 static MonoClass *System_Reflection_ConstructorInfo;
3609 MonoClass *startklass, *klass, *refklass;
3614 gpointer iter = NULL;
3615 MonoPtrArray tmp_array;
3617 MONO_ARCH_SAVE_REGS;
3619 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3621 domain = ((MonoObject *)type)->vtable->domain;
3622 if (type->type->byref)
3623 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3624 klass = startklass = mono_class_from_mono_type (type->type);
3625 refklass = mono_class_from_mono_type (reftype->type);
3627 if (klass->exception_type != MONO_EXCEPTION_NONE)
3628 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3630 if (!System_Reflection_ConstructorInfo)
3631 System_Reflection_ConstructorInfo = mono_class_from_name (
3632 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3635 while ((method = mono_class_get_methods (klass, &iter))) {
3637 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3639 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3640 if (bflags & BFLAGS_Public)
3643 if (bflags & BFLAGS_NonPublic)
3649 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3650 if (bflags & BFLAGS_Static)
3651 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3654 if (bflags & BFLAGS_Instance)
3660 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3662 mono_ptr_array_append (tmp_array, member);
3665 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3667 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3668 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3670 mono_ptr_array_destroy (tmp_array);
3676 property_hash (gconstpointer data)
3678 MonoProperty *prop = (MonoProperty*)data;
3680 return g_str_hash (prop->name);
3684 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3686 // Properties are hide-by-name-and-signature
3687 if (!g_str_equal (prop1->name, prop2->name))
3690 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3692 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3698 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3703 return method_nonpublic (accessor, start_klass);
3707 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3710 static MonoClass *System_Reflection_PropertyInfo;
3711 MonoClass *startklass, *klass;
3717 gchar *propname = NULL;
3718 int (*compare_func) (const char *s1, const char *s2) = NULL;
3720 GHashTable *properties;
3721 MonoPtrArray tmp_array;
3723 MONO_ARCH_SAVE_REGS;
3725 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3727 if (!System_Reflection_PropertyInfo)
3728 System_Reflection_PropertyInfo = mono_class_from_name (
3729 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3731 domain = ((MonoObject *)type)->vtable->domain;
3732 if (type->type->byref)
3733 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3734 klass = startklass = mono_class_from_mono_type (type->type);
3736 propname = mono_string_to_utf8 (name);
3737 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3740 mono_class_setup_vtable (klass);
3742 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3744 mono_class_setup_vtable (klass);
3745 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3746 g_hash_table_destroy (properties);
3749 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3753 while ((prop = mono_class_get_properties (klass, &iter))) {
3759 flags = method->flags;
3762 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3763 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3764 if (bflags & BFLAGS_Public)
3766 } else if (bflags & BFLAGS_NonPublic) {
3767 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3768 property_accessor_nonpublic(prop->set, startklass == klass)) {
3775 if (flags & METHOD_ATTRIBUTE_STATIC) {
3776 if (bflags & BFLAGS_Static)
3777 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3780 if (bflags & BFLAGS_Instance)
3789 if (compare_func (propname, prop->name))
3793 if (g_hash_table_lookup (properties, prop))
3796 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3798 g_hash_table_insert (properties, prop, prop);
3800 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3803 g_hash_table_destroy (properties);
3806 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3807 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3808 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3810 mono_ptr_array_destroy (tmp_array);
3815 static MonoReflectionEvent *
3816 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3819 MonoClass *klass, *startklass;
3825 MONO_ARCH_SAVE_REGS;
3827 event_name = mono_string_to_utf8 (name);
3828 if (type->type->byref)
3830 klass = startklass = mono_class_from_mono_type (type->type);
3831 domain = mono_object_domain (type);
3834 if (klass->exception_type != MONO_EXCEPTION_NONE)
3835 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3838 while ((event = mono_class_get_events (klass, &iter))) {
3839 if (strcmp (event->name, event_name))
3842 method = event->add;
3844 method = event->remove;
3846 method = event->raise;
3848 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3849 if (!(bflags & BFLAGS_Public))
3852 if (!(bflags & BFLAGS_NonPublic))
3854 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3858 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3859 if (!(bflags & BFLAGS_Static))
3861 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3864 if (!(bflags & BFLAGS_Instance))
3868 if (!(bflags & BFLAGS_NonPublic))
3871 g_free (event_name);
3872 return mono_event_get_object (domain, startklass, event);
3875 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3878 g_free (event_name);
3883 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3886 static MonoClass *System_Reflection_EventInfo;
3887 MonoClass *startklass, *klass;
3894 MonoPtrArray tmp_array;
3896 MONO_ARCH_SAVE_REGS;
3898 mono_ptr_array_init (tmp_array, 4);
3900 if (!System_Reflection_EventInfo)
3901 System_Reflection_EventInfo = mono_class_from_name (
3902 mono_defaults.corlib, "System.Reflection", "EventInfo");
3904 domain = mono_object_domain (type);
3905 if (type->type->byref)
3906 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3907 klass = startklass = mono_class_from_mono_type (type->type);
3910 if (klass->exception_type != MONO_EXCEPTION_NONE)
3911 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3914 while ((event = mono_class_get_events (klass, &iter))) {
3916 method = event->add;
3918 method = event->remove;
3920 method = event->raise;
3922 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3923 if (bflags & BFLAGS_Public)
3925 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3926 if (bflags & BFLAGS_NonPublic)
3931 if (bflags & BFLAGS_NonPublic)
3937 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3938 if (bflags & BFLAGS_Static)
3939 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3942 if (bflags & BFLAGS_Instance)
3947 if (bflags & BFLAGS_Instance)
3951 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3953 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3956 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3958 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3959 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3961 mono_ptr_array_destroy (tmp_array);
3966 static MonoReflectionType *
3967 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3975 MONO_ARCH_SAVE_REGS;
3978 mono_raise_exception (mono_get_exception_argument_null ("name"));
3980 domain = ((MonoObject *)type)->vtable->domain;
3981 if (type->type->byref)
3983 klass = mono_class_from_mono_type (type->type);
3984 str = mono_string_to_utf8 (name);
3987 if (klass->exception_type != MONO_EXCEPTION_NONE)
3988 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3991 * If a nested type is generic, return its generic type definition.
3992 * Note that this means that the return value is essentially a
3993 * nested type of the generic type definition of @klass.
3995 * A note in MSDN claims that a generic type definition can have
3996 * nested types that aren't generic. In any case, the container of that
3997 * nested type would be the generic type definition.
3999 if (klass->generic_class)
4000 klass = klass->generic_class->container_class;
4003 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4005 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4006 if (bflags & BFLAGS_Public)
4009 if (bflags & BFLAGS_NonPublic)
4014 if (strcmp (nested->name, str) == 0){
4016 return mono_type_get_object (domain, &nested->byval_arg);
4019 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4026 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4035 MonoPtrArray tmp_array;
4037 MONO_ARCH_SAVE_REGS;
4039 domain = ((MonoObject *)type)->vtable->domain;
4040 if (type->type->byref)
4041 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4042 klass = mono_class_from_mono_type (type->type);
4043 if (klass->exception_type != MONO_EXCEPTION_NONE)
4044 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4047 * If a nested type is generic, return its generic type definition.
4048 * Note that this means that the return value is essentially the set
4049 * of nested types of the generic type definition of @klass.
4051 * A note in MSDN claims that a generic type definition can have
4052 * nested types that aren't generic. In any case, the container of that
4053 * nested type would be the generic type definition.
4055 if (klass->generic_class)
4056 klass = klass->generic_class->container_class;
4058 mono_ptr_array_init (tmp_array, 1);
4060 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4062 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4063 if (bflags & BFLAGS_Public)
4066 if (bflags & BFLAGS_NonPublic)
4071 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4072 mono_ptr_array_append (tmp_array, member);
4075 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4077 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4078 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4080 mono_ptr_array_destroy (tmp_array);
4085 static MonoReflectionType*
4086 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4089 MonoType *type = NULL;
4090 MonoTypeNameParse info;
4091 gboolean type_resolve;
4093 MONO_ARCH_SAVE_REGS;
4095 /* On MS.NET, this does not fire a TypeResolve event */
4096 type_resolve = TRUE;
4097 str = mono_string_to_utf8 (name);
4098 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4099 if (!mono_reflection_parse_type (str, &info)) {
4101 mono_reflection_free_type_info (&info);
4102 if (throwOnError) /* uhm: this is a parse error, though... */
4103 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4104 /*g_print ("failed parse\n");*/
4108 if (info.assembly.name) {
4110 mono_reflection_free_type_info (&info);
4112 /* 1.0 and 2.0 throw different exceptions */
4113 if (mono_defaults.generic_ilist_class)
4114 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4116 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4121 if (module != NULL) {
4123 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4128 if (assembly->assembly->dynamic) {
4129 /* Enumerate all modules */
4130 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4134 if (abuilder->modules) {
4135 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4136 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4137 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4143 if (!type && abuilder->loaded_modules) {
4144 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4145 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4146 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4153 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4155 mono_reflection_free_type_info (&info);
4157 MonoException *e = NULL;
4160 e = mono_get_exception_type_load (name, NULL);
4162 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4163 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4165 mono_loader_clear_error ();
4168 mono_raise_exception (e);
4173 if (type->type == MONO_TYPE_CLASS) {
4174 MonoClass *klass = mono_type_get_class (type);
4176 if (mono_is_security_manager_active () && !klass->exception_type)
4177 /* Some security problems are detected during generic vtable construction */
4178 mono_class_setup_vtable (klass);
4179 /* need to report exceptions ? */
4180 if (throwOnError && klass->exception_type) {
4181 /* report SecurityException (or others) that occured when loading the assembly */
4182 MonoException *exc = mono_class_get_exception_for_failure (klass);
4183 mono_loader_clear_error ();
4184 mono_raise_exception (exc);
4185 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4190 /* g_print ("got it\n"); */
4191 return mono_type_get_object (mono_object_domain (assembly), type);
4195 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4198 gchar *shadow_ini_file;
4201 /* Check for shadow-copied assembly */
4202 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4203 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4205 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4206 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4212 g_free (shadow_ini_file);
4213 if (content != NULL) {
4216 *filename = content;
4224 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4226 MonoDomain *domain = mono_object_domain (assembly);
4227 MonoAssembly *mass = assembly->assembly;
4228 MonoString *res = NULL;
4233 MONO_ARCH_SAVE_REGS;
4235 if (g_path_is_absolute (mass->image->name)) {
4236 absolute = g_strdup (mass->image->name);
4237 dirname = g_path_get_dirname (absolute);
4239 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4240 dirname = g_strdup (mass->basedir);
4243 replace_shadow_path (domain, dirname, &absolute);
4248 for (i = strlen (absolute) - 1; i >= 0; i--)
4249 if (absolute [i] == '\\')
4254 uri = g_filename_to_uri (absolute, NULL, NULL);
4256 const char *prepend = "file://";
4258 if (*absolute == '/' && *(absolute + 1) == '/') {
4261 prepend = "file:///";
4264 uri = g_strconcat (prepend, absolute, NULL);
4268 res = mono_string_new (domain, uri);
4276 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4278 MonoAssembly *mass = assembly->assembly;
4280 MONO_ARCH_SAVE_REGS;
4282 return mass->in_gac;
4285 static MonoReflectionAssembly*
4286 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4290 MonoImageOpenStatus status;
4292 MONO_ARCH_SAVE_REGS;
4294 name = mono_string_to_utf8 (mname);
4295 res = mono_assembly_load_with_partial_name (name, &status);
4301 return mono_assembly_get_object (mono_domain_get (), res);
4305 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4307 MonoDomain *domain = mono_object_domain (assembly);
4310 MONO_ARCH_SAVE_REGS;
4312 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4318 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4320 MONO_ARCH_SAVE_REGS;
4322 return assembly->assembly->ref_only;
4326 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4328 MonoDomain *domain = mono_object_domain (assembly);
4330 MONO_ARCH_SAVE_REGS;
4332 return mono_string_new (domain, assembly->assembly->image->version);
4335 static MonoReflectionMethod*
4336 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4338 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4340 MONO_ARCH_SAVE_REGS;
4344 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4347 static MonoReflectionModule*
4348 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4350 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4354 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4356 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4357 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4361 MONO_ARCH_SAVE_REGS;
4363 for (i = 0; i < table->rows; ++i) {
4364 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4365 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4371 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4373 static MonoClass *System_Version = NULL;
4374 static MonoMethod *create_version = NULL;
4378 if (!System_Version) {
4379 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4380 g_assert (System_Version);
4383 if (!create_version) {
4384 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4385 create_version = mono_method_desc_search_in_class (desc, System_Version);
4386 g_assert (create_version);
4387 mono_method_desc_free (desc);
4393 args [3] = &revision;
4394 result = mono_object_new (domain, System_Version);
4395 mono_runtime_invoke (create_version, result, args, NULL);
4401 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4403 static MonoClass *System_Reflection_AssemblyName;
4405 MonoDomain *domain = mono_object_domain (assembly);
4407 static MonoMethod *create_culture = NULL;
4408 MonoImage *image = assembly->assembly->image;
4411 MONO_ARCH_SAVE_REGS;
4413 if (!System_Reflection_AssemblyName)
4414 System_Reflection_AssemblyName = mono_class_from_name (
4415 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4417 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4420 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4422 if (count > 0 && !create_culture) {
4423 MonoMethodDesc *desc = mono_method_desc_new (
4424 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4425 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4426 g_assert (create_culture);
4427 mono_method_desc_free (desc);
4430 for (i = 0; i < count; i++) {
4431 MonoReflectionAssemblyName *aname;
4432 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4434 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4436 aname = (MonoReflectionAssemblyName *) mono_object_new (
4437 domain, System_Reflection_AssemblyName);
4439 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4441 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4442 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4443 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4444 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4445 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4446 aname->versioncompat = 1; /* SameMachine (default) */
4447 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4448 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4450 if (create_culture) {
4452 MonoBoolean assembly_ref = 1;
4453 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4454 args [1] = &assembly_ref;
4455 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4458 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4459 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4460 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4462 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4463 /* public key token isn't copied - the class library will
4464 automatically generate it from the public key if required */
4465 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4466 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4468 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4469 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4472 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4475 /* note: this function doesn't return the codebase on purpose (i.e. it can
4476 be used under partial trust as path information isn't present). */
4478 mono_array_setref (result, i, aname);
4489 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4491 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4493 mono_array_setref (info->res, info->idx, name);
4498 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4500 MonoImage *img = assembly->assembly->image;
4505 MONO_ARCH_SAVE_REGS;
4507 mono_image_lock (img);
4508 mono_image_init_name_cache (img);
4511 len = g_hash_table_size (img->name_cache);
4512 mono_image_unlock (img);
4514 /*we can't create objects holding the image lock */
4515 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4517 mono_image_lock (img);
4518 /*len might have changed, create a new array*/
4519 if (len != g_hash_table_size (img->name_cache))
4524 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4525 mono_image_unlock (img);
4530 /* move this in some file in mono/util/ */
4532 g_concat_dir_and_file (const char *dir, const char *file)
4534 g_return_val_if_fail (dir != NULL, NULL);
4535 g_return_val_if_fail (file != NULL, NULL);
4538 * If the directory name doesn't have a / on the end, we need
4539 * to add one so we get a proper path to the file
4541 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4542 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4544 return g_strconcat (dir, file, NULL);
4548 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4550 char *n = mono_string_to_utf8 (name);
4551 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4553 guint32 cols [MONO_MANIFEST_SIZE];
4554 guint32 impl, file_idx;
4558 MONO_ARCH_SAVE_REGS;
4560 for (i = 0; i < table->rows; ++i) {
4561 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4562 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4563 if (strcmp (val, n) == 0)
4567 if (i == table->rows)
4570 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4573 * this code should only be called after obtaining the
4574 * ResourceInfo and handling the other cases.
4576 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4577 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4579 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4584 module = assembly->assembly->image;
4586 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4588 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4592 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4594 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4596 guint32 cols [MONO_MANIFEST_SIZE];
4597 guint32 file_cols [MONO_FILE_SIZE];
4601 MONO_ARCH_SAVE_REGS;
4603 n = mono_string_to_utf8 (name);
4604 for (i = 0; i < table->rows; ++i) {
4605 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4606 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4607 if (strcmp (val, n) == 0)
4611 if (i == table->rows)
4614 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4615 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4618 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4619 case MONO_IMPLEMENTATION_FILE:
4620 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4621 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4622 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4623 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4624 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4625 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4628 info->location = RESOURCE_LOCATION_EMBEDDED;
4631 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4632 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4633 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4634 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4635 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4636 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4638 mono_raise_exception (ex);
4640 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4642 /* Obtain info recursively */
4643 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4644 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4647 case MONO_IMPLEMENTATION_EXP_TYPE:
4648 g_assert_not_reached ();
4657 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4659 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4660 MonoArray *result = NULL;
4665 MONO_ARCH_SAVE_REGS;
4667 /* check hash if needed */
4669 n = mono_string_to_utf8 (name);
4670 for (i = 0; i < table->rows; ++i) {
4671 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4672 if (strcmp (val, n) == 0) {
4675 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4676 fn = mono_string_new (mono_object_domain (assembly), n);
4678 return (MonoObject*)fn;
4686 for (i = 0; i < table->rows; ++i) {
4687 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4691 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4694 for (i = 0; i < table->rows; ++i) {
4695 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4696 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4697 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4698 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4703 return (MonoObject*)result;
4707 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4709 MonoDomain *domain = mono_domain_get();
4712 int i, j, file_count = 0;
4713 MonoImage **modules;
4714 guint32 module_count, real_module_count;
4715 MonoTableInfo *table;
4716 guint32 cols [MONO_FILE_SIZE];
4717 MonoImage *image = assembly->assembly->image;
4719 g_assert (image != NULL);
4720 g_assert (!assembly->assembly->dynamic);
4722 table = &image->tables [MONO_TABLE_FILE];
4723 file_count = table->rows;
4725 modules = image->modules;
4726 module_count = image->module_count;
4728 real_module_count = 0;
4729 for (i = 0; i < module_count; ++i)
4731 real_module_count ++;
4733 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4734 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4736 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4738 for (i = 0; i < module_count; ++i)
4740 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4744 for (i = 0; i < file_count; ++i, ++j) {
4745 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4746 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4747 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4749 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4751 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4752 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4754 mono_array_setref (res, j, mono_module_get_object (domain, m));
4761 static MonoReflectionMethod*
4762 ves_icall_GetCurrentMethod (void)
4764 MonoMethod *m = mono_method_get_last_managed ();
4766 while (m->is_inflated)
4767 m = ((MonoMethodInflated*)m)->declaring;
4769 return mono_method_get_object (mono_domain_get (), m, NULL);
4774 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4777 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4778 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4779 //method is inflated, we should inflate it on the other class
4780 MonoGenericContext ctx;
4781 ctx.method_inst = inflated->context.method_inst;
4782 ctx.class_inst = inflated->context.class_inst;
4783 if (klass->generic_class)
4784 ctx.class_inst = klass->generic_class->context.class_inst;
4785 else if (klass->generic_container)
4786 ctx.class_inst = klass->generic_container->context.class_inst;
4787 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4790 mono_class_setup_methods (method->klass);
4791 if (method->klass->exception_type)
4793 for (i = 0; i < method->klass->method.count; ++i) {
4794 if (method->klass->methods [i] == method) {
4799 mono_class_setup_methods (klass);
4800 if (klass->exception_type)
4802 g_assert (offset >= 0 && offset < klass->method.count);
4803 return klass->methods [offset];
4806 static MonoReflectionMethod*
4807 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4811 klass = mono_class_from_mono_type (type);
4812 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4814 if (method->klass != klass) {
4815 method = mono_method_get_equivalent_method (method, klass);
4820 klass = method->klass;
4821 return mono_method_get_object (mono_domain_get (), method, klass);
4824 static MonoReflectionMethod*
4825 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4827 return mono_method_get_object (mono_domain_get (), method, NULL);
4830 static MonoReflectionMethodBody*
4831 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4833 return mono_method_body_get_object (mono_domain_get (), method);
4836 static MonoReflectionAssembly*
4837 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4839 MonoMethod *dest = NULL;
4841 MONO_ARCH_SAVE_REGS;
4843 mono_stack_walk_no_il (get_executing, &dest);
4844 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4848 static MonoReflectionAssembly*
4849 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4851 MonoDomain* domain = mono_domain_get ();
4853 MONO_ARCH_SAVE_REGS;
4855 if (!domain->entry_assembly)
4858 return mono_assembly_get_object (domain, domain->entry_assembly);
4861 static MonoReflectionAssembly*
4862 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4867 MONO_ARCH_SAVE_REGS;
4870 mono_stack_walk_no_il (get_executing, &dest);
4872 mono_stack_walk_no_il (get_caller, &dest);
4875 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4879 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4880 gboolean assembly_qualified)
4882 MonoDomain *domain = mono_object_domain (object);
4883 MonoTypeNameFormat format;
4887 MONO_ARCH_SAVE_REGS;
4889 format = assembly_qualified ?
4890 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4891 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4893 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4895 name = mono_type_get_name_full (object->type, format);
4899 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4904 res = mono_string_new (domain, name);
4911 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4913 MonoClass *klass = mono_class_from_mono_type (this->type);
4914 return mono_security_core_clr_class_level (klass);
4918 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4920 static MonoMethod *create_culture = NULL;
4923 const char *pkey_ptr;
4925 MonoBoolean assembly_ref = 0;
4927 MONO_ARCH_SAVE_REGS;
4929 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4930 aname->major = name->major;
4931 aname->minor = name->minor;
4932 aname->build = name->build;
4933 aname->flags = name->flags;
4934 aname->revision = name->revision;
4935 aname->hashalg = name->hash_alg;
4936 aname->versioncompat = 1; /* SameMachine (default) */
4938 if (by_default_version)
4939 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4942 if (absolute != NULL && *absolute != '\0') {
4943 const gchar *prepend = "file://";
4946 codebase = g_strdup (absolute);
4951 for (i = strlen (codebase) - 1; i >= 0; i--)
4952 if (codebase [i] == '\\')
4955 if (*codebase == '/' && *(codebase + 1) == '/') {
4958 prepend = "file:///";
4962 result = g_strconcat (prepend, codebase, NULL);
4968 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4972 if (!create_culture) {
4973 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4974 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4975 g_assert (create_culture);
4976 mono_method_desc_free (desc);
4979 if (name->culture) {
4980 args [0] = mono_string_new (domain, name->culture);
4981 args [1] = &assembly_ref;
4982 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4985 if (name->public_key) {
4986 pkey_ptr = (char*)name->public_key;
4987 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4989 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4990 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4991 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4992 } else if (default_publickey) {
4993 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4994 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4997 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4998 if (name->public_key_token [0]) {
5002 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5003 p = mono_array_addr (aname->keyToken, char, 0);
5005 for (i = 0, j = 0; i < 8; i++) {
5006 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5007 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5010 } else if (default_token) {
5011 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5016 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5018 MonoDomain *domain = mono_object_domain (assembly);
5019 MonoAssembly *mass = assembly->assembly;
5023 name = g_strdup_printf (
5024 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5026 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5027 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5028 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5029 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5031 res = mono_string_new (domain, name);
5038 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5041 MonoAssembly *mass = assembly->assembly;
5043 MONO_ARCH_SAVE_REGS;
5045 if (g_path_is_absolute (mass->image->name)) {
5046 fill_reflection_assembly_name (mono_object_domain (assembly),
5047 aname, &mass->aname, mass->image->name, TRUE,
5051 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5053 fill_reflection_assembly_name (mono_object_domain (assembly),
5054 aname, &mass->aname, absolute, TRUE, TRUE,
5061 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5064 MonoImageOpenStatus status = MONO_IMAGE_OK;
5067 MonoAssemblyName name;
5070 MONO_ARCH_SAVE_REGS;
5072 filename = mono_string_to_utf8 (fname);
5074 dirname = g_path_get_dirname (filename);
5075 replace_shadow_path (mono_domain_get (), dirname, &filename);
5078 image = mono_image_open (filename, &status);
5084 if (status == MONO_IMAGE_IMAGE_INVALID)
5085 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5087 exc = mono_get_exception_file_not_found2 (NULL, fname);
5088 mono_raise_exception (exc);
5091 res = mono_assembly_fill_assembly_name (image, &name);
5093 mono_image_close (image);
5095 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5098 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5102 mono_image_close (image);
5106 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5107 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5109 MonoBoolean result = FALSE;
5110 MonoDeclSecurityEntry entry;
5112 /* SecurityAction.RequestMinimum */
5113 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5114 *minimum = entry.blob;
5115 *minLength = entry.size;
5118 /* SecurityAction.RequestOptional */
5119 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5120 *optional = entry.blob;
5121 *optLength = entry.size;
5124 /* SecurityAction.RequestRefuse */
5125 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5126 *refused = entry.blob;
5127 *refLength = entry.size;
5135 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5139 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5141 guint32 attrs, visibility;
5143 /* we start the count from 1 because we skip the special type <Module> */
5146 for (i = 1; i < tdef->rows; ++i) {
5147 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5148 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5149 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5153 count = tdef->rows - 1;
5155 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5156 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5158 for (i = 1; i < tdef->rows; ++i) {
5159 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5160 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5161 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5162 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5164 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5166 MonoLoaderError *error;
5169 error = mono_loader_get_last_error ();
5170 g_assert (error != NULL);
5172 ex = mono_loader_error_prepare_exception (error);
5173 mono_array_setref (*exceptions, count, ex);
5175 if (mono_loader_get_last_error ())
5176 mono_loader_clear_error ();
5185 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5187 MonoArray *res = NULL;
5188 MonoArray *exceptions = NULL;
5189 MonoImage *image = NULL;
5190 MonoTableInfo *table = NULL;
5193 int i, len, ex_count;
5195 MONO_ARCH_SAVE_REGS;
5197 domain = mono_object_domain (assembly);
5199 g_assert (!assembly->assembly->dynamic);
5200 image = assembly->assembly->image;
5201 table = &image->tables [MONO_TABLE_FILE];
5202 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5204 /* Append data from all modules in the assembly */
5205 for (i = 0; i < table->rows; ++i) {
5206 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5207 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5210 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5211 /* Append the new types to the end of the array */
5212 if (mono_array_length (res2) > 0) {
5214 MonoArray *res3, *ex3;
5216 len1 = mono_array_length (res);
5217 len2 = mono_array_length (res2);
5219 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5220 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5221 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5224 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5225 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5226 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5233 /* the ReflectionTypeLoadException must have all the types (Types property),
5234 * NULL replacing types which throws an exception. The LoaderException must
5235 * contain all exceptions for NULL items.
5238 len = mono_array_length (res);
5241 for (i = 0; i < len; i++) {
5242 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5246 klass = mono_type_get_class (t->type);
5247 if ((klass != NULL) && klass->exception_type) {
5248 /* keep the class in the list */
5249 list = g_list_append (list, klass);
5250 /* and replace Type with NULL */
5251 mono_array_setref (res, i, NULL);
5258 if (list || ex_count) {
5260 MonoException *exc = NULL;
5261 MonoArray *exl = NULL;
5262 int j, length = g_list_length (list) + ex_count;
5264 mono_loader_clear_error ();
5266 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5267 /* Types for which mono_class_get () succeeded */
5268 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5269 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5270 mono_array_setref (exl, i, exc);
5272 /* Types for which it don't */
5273 for (j = 0; j < mono_array_length (exceptions); ++j) {
5274 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5276 g_assert (i < length);
5277 mono_array_setref (exl, i, exc);
5284 exc = mono_get_exception_reflection_type_load (res, exl);
5285 mono_loader_clear_error ();
5286 mono_raise_exception (exc);
5293 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5295 MonoAssemblyName aname;
5296 MonoDomain *domain = mono_object_domain (name);
5298 gboolean is_version_defined;
5299 gboolean is_token_defined;
5301 aname.public_key = NULL;
5302 val = mono_string_to_utf8 (assname);
5303 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5304 g_free ((guint8*) aname.public_key);
5309 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5310 FALSE, is_token_defined);
5312 mono_assembly_name_free (&aname);
5313 g_free ((guint8*) aname.public_key);
5319 static MonoReflectionType*
5320 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5322 MonoDomain *domain = mono_object_domain (module);
5325 MONO_ARCH_SAVE_REGS;
5327 g_assert (module->image);
5329 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5330 /* These images do not have a global type */
5333 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5334 return mono_type_get_object (domain, &klass->byval_arg);
5338 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5340 /*if (module->image)
5341 mono_image_close (module->image);*/
5345 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5347 MonoDomain *domain = mono_object_domain (module);
5349 MONO_ARCH_SAVE_REGS;
5351 g_assert (module->image);
5352 return mono_string_new (domain, module->image->guid);
5356 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5359 if (module->image && module->image->is_module_handle)
5360 return module->image->raw_data;
5363 return (gpointer) (-1);
5367 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5369 if (image->dynamic) {
5370 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5371 *pe_kind = dyn->pe_kind;
5372 *machine = dyn->machine;
5375 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5376 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5381 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5383 return (image->md_version_major << 16) | (image->md_version_minor);
5387 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5389 MonoArray *exceptions;
5392 MONO_ARCH_SAVE_REGS;
5395 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5397 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5398 for (i = 0; i < mono_array_length (exceptions); ++i) {
5399 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5401 mono_raise_exception (ex);
5408 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5410 guint32 cols [MONO_MEMBERREF_SIZE];
5412 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5413 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5414 mono_metadata_decode_blob_size (sig, &sig);
5415 return (*sig != 0x6);
5419 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5422 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5423 mono_array_addr (type_args, MonoType*, 0));
5425 context->class_inst = NULL;
5427 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5428 mono_array_addr (method_args, MonoType*, 0));
5430 context->method_inst = NULL;
5434 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5437 int table = mono_metadata_token_table (token);
5438 int index = mono_metadata_token_index (token);
5439 MonoGenericContext context;
5441 *error = ResolveTokenError_Other;
5443 /* Validate token */
5444 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5445 (table != MONO_TABLE_TYPESPEC)) {
5446 *error = ResolveTokenError_BadTable;
5450 if (image->dynamic) {
5451 if (type_args || method_args)
5452 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5453 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5456 return &klass->byval_arg;
5459 if ((index <= 0) || (index > image->tables [table].rows)) {
5460 *error = ResolveTokenError_OutOfRange;
5464 init_generic_context_from_args (&context, type_args, method_args);
5465 klass = mono_class_get_full (image, token, &context);
5467 if (mono_loader_get_last_error ())
5468 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5471 return &klass->byval_arg;
5477 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5479 int table = mono_metadata_token_table (token);
5480 int index = mono_metadata_token_index (token);
5481 MonoGenericContext context;
5484 *error = ResolveTokenError_Other;
5486 /* Validate token */
5487 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5488 (table != MONO_TABLE_MEMBERREF)) {
5489 *error = ResolveTokenError_BadTable;
5493 if (image->dynamic) {
5494 if (type_args || method_args)
5495 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5496 /* FIXME: validate memberref token type */
5497 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5500 if ((index <= 0) || (index > image->tables [table].rows)) {
5501 *error = ResolveTokenError_OutOfRange;
5504 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5505 *error = ResolveTokenError_BadTable;
5509 init_generic_context_from_args (&context, type_args, method_args);
5510 method = mono_get_method_full (image, token, NULL, &context);
5512 if (mono_loader_get_last_error ())
5513 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5519 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5521 int index = mono_metadata_token_index (token);
5523 *error = ResolveTokenError_Other;
5525 /* Validate token */
5526 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5527 *error = ResolveTokenError_BadTable;
5532 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5534 if ((index <= 0) || (index >= image->heap_us.size)) {
5535 *error = ResolveTokenError_OutOfRange;
5539 /* FIXME: What to do if the index points into the middle of a string ? */
5541 return mono_ldstr (mono_domain_get (), image, index);
5544 static MonoClassField*
5545 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5548 int table = mono_metadata_token_table (token);
5549 int index = mono_metadata_token_index (token);
5550 MonoGenericContext context;
5551 MonoClassField *field;
5553 *error = ResolveTokenError_Other;
5555 /* Validate token */
5556 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5557 *error = ResolveTokenError_BadTable;
5561 if (image->dynamic) {
5562 if (type_args || method_args)
5563 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5564 /* FIXME: validate memberref token type */
5565 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5568 if ((index <= 0) || (index > image->tables [table].rows)) {
5569 *error = ResolveTokenError_OutOfRange;
5572 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5573 *error = ResolveTokenError_BadTable;
5577 init_generic_context_from_args (&context, type_args, method_args);
5578 field = mono_field_from_token (image, token, &klass, &context);
5580 if (mono_loader_get_last_error ())
5581 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5588 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5590 int table = mono_metadata_token_table (token);
5592 *error = ResolveTokenError_Other;
5595 case MONO_TABLE_TYPEDEF:
5596 case MONO_TABLE_TYPEREF:
5597 case MONO_TABLE_TYPESPEC: {
5598 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5600 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5604 case MONO_TABLE_METHOD:
5605 case MONO_TABLE_METHODSPEC: {
5606 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5608 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5612 case MONO_TABLE_FIELD: {
5613 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5615 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5619 case MONO_TABLE_MEMBERREF:
5620 if (mono_metadata_memberref_is_method (image, token)) {
5621 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5623 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5628 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5630 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5637 *error = ResolveTokenError_BadTable;
5644 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5646 int table = mono_metadata_token_table (token);
5647 int idx = mono_metadata_token_index (token);
5648 MonoTableInfo *tables = image->tables;
5653 *error = ResolveTokenError_OutOfRange;
5655 /* FIXME: Support other tables ? */
5656 if (table != MONO_TABLE_STANDALONESIG)
5662 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5665 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5667 ptr = mono_metadata_blob_heap (image, sig);
5668 len = mono_metadata_decode_blob_size (ptr, &ptr);
5670 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5671 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5675 static MonoReflectionType*
5676 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5679 int isbyref = 0, rank;
5680 char *str = mono_string_to_utf8 (smodifiers);
5683 MONO_ARCH_SAVE_REGS;
5685 klass = mono_class_from_mono_type (tb->type.type);
5687 /* logic taken from mono_reflection_parse_type(): keep in sync */
5691 if (isbyref) { /* only one level allowed by the spec */
5698 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5701 klass = mono_ptr_class_get (&klass->byval_arg);
5702 mono_class_init (klass);
5713 else if (*p != '*') { /* '*' means unknown lower bound */
5724 klass = mono_array_class_get (klass, rank);
5725 mono_class_init (klass);
5732 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5736 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5741 MONO_ARCH_SAVE_REGS;
5744 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5749 static MonoReflectionType *
5750 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5752 MonoClass *klass, *aklass;
5754 MONO_ARCH_SAVE_REGS;
5756 klass = mono_class_from_mono_type (type->type);
5757 if (rank == 0) //single dimentional array
5758 aklass = mono_array_class_get (klass, 1);
5760 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5762 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5765 static MonoReflectionType *
5766 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5770 MONO_ARCH_SAVE_REGS;
5772 klass = mono_class_from_mono_type (type->type);
5774 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5777 static MonoReflectionType *
5778 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5782 MONO_ARCH_SAVE_REGS;
5784 pklass = mono_ptr_class_get (type->type);
5786 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5790 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5791 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5793 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5794 MonoObject *delegate;
5796 MonoMethod *method = info->method;
5798 MONO_ARCH_SAVE_REGS;
5800 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5802 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5803 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5807 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5809 if (method->dynamic) {
5810 /* Creating a trampoline would leak memory */
5811 func = mono_compile_method (method);
5813 func = mono_create_ftnptr (mono_domain_get (),
5814 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5817 mono_delegate_ctor_with_method (delegate, target, func, method);
5823 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5825 /* Reset the invoke impl to the default one */
5826 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5830 * Magic number to convert a time which is relative to
5831 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5833 #define EPOCH_ADJUST ((guint64)62135596800LL)
5836 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5838 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5841 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5843 convert_to_absolute_date(SYSTEMTIME *date)
5845 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5846 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5847 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5848 /* from the calendar FAQ */
5849 int a = (14 - date->wMonth) / 12;
5850 int y = date->wYear - a;
5851 int m = date->wMonth + 12 * a - 2;
5852 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5854 /* d is now the day of the week for the first of the month (0 == Sunday) */
5856 int day_of_week = date->wDayOfWeek;
5858 /* set day_in_month to the first day in the month which falls on day_of_week */
5859 int day_in_month = 1 + (day_of_week - d);
5860 if (day_in_month <= 0)
5863 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5864 date->wDay = day_in_month + (date->wDay - 1) * 7;
5865 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5872 * Return's the offset from GMT of a local time.
5874 * tm is a local time
5875 * t is the same local time as seconds.
5878 gmt_offset(struct tm *tm, time_t t)
5880 #if defined (HAVE_TM_GMTOFF)
5881 return tm->tm_gmtoff;
5886 g.tm_isdst = tm->tm_isdst;
5888 return (int)difftime(t, t2);
5893 * This is heavily based on zdump.c from glibc 2.2.
5895 * * data[0]: start of daylight saving time (in DateTime ticks).
5896 * * data[1]: end of daylight saving time (in DateTime ticks).
5897 * * data[2]: utcoffset (in TimeSpan ticks).
5898 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5899 * * name[0]: name of this timezone when not daylight saving.
5900 * * name[1]: name of this timezone when daylight saving.
5902 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5903 * the class library allows years between 1 and 9999.
5905 * Returns true on success and zero on failure.
5908 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5911 MonoDomain *domain = mono_domain_get ();
5912 struct tm start, tt;
5916 int is_daylight = 0, day;
5919 MONO_ARCH_SAVE_REGS;
5921 MONO_CHECK_ARG_NULL (data);
5922 MONO_CHECK_ARG_NULL (names);
5924 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5925 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5928 * no info is better than crashing: we'll need our own tz data
5929 * to make this work properly, anyway. The range is probably
5930 * reduced to 1970 .. 2037 because that is what mktime is
5931 * guaranteed to support (we get into an infinite loop
5935 memset (&start, 0, sizeof (start));
5938 start.tm_year = year-1900;
5940 t = mktime (&start);
5942 if ((year < 1970) || (year > 2037) || (t == -1)) {
5944 tt = *localtime (&t);
5945 strftime (tzone, sizeof (tzone), "%Z", &tt);
5946 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5947 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5951 gmtoff = gmt_offset (&start, t);
5953 /* For each day of the year, calculate the tm_gmtoff. */
5954 for (day = 0; day < 365; day++) {
5957 tt = *localtime (&t);
5959 /* Daylight saving starts or ends here. */
5960 if (gmt_offset (&tt, t) != gmtoff) {
5964 /* Try to find the exact hour when daylight saving starts/ends. */
5968 tt1 = *localtime (&t1);
5969 } while (gmt_offset (&tt1, t1) != gmtoff);
5971 /* Try to find the exact minute when daylight saving starts/ends. */
5974 tt1 = *localtime (&t1);
5975 } while (gmt_offset (&tt1, t1) == gmtoff);
5977 strftime (tzone, sizeof (tzone), "%Z", &tt);
5979 /* Write data, if we're already in daylight saving, we're done. */
5981 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5982 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5985 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5986 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5990 /* This is only set once when we enter daylight saving. */
5991 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5992 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5994 gmtoff = gmt_offset (&tt, t);
5999 strftime (tzone, sizeof (tzone), "%Z", &tt);
6000 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6001 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6002 mono_array_set ((*data), gint64, 0, 0);
6003 mono_array_set ((*data), gint64, 1, 0);
6004 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6005 mono_array_set ((*data), gint64, 3, 0);
6010 MonoDomain *domain = mono_domain_get ();
6011 TIME_ZONE_INFORMATION tz_info;
6016 tz_id = GetTimeZoneInformation (&tz_info);
6017 if (tz_id == TIME_ZONE_ID_INVALID)
6020 MONO_CHECK_ARG_NULL (data);
6021 MONO_CHECK_ARG_NULL (names);
6023 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6024 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6026 for (i = 0; i < 32; ++i)
6027 if (!tz_info.DaylightName [i])
6029 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6030 for (i = 0; i < 32; ++i)
6031 if (!tz_info.StandardName [i])
6033 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6035 if ((year <= 1601) || (year > 30827)) {
6037 * According to MSDN, the MS time functions can't handle dates outside
6043 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6044 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6045 tz_info.StandardDate.wYear = year;
6046 convert_to_absolute_date(&tz_info.StandardDate);
6047 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6052 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6053 tz_info.DaylightDate.wYear = year;
6054 convert_to_absolute_date(&tz_info.DaylightDate);
6055 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6060 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6062 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6063 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6070 ves_icall_System_Object_obj_address (MonoObject *this)
6072 MONO_ARCH_SAVE_REGS;
6079 static inline gint32
6080 mono_array_get_byte_length (MonoArray *array)
6086 klass = array->obj.vtable->klass;
6088 if (array->bounds == NULL)
6089 length = array->max_length;
6092 for (i = 0; i < klass->rank; ++ i)
6093 length *= array->bounds [i].length;
6096 switch (klass->element_class->byval_arg.type) {
6099 case MONO_TYPE_BOOLEAN:
6103 case MONO_TYPE_CHAR:
6111 return length * sizeof (gpointer);
6122 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6124 MONO_ARCH_SAVE_REGS;
6126 return mono_array_get_byte_length (array);
6130 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6132 MONO_ARCH_SAVE_REGS;
6134 return mono_array_get (array, gint8, idx);
6138 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6140 MONO_ARCH_SAVE_REGS;
6142 mono_array_set (array, gint8, idx, value);
6146 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6148 guint8 *src_buf, *dest_buf;
6150 MONO_ARCH_SAVE_REGS;
6152 /* watch out for integer overflow */
6153 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6156 src_buf = (guint8 *)src->vector + src_offset;
6157 dest_buf = (guint8 *)dest->vector + dest_offset;
6160 memcpy (dest_buf, src_buf, count);
6162 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6168 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6170 MonoDomain *domain = mono_object_domain (this);
6172 MonoRealProxy *rp = ((MonoRealProxy *)this);
6173 MonoTransparentProxy *tp;
6177 MONO_ARCH_SAVE_REGS;
6179 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6180 tp = (MonoTransparentProxy*) res;
6182 MONO_OBJECT_SETREF (tp, rp, rp);
6183 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6184 klass = mono_class_from_mono_type (type);
6186 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6187 tp->remote_class = mono_remote_class (domain, class_name, klass);
6189 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6193 static MonoReflectionType *
6194 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6196 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6199 /* System.Environment */
6202 ves_icall_System_Environment_get_UserName (void)
6204 MONO_ARCH_SAVE_REGS;
6206 /* using glib is more portable */
6207 return mono_string_new (mono_domain_get (), g_get_user_name ());
6212 ves_icall_System_Environment_get_MachineName (void)
6214 #if defined (HOST_WIN32)
6219 len = MAX_COMPUTERNAME_LENGTH + 1;
6220 buf = g_new (gunichar2, len);
6223 if (GetComputerName (buf, (PDWORD) &len))
6224 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6228 #elif !defined(DISABLE_SOCKETS)
6232 if (gethostname (buf, sizeof (buf)) == 0)
6233 result = mono_string_new (mono_domain_get (), buf);
6239 return mono_string_new (mono_domain_get (), "mono");
6244 ves_icall_System_Environment_get_Platform (void)
6246 #if defined (TARGET_WIN32)
6249 #elif defined(__MACH__)
6252 // For compatibility with our client code, this will be 4 for a while.
6253 // We will eventually move to 6 to match .NET, but it requires all client
6254 // code to be updated and the documentation everywhere to be updated
6265 ves_icall_System_Environment_get_NewLine (void)
6267 MONO_ARCH_SAVE_REGS;
6269 #if defined (HOST_WIN32)
6270 return mono_string_new (mono_domain_get (), "\r\n");
6272 return mono_string_new (mono_domain_get (), "\n");
6277 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6282 MONO_ARCH_SAVE_REGS;
6287 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6288 value = g_getenv (utf8_name);
6295 return mono_string_new (mono_domain_get (), value);
6299 * There is no standard way to get at environ.
6302 #ifndef __MINGW32_VERSION
6304 /* Apple defines this in crt_externs.h but doesn't provide that header for
6305 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6306 * in fact exist on all implementations (so far)
6308 gchar ***_NSGetEnviron(void);
6309 #define environ (*_NSGetEnviron())
6318 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6329 env_strings = GetEnvironmentStrings();
6332 env_string = env_strings;
6333 while (*env_string != '\0') {
6334 /* weird case that MS seems to skip */
6335 if (*env_string != '=')
6337 while (*env_string != '\0')
6343 domain = mono_domain_get ();
6344 names = mono_array_new (domain, mono_defaults.string_class, n);
6348 env_string = env_strings;
6349 while (*env_string != '\0') {
6350 /* weird case that MS seems to skip */
6351 if (*env_string != '=') {
6352 equal_str = wcschr(env_string, '=');
6353 g_assert(equal_str);
6354 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6355 mono_array_setref (names, n, str);
6358 while (*env_string != '\0')
6363 FreeEnvironmentStrings (env_strings);
6375 MONO_ARCH_SAVE_REGS;
6378 for (e = environ; *e != 0; ++ e)
6381 domain = mono_domain_get ();
6382 names = mono_array_new (domain, mono_defaults.string_class, n);
6385 for (e = environ; *e != 0; ++ e) {
6386 parts = g_strsplit (*e, "=", 2);
6388 str = mono_string_new (domain, *parts);
6389 mono_array_setref (names, n, str);
6402 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6404 #if !GLIB_CHECK_VERSION(2,4,0)
6405 #define g_setenv(a,b,c) setenv(a,b,c)
6406 #define g_unsetenv(a) unsetenv(a)
6410 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6415 gunichar2 *utf16_name, *utf16_value;
6417 gchar *utf8_name, *utf8_value;
6420 MONO_ARCH_SAVE_REGS;
6423 utf16_name = mono_string_to_utf16 (name);
6424 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6425 SetEnvironmentVariable (utf16_name, NULL);
6426 g_free (utf16_name);
6430 utf16_value = mono_string_to_utf16 (value);
6432 SetEnvironmentVariable (utf16_name, utf16_value);
6434 g_free (utf16_name);
6435 g_free (utf16_value);
6437 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6439 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6440 g_unsetenv (utf8_name);
6445 utf8_value = mono_string_to_utf8_checked (value, &error);
6446 if (!mono_error_ok (&error)) {
6448 mono_error_raise_exception (&error);
6450 g_setenv (utf8_name, utf8_value, TRUE);
6453 g_free (utf8_value);
6458 ves_icall_System_Environment_Exit (int result)
6460 MONO_ARCH_SAVE_REGS;
6462 mono_threads_set_shutting_down ();
6464 mono_runtime_set_shutting_down ();
6466 /* Suspend all managed threads since the runtime is going away */
6467 mono_thread_suspend_all_other_threads ();
6469 mono_runtime_quit ();
6471 /* we may need to do some cleanup here... */
6476 ves_icall_System_Environment_GetGacPath (void)
6478 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6482 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6484 #if defined (HOST_WIN32)
6485 #ifndef CSIDL_FLAG_CREATE
6486 #define CSIDL_FLAG_CREATE 0x8000
6489 WCHAR path [MAX_PATH];
6490 /* Create directory if no existing */
6491 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6495 return mono_string_new_utf16 (mono_domain_get (), path, len);
6498 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6500 return mono_string_new (mono_domain_get (), "");
6504 ves_icall_System_Environment_GetLogicalDrives (void)
6506 gunichar2 buf [128], *ptr, *dname;
6508 guint initial_size = 127, size = 128;
6511 MonoString *drivestr;
6512 MonoDomain *domain = mono_domain_get ();
6515 MONO_ARCH_SAVE_REGS;
6520 while (size > initial_size) {
6521 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6522 if (size > initial_size) {
6525 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6526 initial_size = size;
6540 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6545 while (*u16) { u16++; len ++; }
6546 drivestr = mono_string_new_utf16 (domain, dname, len);
6547 mono_array_setref (result, ndrives++, drivestr);
6558 ves_icall_System_Environment_InternalGetHome (void)
6560 MONO_ARCH_SAVE_REGS;
6562 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6565 static const char *encodings [] = {
6567 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6568 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6569 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6571 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6572 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6573 "x_unicode_2_0_utf_7",
6575 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6576 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6578 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6581 "unicodefffe", "utf_16be",
6588 * Returns the internal codepage, if the value of "int_code_page" is
6589 * 1 at entry, and we can not compute a suitable code page number,
6590 * returns the code page as a string
6593 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6598 char *codepage = NULL;
6600 int want_name = *int_code_page;
6603 *int_code_page = -1;
6604 MONO_ARCH_SAVE_REGS;
6606 g_get_charset (&cset);
6607 c = codepage = strdup (cset);
6608 for (c = codepage; *c; c++){
6609 if (isascii (*c) && isalpha (*c))
6614 /* g_print ("charset: %s\n", cset); */
6616 /* handle some common aliases */
6619 for (i = 0; p != 0; ){
6620 if ((gssize) p < 7){
6622 p = encodings [++i];
6625 if (strcmp (p, codepage) == 0){
6626 *int_code_page = code;
6629 p = encodings [++i];
6632 if (strstr (codepage, "utf_8") != NULL)
6633 *int_code_page |= 0x10000000;
6636 if (want_name && *int_code_page == -1)
6637 return mono_string_new (mono_domain_get (), cset);
6643 ves_icall_System_Environment_get_HasShutdownStarted (void)
6645 if (mono_runtime_is_shutting_down ())
6648 if (mono_domain_is_unloading (mono_domain_get ()))
6655 ves_icall_System_Environment_BroadcastSettingChange (void)
6658 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6663 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6664 MonoReflectionMethod *method,
6665 MonoArray *out_args)
6667 MONO_ARCH_SAVE_REGS;
6669 mono_message_init (mono_object_domain (this), this, method, out_args);
6673 ves_icall_IsTransparentProxy (MonoObject *proxy)
6675 MONO_ARCH_SAVE_REGS;
6680 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6686 static MonoReflectionMethod *
6687 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6688 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6692 MonoMethod **vtable;
6693 MonoMethod *res = NULL;
6695 MONO_CHECK_ARG_NULL (rtype);
6696 MONO_CHECK_ARG_NULL (rmethod);
6698 method = rmethod->method;
6699 klass = mono_class_from_mono_type (rtype->type);
6701 if (MONO_CLASS_IS_INTERFACE (klass))
6704 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6707 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6708 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6714 mono_class_setup_vtable (klass);
6715 vtable = klass->vtable;
6717 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6718 gboolean variance_used = FALSE;
6719 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6720 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6722 res = vtable [offs + method->slot];
6724 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6727 if (method->slot != -1)
6728 res = vtable [method->slot];
6734 return mono_method_get_object (mono_domain_get (), res, NULL);
6738 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6743 MONO_ARCH_SAVE_REGS;
6745 klass = mono_class_from_mono_type (type->type);
6746 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6748 if (enable) vtable->remote = 1;
6749 else vtable->remote = 0;
6753 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6758 MONO_ARCH_SAVE_REGS;
6760 domain = mono_object_domain (type);
6761 klass = mono_class_from_mono_type (type->type);
6763 if (klass->rank >= 1) {
6764 g_assert (klass->rank == 1);
6765 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6767 /* Bypass remoting object creation check */
6768 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6773 ves_icall_System_IO_get_temp_path (void)
6775 MONO_ARCH_SAVE_REGS;
6777 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6780 #ifndef PLATFORM_NO_DRIVEINFO
6782 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6783 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6787 ULARGE_INTEGER wapi_free_bytes_avail;
6788 ULARGE_INTEGER wapi_total_number_of_bytes;
6789 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6791 MONO_ARCH_SAVE_REGS;
6793 *error = ERROR_SUCCESS;
6794 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6795 &wapi_total_number_of_free_bytes);
6798 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6799 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6800 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6802 *free_bytes_avail = 0;
6803 *total_number_of_bytes = 0;
6804 *total_number_of_free_bytes = 0;
6805 *error = GetLastError ();
6812 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6814 MONO_ARCH_SAVE_REGS;
6816 return GetDriveType (mono_string_chars (root_path_name));
6821 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6823 MONO_ARCH_SAVE_REGS;
6825 return mono_compile_method (method);
6829 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6834 MONO_ARCH_SAVE_REGS;
6836 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6838 #if defined (HOST_WIN32)
6839 /* Avoid mixing '/' and '\\' */
6842 for (i = strlen (path) - 1; i >= 0; i--)
6843 if (path [i] == '/')
6847 mcpath = mono_string_new (mono_domain_get (), path);
6854 get_bundled_machine_config (void)
6856 const gchar *machine_config;
6858 MONO_ARCH_SAVE_REGS;
6860 machine_config = mono_get_machine_config ();
6862 if (!machine_config)
6865 return mono_string_new (mono_domain_get (), machine_config);
6869 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6874 MONO_ARCH_SAVE_REGS;
6876 path = g_path_get_dirname (mono_get_config_dir ());
6878 #if defined (HOST_WIN32)
6879 /* Avoid mixing '/' and '\\' */
6882 for (i = strlen (path) - 1; i >= 0; i--)
6883 if (path [i] == '/')
6887 ipath = mono_string_new (mono_domain_get (), path);
6894 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6896 MonoPEResourceDataEntry *entry;
6899 MONO_ARCH_SAVE_REGS;
6901 if (!assembly || !result || !size)
6906 image = assembly->assembly->image;
6907 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6911 *result = mono_image_rva_map (image, entry->rde_data_offset);
6916 *size = entry->rde_size;
6922 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6924 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6928 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6930 #if defined (HOST_WIN32)
6931 OutputDebugString (mono_string_chars (message));
6933 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6937 /* Only used for value types */
6939 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6944 MONO_ARCH_SAVE_REGS;
6946 domain = mono_object_domain (type);
6947 klass = mono_class_from_mono_type (type->type);
6949 if (mono_class_is_nullable (klass))
6950 /* No arguments -> null */
6953 return mono_object_new (domain, klass);
6956 static MonoReflectionMethod *
6957 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6959 MonoClass *klass, *parent;
6960 MonoMethod *method = m->method;
6961 MonoMethod *result = NULL;
6963 MONO_ARCH_SAVE_REGS;
6965 if (method->klass == NULL)
6968 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6969 MONO_CLASS_IS_INTERFACE (method->klass) ||
6970 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6973 klass = method->klass;
6974 if (klass->generic_class)
6975 klass = klass->generic_class->container_class;
6978 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6979 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6980 mono_class_setup_vtable (parent);
6981 if (parent->vtable_size <= method->slot)
6986 klass = klass->parent;
6991 if (klass == method->klass)
6994 result = klass->vtable [method->slot];
6995 if (result == NULL) {
6996 /* It is an abstract method */
6997 gpointer iter = NULL;
6998 while ((result = mono_class_get_methods (klass, &iter)))
6999 if (result->slot == method->slot)
7006 return mono_method_get_object (mono_domain_get (), result, NULL);
7010 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7012 MonoMethod *method = m->method;
7014 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7019 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7021 MONO_ARCH_SAVE_REGS;
7023 iter->sig = *(MonoMethodSignature**)argsp;
7025 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7026 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7029 /* FIXME: it's not documented what start is exactly... */
7033 iter->args = argsp + sizeof (gpointer);
7035 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7037 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7041 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7043 guint32 i, arg_size;
7046 MONO_ARCH_SAVE_REGS;
7048 i = iter->sig->sentinelpos + iter->next_arg;
7050 g_assert (i < iter->sig->param_count);
7052 res.type = iter->sig->params [i];
7053 res.klass = mono_class_from_mono_type (res.type);
7054 res.value = iter->args;
7055 arg_size = mono_type_stack_size (res.type, &align);
7056 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7057 if (arg_size <= sizeof (gpointer)) {
7059 int padding = arg_size - mono_type_size (res.type, &dummy);
7060 res.value = (guint8*)res.value + padding;
7063 iter->args = (char*)iter->args + arg_size;
7066 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7072 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7074 guint32 i, arg_size;
7077 MONO_ARCH_SAVE_REGS;
7079 i = iter->sig->sentinelpos + iter->next_arg;
7081 g_assert (i < iter->sig->param_count);
7083 while (i < iter->sig->param_count) {
7084 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7086 res.type = iter->sig->params [i];
7087 res.klass = mono_class_from_mono_type (res.type);
7088 /* FIXME: endianess issue... */
7089 res.value = iter->args;
7090 arg_size = mono_type_stack_size (res.type, &align);
7091 iter->args = (char*)iter->args + arg_size;
7093 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7096 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7105 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7108 MONO_ARCH_SAVE_REGS;
7110 i = iter->sig->sentinelpos + iter->next_arg;
7112 g_assert (i < iter->sig->param_count);
7114 return iter->sig->params [i];
7118 mono_TypedReference_ToObject (MonoTypedRef tref)
7120 MONO_ARCH_SAVE_REGS;
7122 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7123 MonoObject** objp = tref.value;
7127 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7131 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7133 MONO_ARCH_SAVE_REGS;
7135 if (MONO_TYPE_IS_REFERENCE (type)) {
7136 MonoObject** objp = value;
7140 return mono_value_box (mono_domain_get (), klass, value);
7144 prelink_method (MonoMethod *method)
7146 const char *exc_class, *exc_arg;
7147 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7149 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7151 mono_raise_exception(
7152 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7154 /* create the wrapper, too? */
7158 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7160 MONO_ARCH_SAVE_REGS;
7161 prelink_method (method->method);
7165 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7167 MonoClass *klass = mono_class_from_mono_type (type->type);
7169 gpointer iter = NULL;
7170 MONO_ARCH_SAVE_REGS;
7172 while ((m = mono_class_get_methods (klass, &iter)))
7176 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7178 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7179 gint32 const **exponents,
7180 gunichar2 const **digitLowerTable,
7181 gunichar2 const **digitUpperTable,
7182 gint64 const **tenPowersList,
7183 gint32 const **decHexDigits)
7185 *mantissas = Formatter_MantissaBitsTable;
7186 *exponents = Formatter_TensExponentTable;
7187 *digitLowerTable = Formatter_DigitLowerTable;
7188 *digitUpperTable = Formatter_DigitUpperTable;
7189 *tenPowersList = Formatter_TenPowersList;
7190 *decHexDigits = Formatter_DecHexDigits;
7193 /* These parameters are "readonly" in corlib/System/Char.cs */
7195 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7196 guint8 const **numeric_data,
7197 gdouble const **numeric_data_values,
7198 guint16 const **to_lower_data_low,
7199 guint16 const **to_lower_data_high,
7200 guint16 const **to_upper_data_low,
7201 guint16 const **to_upper_data_high)
7203 *category_data = CategoryData;
7204 *numeric_data = NumericData;
7205 *numeric_data_values = NumericDataValues;
7206 *to_lower_data_low = ToLowerDataLow;
7207 *to_lower_data_high = ToLowerDataHigh;
7208 *to_upper_data_low = ToUpperDataLow;
7209 *to_upper_data_high = ToUpperDataHigh;
7213 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7215 return method->method->token;
7219 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7220 * and avoid useless allocations.
7223 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7227 for (i = 0; i < type->num_mods; ++i) {
7228 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7233 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7235 for (i = 0; i < type->num_mods; ++i) {
7236 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7237 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7238 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7246 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7248 MonoType *type = param->ClassImpl->type;
7249 MonoClass *member_class = mono_object_class (param->MemberImpl);
7250 MonoMethod *method = NULL;
7253 MonoMethodSignature *sig;
7255 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7256 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7257 method = rmethod->method;
7258 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7259 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7260 if (!(method = prop->property->get))
7261 method = prop->property->set;
7264 char *type_name = mono_type_get_full_name (member_class);
7265 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7266 MonoException *ex = mono_get_exception_not_supported (msg);
7269 mono_raise_exception (ex);
7272 image = method->klass->image;
7273 pos = param->PositionImpl;
7274 sig = mono_method_signature (method);
7278 type = sig->params [pos];
7280 return type_array_from_modifiers (image, type, optional);
7284 get_property_type (MonoProperty *prop)
7286 MonoMethodSignature *sig;
7288 sig = mono_method_signature (prop->get);
7290 } else if (prop->set) {
7291 sig = mono_method_signature (prop->set);
7292 return sig->params [sig->param_count - 1];
7298 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7300 MonoType *type = get_property_type (property->property);
7301 MonoImage *image = property->klass->image;
7305 return type_array_from_modifiers (image, type, optional);
7309 *Construct a MonoType suited to be used to decode a constant blob object.
7311 * @type is the target type which will be constructed
7312 * @blob_type is the blob type, for example, that comes from the constant table
7313 * @real_type is the expected constructed type.
7316 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7318 type->type = blob_type;
7319 type->data.klass = NULL;
7320 if (blob_type == MONO_TYPE_CLASS)
7321 type->data.klass = mono_defaults.object_class;
7322 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7323 /* For enums, we need to use the base type */
7324 type->type = MONO_TYPE_VALUETYPE;
7325 type->data.klass = mono_class_from_mono_type (real_type);
7327 type->data.klass = mono_class_from_mono_type (real_type);
7331 property_info_get_default_value (MonoReflectionProperty *property)
7334 MonoProperty *prop = property->property;
7335 MonoType *type = get_property_type (prop);
7336 MonoDomain *domain = mono_object_domain (property);
7337 MonoTypeEnum def_type;
7338 const char *def_value;
7341 g_assert (!prop->parent->image->dynamic);
7343 mono_class_init (prop->parent);
7345 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7346 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7348 def_value = mono_class_get_property_default_value (prop, &def_type);
7350 mono_type_from_blob_type (&blob_type, def_type, type);
7351 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7357 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7359 MonoCustomAttrInfo *cinfo;
7362 cinfo = mono_reflection_get_custom_attrs_info (obj);
7365 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7367 mono_custom_attrs_free (cinfo);
7372 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7374 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7376 if (mono_loader_get_last_error ()) {
7377 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7378 g_assert_not_reached ();
7387 ves_icall_Mono_Runtime_GetDisplayName (void)
7390 MonoString *display_name;
7392 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7393 display_name = mono_string_new (mono_domain_get (), info);
7395 return display_name;
7399 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7401 MonoString *message;
7405 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7406 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7409 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7411 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7419 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7420 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7421 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7422 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7423 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7424 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7425 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7426 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7430 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7435 gunichar2 last, prev_last, prev2_last;
7443 last = prev_last = 0, prev2_last = 0;
7444 for (i = 0; i < ilength; i++) {
7446 if (c >= sizeof (dbase64)) {
7447 exc = mono_exception_from_name_msg (mono_get_corlib (),
7448 "System", "FormatException",
7449 "Invalid character found.");
7450 mono_raise_exception (exc);
7451 } else if (isspace (c)) {
7454 prev2_last = prev_last;
7460 olength = ilength - ignored;
7462 if (allowWhitespaceOnly && olength == 0) {
7463 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7466 if ((olength & 3) != 0 || olength <= 0) {
7467 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7468 "FormatException", "Invalid length.");
7469 mono_raise_exception (exc);
7472 if (prev2_last == '=') {
7473 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7474 mono_raise_exception (exc);
7477 olength = (olength * 3) / 4;
7481 if (prev_last == '=')
7484 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7485 res_ptr = mono_array_addr (result, guchar, 0);
7486 for (i = 0; i < ilength; ) {
7489 for (k = 0; k < 4 && i < ilength;) {
7495 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7496 exc = mono_exception_from_name_msg (mono_get_corlib (),
7497 "System", "FormatException",
7498 "Invalid character found.");
7499 mono_raise_exception (exc);
7504 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7506 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7508 *res_ptr++ = (b [2] << 6) | b [3];
7510 while (i < ilength && isspace (start [i]))
7518 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7520 MONO_ARCH_SAVE_REGS;
7522 return base64_to_byte_array (mono_string_chars (str),
7523 mono_string_length (str), allowWhitespaceOnly);
7527 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7529 MONO_ARCH_SAVE_REGS;
7531 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7535 #define ICALL_TYPE(id,name,first)
7536 #define ICALL(id,name,func) Icall_ ## id,
7539 #include "metadata/icall-def.h"
7545 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7546 #define ICALL(id,name,func)
7548 #include "metadata/icall-def.h"
7554 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7555 #define ICALL(id,name,func)
7557 guint16 first_icall;
7560 static const IcallTypeDesc
7561 icall_type_descs [] = {
7562 #include "metadata/icall-def.h"
7566 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7569 #define ICALL_TYPE(id,name,first)
7572 #ifdef HAVE_ARRAY_ELEM_INIT
7573 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7574 #define MSGSTRFIELD1(line) str##line
7576 static const struct msgstrtn_t {
7577 #define ICALL(id,name,func)
7579 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7580 #include "metadata/icall-def.h"
7582 } icall_type_names_str = {
7583 #define ICALL_TYPE(id,name,first) (name),
7584 #include "metadata/icall-def.h"
7587 static const guint16 icall_type_names_idx [] = {
7588 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7589 #include "metadata/icall-def.h"
7592 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7594 static const struct msgstr_t {
7596 #define ICALL_TYPE(id,name,first)
7597 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7598 #include "metadata/icall-def.h"
7600 } icall_names_str = {
7601 #define ICALL(id,name,func) (name),
7602 #include "metadata/icall-def.h"
7605 static const guint16 icall_names_idx [] = {
7606 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7607 #include "metadata/icall-def.h"
7610 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7616 #define ICALL_TYPE(id,name,first) name,
7617 #define ICALL(id,name,func)
7618 static const char* const
7619 icall_type_names [] = {
7620 #include "metadata/icall-def.h"
7624 #define icall_type_name_get(id) (icall_type_names [(id)])
7628 #define ICALL_TYPE(id,name,first)
7629 #define ICALL(id,name,func) name,
7630 static const char* const
7632 #include "metadata/icall-def.h"
7635 #define icall_name_get(id) icall_names [(id)]
7637 #endif /* !HAVE_ARRAY_ELEM_INIT */
7641 #define ICALL_TYPE(id,name,first)
7642 #define ICALL(id,name,func) func,
7643 static const gconstpointer
7644 icall_functions [] = {
7645 #include "metadata/icall-def.h"
7649 static GHashTable *icall_hash = NULL;
7650 static GHashTable *jit_icall_hash_name = NULL;
7651 static GHashTable *jit_icall_hash_addr = NULL;
7654 mono_icall_init (void)
7658 /* check that tables are sorted: disable in release */
7661 const char *prev_class = NULL;
7662 const char *prev_method;
7664 for (i = 0; i < Icall_type_num; ++i) {
7665 const IcallTypeDesc *desc;
7668 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7669 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7670 prev_class = icall_type_name_get (i);
7671 desc = &icall_type_descs [i];
7672 num_icalls = icall_desc_num_icalls (desc);
7673 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7674 for (j = 0; j < num_icalls; ++j) {
7675 const char *methodn = icall_name_get (desc->first_icall + j);
7676 if (prev_method && strcmp (prev_method, methodn) >= 0)
7677 g_print ("method %s should come before method %s\n", methodn, prev_method);
7678 prev_method = methodn;
7683 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7687 mono_icall_cleanup (void)
7689 g_hash_table_destroy (icall_hash);
7690 g_hash_table_destroy (jit_icall_hash_name);
7691 g_hash_table_destroy (jit_icall_hash_addr);
7695 mono_add_internal_call (const char *name, gconstpointer method)
7697 mono_loader_lock ();
7699 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7701 mono_loader_unlock ();
7704 #ifdef HAVE_ARRAY_ELEM_INIT
7706 compare_method_imap (const void *key, const void *elem)
7708 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7709 return strcmp (key, method_name);
7713 find_method_icall (const IcallTypeDesc *imap, const char *name)
7715 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7718 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7722 compare_class_imap (const void *key, const void *elem)
7724 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7725 return strcmp (key, class_name);
7728 static const IcallTypeDesc*
7729 find_class_icalls (const char *name)
7731 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7734 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7739 compare_method_imap (const void *key, const void *elem)
7741 const char** method_name = (const char**)elem;
7742 return strcmp (key, *method_name);
7746 find_method_icall (const IcallTypeDesc *imap, const char *name)
7748 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7751 return (gpointer)icall_functions [(nameslot - icall_names)];
7755 compare_class_imap (const void *key, const void *elem)
7757 const char** class_name = (const char**)elem;
7758 return strcmp (key, *class_name);
7761 static const IcallTypeDesc*
7762 find_class_icalls (const char *name)
7764 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7767 return &icall_type_descs [nameslot - icall_type_names];
7773 * we should probably export this as an helper (handle nested types).
7774 * Returns the number of chars written in buf.
7777 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7779 int nspacelen, cnamelen;
7780 nspacelen = strlen (klass->name_space);
7781 cnamelen = strlen (klass->name);
7782 if (nspacelen + cnamelen + 2 > bufsize)
7785 memcpy (buf, klass->name_space, nspacelen);
7786 buf [nspacelen ++] = '.';
7788 memcpy (buf + nspacelen, klass->name, cnamelen);
7789 buf [nspacelen + cnamelen] = 0;
7790 return nspacelen + cnamelen;
7794 mono_lookup_internal_call (MonoMethod *method)
7799 int typelen = 0, mlen, siglen;
7801 const IcallTypeDesc *imap;
7803 g_assert (method != NULL);
7805 if (method->is_inflated)
7806 method = ((MonoMethodInflated *) method)->declaring;
7808 if (method->klass->nested_in) {
7809 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7813 mname [pos++] = '/';
7816 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7822 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7827 imap = find_class_icalls (mname);
7829 mname [typelen] = ':';
7830 mname [typelen + 1] = ':';
7832 mlen = strlen (method->name);
7833 memcpy (mname + typelen + 2, method->name, mlen);
7834 sigstart = mname + typelen + 2 + mlen;
7837 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7838 siglen = strlen (tmpsig);
7839 if (typelen + mlen + siglen + 6 > sizeof (mname))
7842 memcpy (sigstart + 1, tmpsig, siglen);
7843 sigstart [siglen + 1] = ')';
7844 sigstart [siglen + 2] = 0;
7847 mono_loader_lock ();
7849 res = g_hash_table_lookup (icall_hash, mname);
7851 mono_loader_unlock ();
7854 /* try without signature */
7856 res = g_hash_table_lookup (icall_hash, mname);
7858 mono_loader_unlock ();
7862 /* it wasn't found in the static call tables */
7864 mono_loader_unlock ();
7867 res = find_method_icall (imap, sigstart - mlen);
7869 mono_loader_unlock ();
7872 /* try _with_ signature */
7874 res = find_method_icall (imap, sigstart - mlen);
7876 mono_loader_unlock ();
7880 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7881 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7882 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7883 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7884 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");
7885 g_print ("If you see other errors or faults after this message they are probably related\n");
7886 g_print ("and you need to fix your mono install first.\n");
7888 mono_loader_unlock ();
7894 type_from_typename (char *typename)
7896 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7898 if (!strcmp (typename, "int"))
7899 klass = mono_defaults.int_class;
7900 else if (!strcmp (typename, "ptr"))
7901 klass = mono_defaults.int_class;
7902 else if (!strcmp (typename, "void"))
7903 klass = mono_defaults.void_class;
7904 else if (!strcmp (typename, "int32"))
7905 klass = mono_defaults.int32_class;
7906 else if (!strcmp (typename, "uint32"))
7907 klass = mono_defaults.uint32_class;
7908 else if (!strcmp (typename, "int8"))
7909 klass = mono_defaults.sbyte_class;
7910 else if (!strcmp (typename, "uint8"))
7911 klass = mono_defaults.byte_class;
7912 else if (!strcmp (typename, "int16"))
7913 klass = mono_defaults.int16_class;
7914 else if (!strcmp (typename, "uint16"))
7915 klass = mono_defaults.uint16_class;
7916 else if (!strcmp (typename, "long"))
7917 klass = mono_defaults.int64_class;
7918 else if (!strcmp (typename, "ulong"))
7919 klass = mono_defaults.uint64_class;
7920 else if (!strcmp (typename, "float"))
7921 klass = mono_defaults.single_class;
7922 else if (!strcmp (typename, "double"))
7923 klass = mono_defaults.double_class;
7924 else if (!strcmp (typename, "object"))
7925 klass = mono_defaults.object_class;
7926 else if (!strcmp (typename, "obj"))
7927 klass = mono_defaults.object_class;
7928 else if (!strcmp (typename, "string"))
7929 klass = mono_defaults.string_class;
7930 else if (!strcmp (typename, "bool"))
7931 klass = mono_defaults.boolean_class;
7932 else if (!strcmp (typename, "boolean"))
7933 klass = mono_defaults.boolean_class;
7935 g_error ("%s", typename);
7936 g_assert_not_reached ();
7938 return &klass->byval_arg;
7941 MonoMethodSignature*
7942 mono_create_icall_signature (const char *sigstr)
7947 MonoMethodSignature *res;
7949 mono_loader_lock ();
7950 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7952 mono_loader_unlock ();
7956 parts = g_strsplit (sigstr, " ", 256);
7965 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7970 * Under windows, the default pinvoke calling convention is STDCALL but
7973 res->call_convention = MONO_CALL_C;
7976 res->ret = type_from_typename (parts [0]);
7977 for (i = 1; i < len; ++i) {
7978 res->params [i - 1] = type_from_typename (parts [i]);
7983 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7985 mono_loader_unlock ();
7991 mono_find_jit_icall_by_name (const char *name)
7993 MonoJitICallInfo *info;
7994 g_assert (jit_icall_hash_name);
7996 mono_loader_lock ();
7997 info = g_hash_table_lookup (jit_icall_hash_name, name);
7998 mono_loader_unlock ();
8003 mono_find_jit_icall_by_addr (gconstpointer addr)
8005 MonoJitICallInfo *info;
8006 g_assert (jit_icall_hash_addr);
8008 mono_loader_lock ();
8009 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8010 mono_loader_unlock ();
8016 * mono_get_jit_icall_info:
8018 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8019 * caller should access it while holding the loader lock.
8022 mono_get_jit_icall_info (void)
8024 return jit_icall_hash_name;
8028 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8030 mono_loader_lock ();
8031 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8032 mono_loader_unlock ();
8036 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8038 MonoJitICallInfo *info;
8043 mono_loader_lock ();
8045 if (!jit_icall_hash_name) {
8046 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8047 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8050 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8051 g_warning ("jit icall already defined \"%s\"\n", name);
8052 g_assert_not_reached ();
8055 info = g_new0 (MonoJitICallInfo, 1);
8062 info->wrapper = func;
8064 info->wrapper = NULL;
8067 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8068 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8070 mono_loader_unlock ();