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)
3127 MONO_ARCH_SAVE_REGS;
3129 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3133 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3135 gpointer tdata = (char *)this + sizeof (MonoObject);
3136 gpointer odata = (char *)other + sizeof (MonoObject);
3137 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3138 g_assert (basetype);
3140 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3141 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3142 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3145 return me > other ? 1 : -1; \
3148 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3149 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3150 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3153 return me - other; \
3156 switch (basetype->type) {
3158 COMPARE_ENUM_VALUES (guint8);
3160 COMPARE_ENUM_VALUES (gint8);
3161 case MONO_TYPE_CHAR:
3163 COMPARE_ENUM_VALUES_RANGE (guint16);
3165 COMPARE_ENUM_VALUES (gint16);
3167 COMPARE_ENUM_VALUES (guint32);
3169 COMPARE_ENUM_VALUES (gint32);
3171 COMPARE_ENUM_VALUES (guint64);
3173 COMPARE_ENUM_VALUES (gint64);
3175 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3177 #undef COMPARE_ENUM_VALUES_RANGE
3178 #undef COMPARE_ENUM_VALUES
3183 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3185 gpointer data = (char *)this + sizeof (MonoObject);
3186 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3187 g_assert (basetype);
3189 switch (basetype->type) {
3191 return *((gint8*)data);
3193 return *((guint8*)data);
3194 case MONO_TYPE_CHAR:
3196 return *((guint16*)data);
3199 return *((gint16*)data);
3201 return *((guint32*)data);
3203 return *((gint32*)data);
3205 case MONO_TYPE_I8: {
3206 gint64 value = *((gint64*)data);
3207 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3210 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3216 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3218 MonoDomain *domain = mono_object_domain (type);
3219 MonoClass *enumc = mono_class_from_mono_type (type->type);
3220 guint j = 0, nvalues, crow;
3222 MonoClassField *field;
3224 MONO_ARCH_SAVE_REGS;
3226 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3227 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3228 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3229 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3233 while ((field = mono_class_get_fields (enumc, &iter))) {
3236 MonoTypeEnum def_type;
3238 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3240 if (mono_field_is_deleted (field))
3242 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3244 p = mono_class_get_field_default_value (field, &def_type);
3245 len = mono_metadata_decode_blob_size (p, &p);
3246 switch (mono_class_enum_basetype (enumc)->type) {
3249 mono_array_set (info->values, gchar, j, *p);
3251 case MONO_TYPE_CHAR:
3254 mono_array_set (info->values, gint16, j, read16 (p));
3258 mono_array_set (info->values, gint32, j, read32 (p));
3262 mono_array_set (info->values, gint64, j, read64 (p));
3265 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3272 BFLAGS_IgnoreCase = 1,
3273 BFLAGS_DeclaredOnly = 2,
3274 BFLAGS_Instance = 4,
3276 BFLAGS_Public = 0x10,
3277 BFLAGS_NonPublic = 0x20,
3278 BFLAGS_FlattenHierarchy = 0x40,
3279 BFLAGS_InvokeMethod = 0x100,
3280 BFLAGS_CreateInstance = 0x200,
3281 BFLAGS_GetField = 0x400,
3282 BFLAGS_SetField = 0x800,
3283 BFLAGS_GetProperty = 0x1000,
3284 BFLAGS_SetProperty = 0x2000,
3285 BFLAGS_ExactBinding = 0x10000,
3286 BFLAGS_SuppressChangeType = 0x20000,
3287 BFLAGS_OptionalParamBinding = 0x40000
3290 static MonoReflectionField *
3291 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3294 MonoClass *startklass, *klass;
3296 MonoClassField *field;
3299 int (*compare_func) (const char *s1, const char *s2) = NULL;
3300 domain = ((MonoObject *)type)->vtable->domain;
3301 klass = startklass = mono_class_from_mono_type (type->type);
3303 MONO_ARCH_SAVE_REGS;
3306 mono_raise_exception (mono_get_exception_argument_null ("name"));
3307 if (type->type->byref)
3310 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3313 if (klass->exception_type != MONO_EXCEPTION_NONE)
3314 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3317 while ((field = mono_class_get_fields (klass, &iter))) {
3320 if (field->type == NULL)
3322 if (mono_field_is_deleted (field))
3324 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3325 if (bflags & BFLAGS_Public)
3327 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3328 if (bflags & BFLAGS_NonPublic) {
3335 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3336 if (bflags & BFLAGS_Static)
3337 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3340 if (bflags & BFLAGS_Instance)
3347 utf8_name = mono_string_to_utf8 (name);
3349 if (compare_func (mono_field_get_name (field), utf8_name)) {
3355 return mono_field_get_object (domain, klass, field);
3357 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3364 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3367 MonoClass *startklass, *klass, *refklass;
3372 MonoClassField *field;
3373 MonoPtrArray tmp_array;
3375 MONO_ARCH_SAVE_REGS;
3377 domain = ((MonoObject *)type)->vtable->domain;
3378 if (type->type->byref)
3379 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3380 klass = startklass = mono_class_from_mono_type (type->type);
3381 refklass = mono_class_from_mono_type (reftype->type);
3383 mono_ptr_array_init (tmp_array, 2);
3386 if (klass->exception_type != MONO_EXCEPTION_NONE)
3387 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3390 while ((field = mono_class_get_fields (klass, &iter))) {
3392 if (mono_field_is_deleted (field))
3394 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3395 if (bflags & BFLAGS_Public)
3397 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3398 if (bflags & BFLAGS_NonPublic) {
3405 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3406 if (bflags & BFLAGS_Static)
3407 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3410 if (bflags & BFLAGS_Instance)
3416 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3417 mono_ptr_array_append (tmp_array, member);
3419 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3422 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3424 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3425 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3427 mono_ptr_array_destroy (tmp_array);
3433 method_nonpublic (MonoMethod* method, gboolean start_klass)
3435 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3436 case METHOD_ATTRIBUTE_ASSEM:
3437 return (start_klass || mono_defaults.generic_ilist_class);
3438 case METHOD_ATTRIBUTE_PRIVATE:
3440 case METHOD_ATTRIBUTE_PUBLIC:
3448 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3450 static MonoClass *MethodInfo_array;
3452 MonoClass *startklass, *klass, *refklass;
3457 int i, len, match, nslots;
3458 /*FIXME, use MonoBitSet*/
3459 guint32 method_slots_default [8];
3460 guint32 *method_slots = NULL;
3461 gchar *mname = NULL;
3462 int (*compare_func) (const char *s1, const char *s2) = NULL;
3463 MonoVTable *array_vtable;
3465 MonoPtrArray tmp_array;
3467 MONO_ARCH_SAVE_REGS;
3469 mono_ptr_array_init (tmp_array, 4);
3471 if (!MethodInfo_array) {
3472 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3473 mono_memory_barrier ();
3474 MethodInfo_array = klass;
3477 domain = ((MonoObject *)type)->vtable->domain;
3478 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3479 if (type->type->byref)
3480 return mono_array_new_specific (array_vtable, 0);
3481 klass = startklass = mono_class_from_mono_type (type->type);
3482 refklass = mono_class_from_mono_type (reftype->type);
3485 mname = mono_string_to_utf8 (name);
3486 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3489 /* An optimization for calls made from Delegate:CreateDelegate () */
3490 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3491 method = mono_get_delegate_invoke (klass);
3492 if (mono_loader_get_last_error ())
3495 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3497 res = mono_array_new_specific (array_vtable, 1);
3498 mono_array_setref (res, 0, member);
3503 mono_class_setup_vtable (klass);
3504 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3507 if (is_generic_parameter (type->type))
3508 nslots = mono_class_get_vtable_size (klass->parent);
3510 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3511 if (nslots >= sizeof (method_slots_default) * 8) {
3512 method_slots = g_new0 (guint32, nslots / 32 + 1);
3514 method_slots = method_slots_default;
3515 memset (method_slots, 0, sizeof (method_slots_default));
3518 mono_class_setup_vtable (klass);
3519 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3523 while ((method = mono_class_get_methods (klass, &iter))) {
3525 if (method->slot != -1) {
3526 g_assert (method->slot < nslots);
3527 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3529 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3530 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3533 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3535 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3536 if (bflags & BFLAGS_Public)
3538 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3544 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3545 if (bflags & BFLAGS_Static)
3546 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3549 if (bflags & BFLAGS_Instance)
3557 if (compare_func (mname, method->name))
3563 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3565 mono_ptr_array_append (tmp_array, member);
3567 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3571 if (method_slots != method_slots_default)
3572 g_free (method_slots);
3574 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3576 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3577 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3579 mono_ptr_array_destroy (tmp_array);
3584 if (method_slots != method_slots_default)
3585 g_free (method_slots);
3586 mono_ptr_array_destroy (tmp_array);
3587 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3588 ex = mono_class_get_exception_for_failure (klass);
3590 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3591 mono_loader_clear_error ();
3593 mono_raise_exception (ex);
3598 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3601 static MonoClass *System_Reflection_ConstructorInfo;
3602 MonoClass *startklass, *klass, *refklass;
3607 gpointer iter = NULL;
3608 MonoPtrArray tmp_array;
3610 MONO_ARCH_SAVE_REGS;
3612 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3614 domain = ((MonoObject *)type)->vtable->domain;
3615 if (type->type->byref)
3616 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3617 klass = startklass = mono_class_from_mono_type (type->type);
3618 refklass = mono_class_from_mono_type (reftype->type);
3620 if (klass->exception_type != MONO_EXCEPTION_NONE)
3621 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3623 if (!System_Reflection_ConstructorInfo)
3624 System_Reflection_ConstructorInfo = mono_class_from_name (
3625 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3628 while ((method = mono_class_get_methods (klass, &iter))) {
3630 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3632 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3633 if (bflags & BFLAGS_Public)
3636 if (bflags & BFLAGS_NonPublic)
3642 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3643 if (bflags & BFLAGS_Static)
3644 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3647 if (bflags & BFLAGS_Instance)
3653 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3655 mono_ptr_array_append (tmp_array, member);
3658 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3660 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3661 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3663 mono_ptr_array_destroy (tmp_array);
3669 property_hash (gconstpointer data)
3671 MonoProperty *prop = (MonoProperty*)data;
3673 return g_str_hash (prop->name);
3677 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3679 // Properties are hide-by-name-and-signature
3680 if (!g_str_equal (prop1->name, prop2->name))
3683 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3685 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3691 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3696 return method_nonpublic (accessor, start_klass);
3700 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3703 static MonoClass *System_Reflection_PropertyInfo;
3704 MonoClass *startklass, *klass;
3710 gchar *propname = NULL;
3711 int (*compare_func) (const char *s1, const char *s2) = NULL;
3713 GHashTable *properties;
3714 MonoPtrArray tmp_array;
3716 MONO_ARCH_SAVE_REGS;
3718 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3720 if (!System_Reflection_PropertyInfo)
3721 System_Reflection_PropertyInfo = mono_class_from_name (
3722 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3724 domain = ((MonoObject *)type)->vtable->domain;
3725 if (type->type->byref)
3726 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3727 klass = startklass = mono_class_from_mono_type (type->type);
3729 propname = mono_string_to_utf8 (name);
3730 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3733 mono_class_setup_vtable (klass);
3735 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3737 mono_class_setup_vtable (klass);
3738 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3739 g_hash_table_destroy (properties);
3742 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3746 while ((prop = mono_class_get_properties (klass, &iter))) {
3752 flags = method->flags;
3755 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3756 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3757 if (bflags & BFLAGS_Public)
3759 } else if (bflags & BFLAGS_NonPublic) {
3760 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3761 property_accessor_nonpublic(prop->set, startklass == klass)) {
3768 if (flags & METHOD_ATTRIBUTE_STATIC) {
3769 if (bflags & BFLAGS_Static)
3770 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3773 if (bflags & BFLAGS_Instance)
3782 if (compare_func (propname, prop->name))
3786 if (g_hash_table_lookup (properties, prop))
3789 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3791 g_hash_table_insert (properties, prop, prop);
3793 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3796 g_hash_table_destroy (properties);
3799 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3800 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3801 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3803 mono_ptr_array_destroy (tmp_array);
3808 static MonoReflectionEvent *
3809 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3812 MonoClass *klass, *startklass;
3818 MONO_ARCH_SAVE_REGS;
3820 event_name = mono_string_to_utf8 (name);
3821 if (type->type->byref)
3823 klass = startklass = mono_class_from_mono_type (type->type);
3824 domain = mono_object_domain (type);
3827 if (klass->exception_type != MONO_EXCEPTION_NONE)
3828 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3831 while ((event = mono_class_get_events (klass, &iter))) {
3832 if (strcmp (event->name, event_name))
3835 method = event->add;
3837 method = event->remove;
3839 method = event->raise;
3841 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3842 if (!(bflags & BFLAGS_Public))
3845 if (!(bflags & BFLAGS_NonPublic))
3847 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3851 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3852 if (!(bflags & BFLAGS_Static))
3854 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3857 if (!(bflags & BFLAGS_Instance))
3861 if (!(bflags & BFLAGS_NonPublic))
3864 g_free (event_name);
3865 return mono_event_get_object (domain, startklass, event);
3868 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3871 g_free (event_name);
3876 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3879 static MonoClass *System_Reflection_EventInfo;
3880 MonoClass *startklass, *klass;
3887 MonoPtrArray tmp_array;
3889 MONO_ARCH_SAVE_REGS;
3891 mono_ptr_array_init (tmp_array, 4);
3893 if (!System_Reflection_EventInfo)
3894 System_Reflection_EventInfo = mono_class_from_name (
3895 mono_defaults.corlib, "System.Reflection", "EventInfo");
3897 domain = mono_object_domain (type);
3898 if (type->type->byref)
3899 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3900 klass = startklass = mono_class_from_mono_type (type->type);
3903 if (klass->exception_type != MONO_EXCEPTION_NONE)
3904 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3907 while ((event = mono_class_get_events (klass, &iter))) {
3909 method = event->add;
3911 method = event->remove;
3913 method = event->raise;
3915 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3916 if (bflags & BFLAGS_Public)
3918 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3919 if (bflags & BFLAGS_NonPublic)
3924 if (bflags & BFLAGS_NonPublic)
3930 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3931 if (bflags & BFLAGS_Static)
3932 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3935 if (bflags & BFLAGS_Instance)
3940 if (bflags & BFLAGS_Instance)
3944 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3946 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3949 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3951 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3952 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3954 mono_ptr_array_destroy (tmp_array);
3959 static MonoReflectionType *
3960 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3968 MONO_ARCH_SAVE_REGS;
3971 mono_raise_exception (mono_get_exception_argument_null ("name"));
3973 domain = ((MonoObject *)type)->vtable->domain;
3974 if (type->type->byref)
3976 klass = mono_class_from_mono_type (type->type);
3977 str = mono_string_to_utf8 (name);
3980 if (klass->exception_type != MONO_EXCEPTION_NONE)
3981 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3984 * If a nested type is generic, return its generic type definition.
3985 * Note that this means that the return value is essentially a
3986 * nested type of the generic type definition of @klass.
3988 * A note in MSDN claims that a generic type definition can have
3989 * nested types that aren't generic. In any case, the container of that
3990 * nested type would be the generic type definition.
3992 if (klass->generic_class)
3993 klass = klass->generic_class->container_class;
3996 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3998 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3999 if (bflags & BFLAGS_Public)
4002 if (bflags & BFLAGS_NonPublic)
4007 if (strcmp (nested->name, str) == 0){
4009 return mono_type_get_object (domain, &nested->byval_arg);
4012 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4019 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4028 MonoPtrArray tmp_array;
4030 MONO_ARCH_SAVE_REGS;
4032 domain = ((MonoObject *)type)->vtable->domain;
4033 if (type->type->byref)
4034 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4035 klass = mono_class_from_mono_type (type->type);
4036 if (klass->exception_type != MONO_EXCEPTION_NONE)
4037 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4040 * If a nested type is generic, return its generic type definition.
4041 * Note that this means that the return value is essentially the set
4042 * of nested types of the generic type definition of @klass.
4044 * A note in MSDN claims that a generic type definition can have
4045 * nested types that aren't generic. In any case, the container of that
4046 * nested type would be the generic type definition.
4048 if (klass->generic_class)
4049 klass = klass->generic_class->container_class;
4051 mono_ptr_array_init (tmp_array, 1);
4053 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4055 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4056 if (bflags & BFLAGS_Public)
4059 if (bflags & BFLAGS_NonPublic)
4064 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4065 mono_ptr_array_append (tmp_array, member);
4068 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4070 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4071 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4073 mono_ptr_array_destroy (tmp_array);
4078 static MonoReflectionType*
4079 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4082 MonoType *type = NULL;
4083 MonoTypeNameParse info;
4084 gboolean type_resolve;
4086 MONO_ARCH_SAVE_REGS;
4088 /* On MS.NET, this does not fire a TypeResolve event */
4089 type_resolve = TRUE;
4090 str = mono_string_to_utf8 (name);
4091 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4092 if (!mono_reflection_parse_type (str, &info)) {
4094 mono_reflection_free_type_info (&info);
4095 if (throwOnError) /* uhm: this is a parse error, though... */
4096 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4097 /*g_print ("failed parse\n");*/
4101 if (info.assembly.name) {
4103 mono_reflection_free_type_info (&info);
4105 /* 1.0 and 2.0 throw different exceptions */
4106 if (mono_defaults.generic_ilist_class)
4107 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4109 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4114 if (module != NULL) {
4116 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4121 if (assembly->assembly->dynamic) {
4122 /* Enumerate all modules */
4123 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4127 if (abuilder->modules) {
4128 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4129 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4130 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4136 if (!type && abuilder->loaded_modules) {
4137 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4138 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4139 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4146 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4148 mono_reflection_free_type_info (&info);
4150 MonoException *e = NULL;
4153 e = mono_get_exception_type_load (name, NULL);
4155 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4156 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4158 mono_loader_clear_error ();
4161 mono_raise_exception (e);
4166 if (type->type == MONO_TYPE_CLASS) {
4167 MonoClass *klass = mono_type_get_class (type);
4169 if (mono_is_security_manager_active () && !klass->exception_type)
4170 /* Some security problems are detected during generic vtable construction */
4171 mono_class_setup_vtable (klass);
4172 /* need to report exceptions ? */
4173 if (throwOnError && klass->exception_type) {
4174 /* report SecurityException (or others) that occured when loading the assembly */
4175 MonoException *exc = mono_class_get_exception_for_failure (klass);
4176 mono_loader_clear_error ();
4177 mono_raise_exception (exc);
4178 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4183 /* g_print ("got it\n"); */
4184 return mono_type_get_object (mono_object_domain (assembly), type);
4188 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4191 gchar *shadow_ini_file;
4194 /* Check for shadow-copied assembly */
4195 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4196 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4198 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4199 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4205 g_free (shadow_ini_file);
4206 if (content != NULL) {
4209 *filename = content;
4217 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4219 MonoDomain *domain = mono_object_domain (assembly);
4220 MonoAssembly *mass = assembly->assembly;
4221 MonoString *res = NULL;
4226 MONO_ARCH_SAVE_REGS;
4228 if (g_path_is_absolute (mass->image->name)) {
4229 absolute = g_strdup (mass->image->name);
4230 dirname = g_path_get_dirname (absolute);
4232 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4233 dirname = g_strdup (mass->basedir);
4236 replace_shadow_path (domain, dirname, &absolute);
4241 for (i = strlen (absolute) - 1; i >= 0; i--)
4242 if (absolute [i] == '\\')
4247 uri = g_filename_to_uri (absolute, NULL, NULL);
4249 const char *prepend = "file://";
4251 if (*absolute == '/' && *(absolute + 1) == '/') {
4254 prepend = "file:///";
4257 uri = g_strconcat (prepend, absolute, NULL);
4261 res = mono_string_new (domain, uri);
4269 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4271 MonoAssembly *mass = assembly->assembly;
4273 MONO_ARCH_SAVE_REGS;
4275 return mass->in_gac;
4278 static MonoReflectionAssembly*
4279 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4283 MonoImageOpenStatus status;
4285 MONO_ARCH_SAVE_REGS;
4287 name = mono_string_to_utf8 (mname);
4288 res = mono_assembly_load_with_partial_name (name, &status);
4294 return mono_assembly_get_object (mono_domain_get (), res);
4298 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4300 MonoDomain *domain = mono_object_domain (assembly);
4303 MONO_ARCH_SAVE_REGS;
4305 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4311 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4313 MONO_ARCH_SAVE_REGS;
4315 return assembly->assembly->ref_only;
4319 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4321 MonoDomain *domain = mono_object_domain (assembly);
4323 MONO_ARCH_SAVE_REGS;
4325 return mono_string_new (domain, assembly->assembly->image->version);
4328 static MonoReflectionMethod*
4329 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4331 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4333 MONO_ARCH_SAVE_REGS;
4337 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4340 static MonoReflectionModule*
4341 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4343 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4347 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4349 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4350 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4354 MONO_ARCH_SAVE_REGS;
4356 for (i = 0; i < table->rows; ++i) {
4357 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4358 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4364 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4366 static MonoClass *System_Version = NULL;
4367 static MonoMethod *create_version = NULL;
4371 if (!System_Version) {
4372 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4373 g_assert (System_Version);
4376 if (!create_version) {
4377 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4378 create_version = mono_method_desc_search_in_class (desc, System_Version);
4379 g_assert (create_version);
4380 mono_method_desc_free (desc);
4386 args [3] = &revision;
4387 result = mono_object_new (domain, System_Version);
4388 mono_runtime_invoke (create_version, result, args, NULL);
4394 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4396 static MonoClass *System_Reflection_AssemblyName;
4398 MonoDomain *domain = mono_object_domain (assembly);
4400 static MonoMethod *create_culture = NULL;
4401 MonoImage *image = assembly->assembly->image;
4404 MONO_ARCH_SAVE_REGS;
4406 if (!System_Reflection_AssemblyName)
4407 System_Reflection_AssemblyName = mono_class_from_name (
4408 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4410 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4413 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4415 if (count > 0 && !create_culture) {
4416 MonoMethodDesc *desc = mono_method_desc_new (
4417 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4418 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4419 g_assert (create_culture);
4420 mono_method_desc_free (desc);
4423 for (i = 0; i < count; i++) {
4424 MonoReflectionAssemblyName *aname;
4425 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4427 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4429 aname = (MonoReflectionAssemblyName *) mono_object_new (
4430 domain, System_Reflection_AssemblyName);
4432 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4434 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4435 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4436 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4437 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4438 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4439 aname->versioncompat = 1; /* SameMachine (default) */
4440 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4441 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4443 if (create_culture) {
4445 MonoBoolean assembly_ref = 1;
4446 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4447 args [1] = &assembly_ref;
4448 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4451 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4452 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4453 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4455 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4456 /* public key token isn't copied - the class library will
4457 automatically generate it from the public key if required */
4458 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4459 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4461 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4462 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4465 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4468 /* note: this function doesn't return the codebase on purpose (i.e. it can
4469 be used under partial trust as path information isn't present). */
4471 mono_array_setref (result, i, aname);
4482 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4484 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4486 mono_array_setref (info->res, info->idx, name);
4491 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4493 MonoImage *img = assembly->assembly->image;
4498 MONO_ARCH_SAVE_REGS;
4500 mono_image_lock (img);
4501 mono_image_init_name_cache (img);
4504 len = g_hash_table_size (img->name_cache);
4505 mono_image_unlock (img);
4507 /*we can't create objects holding the image lock */
4508 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4510 mono_image_lock (img);
4511 /*len might have changed, create a new array*/
4512 if (len != g_hash_table_size (img->name_cache))
4517 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4518 mono_image_unlock (img);
4523 /* move this in some file in mono/util/ */
4525 g_concat_dir_and_file (const char *dir, const char *file)
4527 g_return_val_if_fail (dir != NULL, NULL);
4528 g_return_val_if_fail (file != NULL, NULL);
4531 * If the directory name doesn't have a / on the end, we need
4532 * to add one so we get a proper path to the file
4534 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4535 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4537 return g_strconcat (dir, file, NULL);
4541 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4543 char *n = mono_string_to_utf8 (name);
4544 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4546 guint32 cols [MONO_MANIFEST_SIZE];
4547 guint32 impl, file_idx;
4551 MONO_ARCH_SAVE_REGS;
4553 for (i = 0; i < table->rows; ++i) {
4554 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4555 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4556 if (strcmp (val, n) == 0)
4560 if (i == table->rows)
4563 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4566 * this code should only be called after obtaining the
4567 * ResourceInfo and handling the other cases.
4569 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4570 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4572 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4577 module = assembly->assembly->image;
4579 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4581 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4585 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4587 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4589 guint32 cols [MONO_MANIFEST_SIZE];
4590 guint32 file_cols [MONO_FILE_SIZE];
4594 MONO_ARCH_SAVE_REGS;
4596 n = mono_string_to_utf8 (name);
4597 for (i = 0; i < table->rows; ++i) {
4598 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4599 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4600 if (strcmp (val, n) == 0)
4604 if (i == table->rows)
4607 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4608 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4611 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4612 case MONO_IMPLEMENTATION_FILE:
4613 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4614 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4615 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4616 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4617 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4618 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4621 info->location = RESOURCE_LOCATION_EMBEDDED;
4624 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4625 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4626 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4627 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4628 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4629 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4631 mono_raise_exception (ex);
4633 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4635 /* Obtain info recursively */
4636 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4637 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4640 case MONO_IMPLEMENTATION_EXP_TYPE:
4641 g_assert_not_reached ();
4650 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4652 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4653 MonoArray *result = NULL;
4658 MONO_ARCH_SAVE_REGS;
4660 /* check hash if needed */
4662 n = mono_string_to_utf8 (name);
4663 for (i = 0; i < table->rows; ++i) {
4664 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4665 if (strcmp (val, n) == 0) {
4668 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4669 fn = mono_string_new (mono_object_domain (assembly), n);
4671 return (MonoObject*)fn;
4679 for (i = 0; i < table->rows; ++i) {
4680 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4684 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4687 for (i = 0; i < table->rows; ++i) {
4688 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4689 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4690 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4691 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4696 return (MonoObject*)result;
4700 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4702 MonoDomain *domain = mono_domain_get();
4705 int i, j, file_count = 0;
4706 MonoImage **modules;
4707 guint32 module_count, real_module_count;
4708 MonoTableInfo *table;
4709 guint32 cols [MONO_FILE_SIZE];
4710 MonoImage *image = assembly->assembly->image;
4712 g_assert (image != NULL);
4713 g_assert (!assembly->assembly->dynamic);
4715 table = &image->tables [MONO_TABLE_FILE];
4716 file_count = table->rows;
4718 modules = image->modules;
4719 module_count = image->module_count;
4721 real_module_count = 0;
4722 for (i = 0; i < module_count; ++i)
4724 real_module_count ++;
4726 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4727 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4729 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4731 for (i = 0; i < module_count; ++i)
4733 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4737 for (i = 0; i < file_count; ++i, ++j) {
4738 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4739 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4740 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4742 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4744 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4745 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4747 mono_array_setref (res, j, mono_module_get_object (domain, m));
4754 static MonoReflectionMethod*
4755 ves_icall_GetCurrentMethod (void)
4757 MonoMethod *m = mono_method_get_last_managed ();
4759 while (m->is_inflated)
4760 m = ((MonoMethodInflated*)m)->declaring;
4762 return mono_method_get_object (mono_domain_get (), m, NULL);
4767 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4770 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4771 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4772 //method is inflated, we should inflate it on the other class
4773 MonoGenericContext ctx;
4774 ctx.method_inst = inflated->context.method_inst;
4775 ctx.class_inst = inflated->context.class_inst;
4776 if (klass->generic_class)
4777 ctx.class_inst = klass->generic_class->context.class_inst;
4778 else if (klass->generic_container)
4779 ctx.class_inst = klass->generic_container->context.class_inst;
4780 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4783 mono_class_setup_methods (method->klass);
4784 if (method->klass->exception_type)
4786 for (i = 0; i < method->klass->method.count; ++i) {
4787 if (method->klass->methods [i] == method) {
4792 mono_class_setup_methods (klass);
4793 if (klass->exception_type)
4795 g_assert (offset >= 0 && offset < klass->method.count);
4796 return klass->methods [offset];
4799 static MonoReflectionMethod*
4800 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4804 klass = mono_class_from_mono_type (type);
4805 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4807 if (method->klass != klass) {
4808 method = mono_method_get_equivalent_method (method, klass);
4813 klass = method->klass;
4814 return mono_method_get_object (mono_domain_get (), method, klass);
4817 static MonoReflectionMethod*
4818 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4820 return mono_method_get_object (mono_domain_get (), method, NULL);
4823 static MonoReflectionMethodBody*
4824 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4826 return mono_method_body_get_object (mono_domain_get (), method);
4829 static MonoReflectionAssembly*
4830 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4832 MonoMethod *dest = NULL;
4834 MONO_ARCH_SAVE_REGS;
4836 mono_stack_walk_no_il (get_executing, &dest);
4837 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4841 static MonoReflectionAssembly*
4842 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4844 MonoDomain* domain = mono_domain_get ();
4846 MONO_ARCH_SAVE_REGS;
4848 if (!domain->entry_assembly)
4851 return mono_assembly_get_object (domain, domain->entry_assembly);
4854 static MonoReflectionAssembly*
4855 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4860 MONO_ARCH_SAVE_REGS;
4863 mono_stack_walk_no_il (get_executing, &dest);
4865 mono_stack_walk_no_il (get_caller, &dest);
4868 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4872 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4873 gboolean assembly_qualified)
4875 MonoDomain *domain = mono_object_domain (object);
4876 MonoTypeNameFormat format;
4880 MONO_ARCH_SAVE_REGS;
4882 format = assembly_qualified ?
4883 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4884 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4886 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4888 name = mono_type_get_name_full (object->type, format);
4892 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4897 res = mono_string_new (domain, name);
4904 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4906 MonoClass *klass = mono_class_from_mono_type (this->type);
4907 return mono_security_core_clr_class_level (klass);
4911 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4913 static MonoMethod *create_culture = NULL;
4916 const char *pkey_ptr;
4918 MonoBoolean assembly_ref = 0;
4920 MONO_ARCH_SAVE_REGS;
4922 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4923 aname->major = name->major;
4924 aname->minor = name->minor;
4925 aname->build = name->build;
4926 aname->flags = name->flags;
4927 aname->revision = name->revision;
4928 aname->hashalg = name->hash_alg;
4929 aname->versioncompat = 1; /* SameMachine (default) */
4931 if (by_default_version)
4932 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4935 if (absolute != NULL && *absolute != '\0') {
4936 const gchar *prepend = "file://";
4939 codebase = g_strdup (absolute);
4944 for (i = strlen (codebase) - 1; i >= 0; i--)
4945 if (codebase [i] == '\\')
4948 if (*codebase == '/' && *(codebase + 1) == '/') {
4951 prepend = "file:///";
4955 result = g_strconcat (prepend, codebase, NULL);
4961 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4965 if (!create_culture) {
4966 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4967 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4968 g_assert (create_culture);
4969 mono_method_desc_free (desc);
4972 if (name->culture) {
4973 args [0] = mono_string_new (domain, name->culture);
4974 args [1] = &assembly_ref;
4975 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4978 if (name->public_key) {
4979 pkey_ptr = (char*)name->public_key;
4980 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4982 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4983 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4984 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4985 } else if (default_publickey) {
4986 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4987 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4990 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4991 if (name->public_key_token [0]) {
4995 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4996 p = mono_array_addr (aname->keyToken, char, 0);
4998 for (i = 0, j = 0; i < 8; i++) {
4999 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5000 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5003 } else if (default_token) {
5004 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5009 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5011 MonoDomain *domain = mono_object_domain (assembly);
5012 MonoAssembly *mass = assembly->assembly;
5016 name = g_strdup_printf (
5017 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5019 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5020 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5021 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5022 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5024 res = mono_string_new (domain, name);
5031 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5034 MonoAssembly *mass = assembly->assembly;
5036 MONO_ARCH_SAVE_REGS;
5038 if (g_path_is_absolute (mass->image->name)) {
5039 fill_reflection_assembly_name (mono_object_domain (assembly),
5040 aname, &mass->aname, mass->image->name, TRUE,
5044 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5046 fill_reflection_assembly_name (mono_object_domain (assembly),
5047 aname, &mass->aname, absolute, TRUE, TRUE,
5054 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5057 MonoImageOpenStatus status = MONO_IMAGE_OK;
5060 MonoAssemblyName name;
5063 MONO_ARCH_SAVE_REGS;
5065 filename = mono_string_to_utf8 (fname);
5067 dirname = g_path_get_dirname (filename);
5068 replace_shadow_path (mono_domain_get (), dirname, &filename);
5071 image = mono_image_open (filename, &status);
5077 if (status == MONO_IMAGE_IMAGE_INVALID)
5078 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5080 exc = mono_get_exception_file_not_found2 (NULL, fname);
5081 mono_raise_exception (exc);
5084 res = mono_assembly_fill_assembly_name (image, &name);
5086 mono_image_close (image);
5088 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5091 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5095 mono_image_close (image);
5099 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5100 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5102 MonoBoolean result = FALSE;
5103 MonoDeclSecurityEntry entry;
5105 /* SecurityAction.RequestMinimum */
5106 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5107 *minimum = entry.blob;
5108 *minLength = entry.size;
5111 /* SecurityAction.RequestOptional */
5112 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5113 *optional = entry.blob;
5114 *optLength = entry.size;
5117 /* SecurityAction.RequestRefuse */
5118 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5119 *refused = entry.blob;
5120 *refLength = entry.size;
5128 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5132 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5134 guint32 attrs, visibility;
5136 /* we start the count from 1 because we skip the special type <Module> */
5139 for (i = 1; i < tdef->rows; ++i) {
5140 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5141 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5142 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5146 count = tdef->rows - 1;
5148 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5149 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5151 for (i = 1; i < tdef->rows; ++i) {
5152 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5153 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5154 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5155 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5157 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5159 MonoLoaderError *error;
5162 error = mono_loader_get_last_error ();
5163 g_assert (error != NULL);
5165 ex = mono_loader_error_prepare_exception (error);
5166 mono_array_setref (*exceptions, count, ex);
5168 if (mono_loader_get_last_error ())
5169 mono_loader_clear_error ();
5178 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5180 MonoArray *res = NULL;
5181 MonoArray *exceptions = NULL;
5182 MonoImage *image = NULL;
5183 MonoTableInfo *table = NULL;
5186 int i, len, ex_count;
5188 MONO_ARCH_SAVE_REGS;
5190 domain = mono_object_domain (assembly);
5192 g_assert (!assembly->assembly->dynamic);
5193 image = assembly->assembly->image;
5194 table = &image->tables [MONO_TABLE_FILE];
5195 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5197 /* Append data from all modules in the assembly */
5198 for (i = 0; i < table->rows; ++i) {
5199 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5200 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5203 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5204 /* Append the new types to the end of the array */
5205 if (mono_array_length (res2) > 0) {
5207 MonoArray *res3, *ex3;
5209 len1 = mono_array_length (res);
5210 len2 = mono_array_length (res2);
5212 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5213 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5214 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5217 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5218 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5219 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5226 /* the ReflectionTypeLoadException must have all the types (Types property),
5227 * NULL replacing types which throws an exception. The LoaderException must
5228 * contain all exceptions for NULL items.
5231 len = mono_array_length (res);
5234 for (i = 0; i < len; i++) {
5235 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5239 klass = mono_type_get_class (t->type);
5240 if ((klass != NULL) && klass->exception_type) {
5241 /* keep the class in the list */
5242 list = g_list_append (list, klass);
5243 /* and replace Type with NULL */
5244 mono_array_setref (res, i, NULL);
5251 if (list || ex_count) {
5253 MonoException *exc = NULL;
5254 MonoArray *exl = NULL;
5255 int j, length = g_list_length (list) + ex_count;
5257 mono_loader_clear_error ();
5259 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5260 /* Types for which mono_class_get () succeeded */
5261 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5262 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5263 mono_array_setref (exl, i, exc);
5265 /* Types for which it don't */
5266 for (j = 0; j < mono_array_length (exceptions); ++j) {
5267 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5269 g_assert (i < length);
5270 mono_array_setref (exl, i, exc);
5277 exc = mono_get_exception_reflection_type_load (res, exl);
5278 mono_loader_clear_error ();
5279 mono_raise_exception (exc);
5286 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5288 MonoAssemblyName aname;
5289 MonoDomain *domain = mono_object_domain (name);
5291 gboolean is_version_defined;
5292 gboolean is_token_defined;
5294 aname.public_key = NULL;
5295 val = mono_string_to_utf8 (assname);
5296 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5297 g_free ((guint8*) aname.public_key);
5302 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5303 FALSE, is_token_defined);
5305 mono_assembly_name_free (&aname);
5306 g_free ((guint8*) aname.public_key);
5312 static MonoReflectionType*
5313 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5315 MonoDomain *domain = mono_object_domain (module);
5318 MONO_ARCH_SAVE_REGS;
5320 g_assert (module->image);
5322 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5323 /* These images do not have a global type */
5326 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5327 return mono_type_get_object (domain, &klass->byval_arg);
5331 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5333 /*if (module->image)
5334 mono_image_close (module->image);*/
5338 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5340 MonoDomain *domain = mono_object_domain (module);
5342 MONO_ARCH_SAVE_REGS;
5344 g_assert (module->image);
5345 return mono_string_new (domain, module->image->guid);
5349 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5352 if (module->image && module->image->is_module_handle)
5353 return module->image->raw_data;
5356 return (gpointer) (-1);
5360 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5362 if (image->dynamic) {
5363 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5364 *pe_kind = dyn->pe_kind;
5365 *machine = dyn->machine;
5368 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5369 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5374 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5376 return (image->md_version_major << 16) | (image->md_version_minor);
5380 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5382 MonoArray *exceptions;
5385 MONO_ARCH_SAVE_REGS;
5388 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5390 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5391 for (i = 0; i < mono_array_length (exceptions); ++i) {
5392 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5394 mono_raise_exception (ex);
5401 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5403 guint32 cols [MONO_MEMBERREF_SIZE];
5405 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5406 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5407 mono_metadata_decode_blob_size (sig, &sig);
5408 return (*sig != 0x6);
5412 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5415 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5416 mono_array_addr (type_args, MonoType*, 0));
5418 context->class_inst = NULL;
5420 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5421 mono_array_addr (method_args, MonoType*, 0));
5423 context->method_inst = NULL;
5427 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5430 int table = mono_metadata_token_table (token);
5431 int index = mono_metadata_token_index (token);
5432 MonoGenericContext context;
5434 *error = ResolveTokenError_Other;
5436 /* Validate token */
5437 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5438 (table != MONO_TABLE_TYPESPEC)) {
5439 *error = ResolveTokenError_BadTable;
5443 if (image->dynamic) {
5444 if (type_args || method_args)
5445 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5446 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5449 return &klass->byval_arg;
5452 if ((index <= 0) || (index > image->tables [table].rows)) {
5453 *error = ResolveTokenError_OutOfRange;
5457 init_generic_context_from_args (&context, type_args, method_args);
5458 klass = mono_class_get_full (image, token, &context);
5460 if (mono_loader_get_last_error ())
5461 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5464 return &klass->byval_arg;
5470 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5472 int table = mono_metadata_token_table (token);
5473 int index = mono_metadata_token_index (token);
5474 MonoGenericContext context;
5477 *error = ResolveTokenError_Other;
5479 /* Validate token */
5480 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5481 (table != MONO_TABLE_MEMBERREF)) {
5482 *error = ResolveTokenError_BadTable;
5486 if (image->dynamic) {
5487 if (type_args || method_args)
5488 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5489 /* FIXME: validate memberref token type */
5490 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5493 if ((index <= 0) || (index > image->tables [table].rows)) {
5494 *error = ResolveTokenError_OutOfRange;
5497 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5498 *error = ResolveTokenError_BadTable;
5502 init_generic_context_from_args (&context, type_args, method_args);
5503 method = mono_get_method_full (image, token, NULL, &context);
5505 if (mono_loader_get_last_error ())
5506 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5512 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5514 int index = mono_metadata_token_index (token);
5516 *error = ResolveTokenError_Other;
5518 /* Validate token */
5519 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5520 *error = ResolveTokenError_BadTable;
5525 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5527 if ((index <= 0) || (index >= image->heap_us.size)) {
5528 *error = ResolveTokenError_OutOfRange;
5532 /* FIXME: What to do if the index points into the middle of a string ? */
5534 return mono_ldstr (mono_domain_get (), image, index);
5537 static MonoClassField*
5538 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5541 int table = mono_metadata_token_table (token);
5542 int index = mono_metadata_token_index (token);
5543 MonoGenericContext context;
5544 MonoClassField *field;
5546 *error = ResolveTokenError_Other;
5548 /* Validate token */
5549 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5550 *error = ResolveTokenError_BadTable;
5554 if (image->dynamic) {
5555 if (type_args || method_args)
5556 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5557 /* FIXME: validate memberref token type */
5558 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5561 if ((index <= 0) || (index > image->tables [table].rows)) {
5562 *error = ResolveTokenError_OutOfRange;
5565 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5566 *error = ResolveTokenError_BadTable;
5570 init_generic_context_from_args (&context, type_args, method_args);
5571 field = mono_field_from_token (image, token, &klass, &context);
5573 if (mono_loader_get_last_error ())
5574 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5581 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5583 int table = mono_metadata_token_table (token);
5585 *error = ResolveTokenError_Other;
5588 case MONO_TABLE_TYPEDEF:
5589 case MONO_TABLE_TYPEREF:
5590 case MONO_TABLE_TYPESPEC: {
5591 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5593 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5597 case MONO_TABLE_METHOD:
5598 case MONO_TABLE_METHODSPEC: {
5599 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5601 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5605 case MONO_TABLE_FIELD: {
5606 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5608 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5612 case MONO_TABLE_MEMBERREF:
5613 if (mono_metadata_memberref_is_method (image, token)) {
5614 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5616 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5621 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5623 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5630 *error = ResolveTokenError_BadTable;
5637 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5639 int table = mono_metadata_token_table (token);
5640 int idx = mono_metadata_token_index (token);
5641 MonoTableInfo *tables = image->tables;
5646 *error = ResolveTokenError_OutOfRange;
5648 /* FIXME: Support other tables ? */
5649 if (table != MONO_TABLE_STANDALONESIG)
5655 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5658 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5660 ptr = mono_metadata_blob_heap (image, sig);
5661 len = mono_metadata_decode_blob_size (ptr, &ptr);
5663 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5664 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5668 static MonoReflectionType*
5669 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5672 int isbyref = 0, rank;
5673 char *str = mono_string_to_utf8 (smodifiers);
5676 MONO_ARCH_SAVE_REGS;
5678 klass = mono_class_from_mono_type (tb->type.type);
5680 /* logic taken from mono_reflection_parse_type(): keep in sync */
5684 if (isbyref) { /* only one level allowed by the spec */
5691 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5694 klass = mono_ptr_class_get (&klass->byval_arg);
5695 mono_class_init (klass);
5706 else if (*p != '*') { /* '*' means unknown lower bound */
5717 klass = mono_array_class_get (klass, rank);
5718 mono_class_init (klass);
5725 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5729 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5734 MONO_ARCH_SAVE_REGS;
5737 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5742 static MonoReflectionType *
5743 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5745 MonoClass *klass, *aklass;
5747 MONO_ARCH_SAVE_REGS;
5749 klass = mono_class_from_mono_type (type->type);
5750 if (rank == 0) //single dimentional array
5751 aklass = mono_array_class_get (klass, 1);
5753 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5755 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5758 static MonoReflectionType *
5759 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5763 MONO_ARCH_SAVE_REGS;
5765 klass = mono_class_from_mono_type (type->type);
5767 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5770 static MonoReflectionType *
5771 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5775 MONO_ARCH_SAVE_REGS;
5777 pklass = mono_ptr_class_get (type->type);
5779 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5783 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5784 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5786 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5787 MonoObject *delegate;
5789 MonoMethod *method = info->method;
5791 MONO_ARCH_SAVE_REGS;
5793 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5795 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5796 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5800 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5802 if (method->dynamic) {
5803 /* Creating a trampoline would leak memory */
5804 func = mono_compile_method (method);
5806 func = mono_create_ftnptr (mono_domain_get (),
5807 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5810 mono_delegate_ctor_with_method (delegate, target, func, method);
5816 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5818 /* Reset the invoke impl to the default one */
5819 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5823 * Magic number to convert a time which is relative to
5824 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5826 #define EPOCH_ADJUST ((guint64)62135596800LL)
5829 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5831 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5834 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5836 convert_to_absolute_date(SYSTEMTIME *date)
5838 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5839 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5840 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5841 /* from the calendar FAQ */
5842 int a = (14 - date->wMonth) / 12;
5843 int y = date->wYear - a;
5844 int m = date->wMonth + 12 * a - 2;
5845 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5847 /* d is now the day of the week for the first of the month (0 == Sunday) */
5849 int day_of_week = date->wDayOfWeek;
5851 /* set day_in_month to the first day in the month which falls on day_of_week */
5852 int day_in_month = 1 + (day_of_week - d);
5853 if (day_in_month <= 0)
5856 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5857 date->wDay = day_in_month + (date->wDay - 1) * 7;
5858 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5865 * Return's the offset from GMT of a local time.
5867 * tm is a local time
5868 * t is the same local time as seconds.
5871 gmt_offset(struct tm *tm, time_t t)
5873 #if defined (HAVE_TM_GMTOFF)
5874 return tm->tm_gmtoff;
5879 g.tm_isdst = tm->tm_isdst;
5881 return (int)difftime(t, t2);
5886 * This is heavily based on zdump.c from glibc 2.2.
5888 * * data[0]: start of daylight saving time (in DateTime ticks).
5889 * * data[1]: end of daylight saving time (in DateTime ticks).
5890 * * data[2]: utcoffset (in TimeSpan ticks).
5891 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5892 * * name[0]: name of this timezone when not daylight saving.
5893 * * name[1]: name of this timezone when daylight saving.
5895 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5896 * the class library allows years between 1 and 9999.
5898 * Returns true on success and zero on failure.
5901 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5904 MonoDomain *domain = mono_domain_get ();
5905 struct tm start, tt;
5909 int is_daylight = 0, day;
5912 MONO_ARCH_SAVE_REGS;
5914 MONO_CHECK_ARG_NULL (data);
5915 MONO_CHECK_ARG_NULL (names);
5917 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5918 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5921 * no info is better than crashing: we'll need our own tz data
5922 * to make this work properly, anyway. The range is probably
5923 * reduced to 1970 .. 2037 because that is what mktime is
5924 * guaranteed to support (we get into an infinite loop
5928 memset (&start, 0, sizeof (start));
5931 start.tm_year = year-1900;
5933 t = mktime (&start);
5935 if ((year < 1970) || (year > 2037) || (t == -1)) {
5937 tt = *localtime (&t);
5938 strftime (tzone, sizeof (tzone), "%Z", &tt);
5939 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5940 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5944 gmtoff = gmt_offset (&start, t);
5946 /* For each day of the year, calculate the tm_gmtoff. */
5947 for (day = 0; day < 365; day++) {
5950 tt = *localtime (&t);
5952 /* Daylight saving starts or ends here. */
5953 if (gmt_offset (&tt, t) != gmtoff) {
5957 /* Try to find the exact hour when daylight saving starts/ends. */
5961 tt1 = *localtime (&t1);
5962 } while (gmt_offset (&tt1, t1) != gmtoff);
5964 /* Try to find the exact minute when daylight saving starts/ends. */
5967 tt1 = *localtime (&t1);
5968 } while (gmt_offset (&tt1, t1) == gmtoff);
5970 strftime (tzone, sizeof (tzone), "%Z", &tt);
5972 /* Write data, if we're already in daylight saving, we're done. */
5974 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5975 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5978 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5979 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5983 /* This is only set once when we enter daylight saving. */
5984 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5985 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5987 gmtoff = gmt_offset (&tt, t);
5992 strftime (tzone, sizeof (tzone), "%Z", &tt);
5993 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5994 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5995 mono_array_set ((*data), gint64, 0, 0);
5996 mono_array_set ((*data), gint64, 1, 0);
5997 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5998 mono_array_set ((*data), gint64, 3, 0);
6003 MonoDomain *domain = mono_domain_get ();
6004 TIME_ZONE_INFORMATION tz_info;
6009 tz_id = GetTimeZoneInformation (&tz_info);
6010 if (tz_id == TIME_ZONE_ID_INVALID)
6013 MONO_CHECK_ARG_NULL (data);
6014 MONO_CHECK_ARG_NULL (names);
6016 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6017 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6019 for (i = 0; i < 32; ++i)
6020 if (!tz_info.DaylightName [i])
6022 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6023 for (i = 0; i < 32; ++i)
6024 if (!tz_info.StandardName [i])
6026 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6028 if ((year <= 1601) || (year > 30827)) {
6030 * According to MSDN, the MS time functions can't handle dates outside
6036 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6037 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6038 tz_info.StandardDate.wYear = year;
6039 convert_to_absolute_date(&tz_info.StandardDate);
6040 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6045 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6046 tz_info.DaylightDate.wYear = year;
6047 convert_to_absolute_date(&tz_info.DaylightDate);
6048 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6053 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6055 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6056 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6063 ves_icall_System_Object_obj_address (MonoObject *this)
6065 MONO_ARCH_SAVE_REGS;
6072 static inline gint32
6073 mono_array_get_byte_length (MonoArray *array)
6079 klass = array->obj.vtable->klass;
6081 if (array->bounds == NULL)
6082 length = array->max_length;
6085 for (i = 0; i < klass->rank; ++ i)
6086 length *= array->bounds [i].length;
6089 switch (klass->element_class->byval_arg.type) {
6092 case MONO_TYPE_BOOLEAN:
6096 case MONO_TYPE_CHAR:
6104 return length * sizeof (gpointer);
6115 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6117 MONO_ARCH_SAVE_REGS;
6119 return mono_array_get_byte_length (array);
6123 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6125 MONO_ARCH_SAVE_REGS;
6127 return mono_array_get (array, gint8, idx);
6131 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6133 MONO_ARCH_SAVE_REGS;
6135 mono_array_set (array, gint8, idx, value);
6139 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6141 guint8 *src_buf, *dest_buf;
6143 MONO_ARCH_SAVE_REGS;
6145 /* watch out for integer overflow */
6146 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6149 src_buf = (guint8 *)src->vector + src_offset;
6150 dest_buf = (guint8 *)dest->vector + dest_offset;
6153 memcpy (dest_buf, src_buf, count);
6155 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6161 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6163 MonoDomain *domain = mono_object_domain (this);
6165 MonoRealProxy *rp = ((MonoRealProxy *)this);
6166 MonoTransparentProxy *tp;
6170 MONO_ARCH_SAVE_REGS;
6172 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6173 tp = (MonoTransparentProxy*) res;
6175 MONO_OBJECT_SETREF (tp, rp, rp);
6176 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6177 klass = mono_class_from_mono_type (type);
6179 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6180 tp->remote_class = mono_remote_class (domain, class_name, klass);
6182 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6186 static MonoReflectionType *
6187 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6189 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6192 /* System.Environment */
6195 ves_icall_System_Environment_get_UserName (void)
6197 MONO_ARCH_SAVE_REGS;
6199 /* using glib is more portable */
6200 return mono_string_new (mono_domain_get (), g_get_user_name ());
6205 ves_icall_System_Environment_get_MachineName (void)
6207 #if defined (HOST_WIN32)
6212 len = MAX_COMPUTERNAME_LENGTH + 1;
6213 buf = g_new (gunichar2, len);
6216 if (GetComputerName (buf, (PDWORD) &len))
6217 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6221 #elif !defined(DISABLE_SOCKETS)
6225 if (gethostname (buf, sizeof (buf)) == 0)
6226 result = mono_string_new (mono_domain_get (), buf);
6232 return mono_string_new (mono_domain_get (), "mono");
6237 ves_icall_System_Environment_get_Platform (void)
6239 #if defined (TARGET_WIN32)
6242 #elif defined(__MACH__)
6245 // For compatibility with our client code, this will be 4 for a while.
6246 // We will eventually move to 6 to match .NET, but it requires all client
6247 // code to be updated and the documentation everywhere to be updated
6258 ves_icall_System_Environment_get_NewLine (void)
6260 MONO_ARCH_SAVE_REGS;
6262 #if defined (HOST_WIN32)
6263 return mono_string_new (mono_domain_get (), "\r\n");
6265 return mono_string_new (mono_domain_get (), "\n");
6270 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6275 MONO_ARCH_SAVE_REGS;
6280 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6281 value = g_getenv (utf8_name);
6288 return mono_string_new (mono_domain_get (), value);
6292 * There is no standard way to get at environ.
6295 #ifndef __MINGW32_VERSION
6297 /* Apple defines this in crt_externs.h but doesn't provide that header for
6298 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6299 * in fact exist on all implementations (so far)
6301 gchar ***_NSGetEnviron(void);
6302 #define environ (*_NSGetEnviron())
6311 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6322 env_strings = GetEnvironmentStrings();
6325 env_string = env_strings;
6326 while (*env_string != '\0') {
6327 /* weird case that MS seems to skip */
6328 if (*env_string != '=')
6330 while (*env_string != '\0')
6336 domain = mono_domain_get ();
6337 names = mono_array_new (domain, mono_defaults.string_class, n);
6341 env_string = env_strings;
6342 while (*env_string != '\0') {
6343 /* weird case that MS seems to skip */
6344 if (*env_string != '=') {
6345 equal_str = wcschr(env_string, '=');
6346 g_assert(equal_str);
6347 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6348 mono_array_setref (names, n, str);
6351 while (*env_string != '\0')
6356 FreeEnvironmentStrings (env_strings);
6368 MONO_ARCH_SAVE_REGS;
6371 for (e = environ; *e != 0; ++ e)
6374 domain = mono_domain_get ();
6375 names = mono_array_new (domain, mono_defaults.string_class, n);
6378 for (e = environ; *e != 0; ++ e) {
6379 parts = g_strsplit (*e, "=", 2);
6381 str = mono_string_new (domain, *parts);
6382 mono_array_setref (names, n, str);
6395 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6397 #if !GLIB_CHECK_VERSION(2,4,0)
6398 #define g_setenv(a,b,c) setenv(a,b,c)
6399 #define g_unsetenv(a) unsetenv(a)
6403 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6408 gunichar2 *utf16_name, *utf16_value;
6410 gchar *utf8_name, *utf8_value;
6413 MONO_ARCH_SAVE_REGS;
6416 utf16_name = mono_string_to_utf16 (name);
6417 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6418 SetEnvironmentVariable (utf16_name, NULL);
6419 g_free (utf16_name);
6423 utf16_value = mono_string_to_utf16 (value);
6425 SetEnvironmentVariable (utf16_name, utf16_value);
6427 g_free (utf16_name);
6428 g_free (utf16_value);
6430 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6432 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6433 g_unsetenv (utf8_name);
6438 utf8_value = mono_string_to_utf8_checked (value, &error);
6439 if (!mono_error_ok (&error)) {
6441 mono_error_raise_exception (&error);
6443 g_setenv (utf8_name, utf8_value, TRUE);
6446 g_free (utf8_value);
6451 ves_icall_System_Environment_Exit (int result)
6453 MONO_ARCH_SAVE_REGS;
6455 mono_threads_set_shutting_down ();
6457 mono_runtime_set_shutting_down ();
6459 /* Suspend all managed threads since the runtime is going away */
6460 mono_thread_suspend_all_other_threads ();
6462 mono_runtime_quit ();
6464 /* we may need to do some cleanup here... */
6469 ves_icall_System_Environment_GetGacPath (void)
6471 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6475 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6477 #if defined (HOST_WIN32)
6478 #ifndef CSIDL_FLAG_CREATE
6479 #define CSIDL_FLAG_CREATE 0x8000
6482 WCHAR path [MAX_PATH];
6483 /* Create directory if no existing */
6484 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6488 return mono_string_new_utf16 (mono_domain_get (), path, len);
6491 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6493 return mono_string_new (mono_domain_get (), "");
6497 ves_icall_System_Environment_GetLogicalDrives (void)
6499 gunichar2 buf [128], *ptr, *dname;
6501 guint initial_size = 127, size = 128;
6504 MonoString *drivestr;
6505 MonoDomain *domain = mono_domain_get ();
6508 MONO_ARCH_SAVE_REGS;
6513 while (size > initial_size) {
6514 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6515 if (size > initial_size) {
6518 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6519 initial_size = size;
6533 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6538 while (*u16) { u16++; len ++; }
6539 drivestr = mono_string_new_utf16 (domain, dname, len);
6540 mono_array_setref (result, ndrives++, drivestr);
6551 ves_icall_System_Environment_InternalGetHome (void)
6553 MONO_ARCH_SAVE_REGS;
6555 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6558 static const char *encodings [] = {
6560 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6561 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6562 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6564 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6565 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6566 "x_unicode_2_0_utf_7",
6568 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6569 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6571 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6574 "unicodefffe", "utf_16be",
6581 * Returns the internal codepage, if the value of "int_code_page" is
6582 * 1 at entry, and we can not compute a suitable code page number,
6583 * returns the code page as a string
6586 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6591 char *codepage = NULL;
6593 int want_name = *int_code_page;
6596 *int_code_page = -1;
6597 MONO_ARCH_SAVE_REGS;
6599 g_get_charset (&cset);
6600 c = codepage = strdup (cset);
6601 for (c = codepage; *c; c++){
6602 if (isascii (*c) && isalpha (*c))
6607 /* g_print ("charset: %s\n", cset); */
6609 /* handle some common aliases */
6612 for (i = 0; p != 0; ){
6613 if ((gssize) p < 7){
6615 p = encodings [++i];
6618 if (strcmp (p, codepage) == 0){
6619 *int_code_page = code;
6622 p = encodings [++i];
6625 if (strstr (codepage, "utf_8") != NULL)
6626 *int_code_page |= 0x10000000;
6629 if (want_name && *int_code_page == -1)
6630 return mono_string_new (mono_domain_get (), cset);
6636 ves_icall_System_Environment_get_HasShutdownStarted (void)
6638 if (mono_runtime_is_shutting_down ())
6641 if (mono_domain_is_unloading (mono_domain_get ()))
6648 ves_icall_System_Environment_BroadcastSettingChange (void)
6651 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6656 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6657 MonoReflectionMethod *method,
6658 MonoArray *out_args)
6660 MONO_ARCH_SAVE_REGS;
6662 mono_message_init (mono_object_domain (this), this, method, out_args);
6666 ves_icall_IsTransparentProxy (MonoObject *proxy)
6668 MONO_ARCH_SAVE_REGS;
6673 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6679 static MonoReflectionMethod *
6680 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6681 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6685 MonoMethod **vtable;
6686 MonoMethod *res = NULL;
6688 MONO_CHECK_ARG_NULL (rtype);
6689 MONO_CHECK_ARG_NULL (rmethod);
6691 method = rmethod->method;
6692 klass = mono_class_from_mono_type (rtype->type);
6694 if (MONO_CLASS_IS_INTERFACE (klass))
6697 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6700 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6701 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6707 mono_class_setup_vtable (klass);
6708 vtable = klass->vtable;
6710 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6711 gboolean variance_used = FALSE;
6712 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6713 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6715 res = vtable [offs + method->slot];
6717 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6720 if (method->slot != -1)
6721 res = vtable [method->slot];
6727 return mono_method_get_object (mono_domain_get (), res, NULL);
6731 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6736 MONO_ARCH_SAVE_REGS;
6738 klass = mono_class_from_mono_type (type->type);
6739 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6741 if (enable) vtable->remote = 1;
6742 else vtable->remote = 0;
6746 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6751 MONO_ARCH_SAVE_REGS;
6753 domain = mono_object_domain (type);
6754 klass = mono_class_from_mono_type (type->type);
6756 if (klass->rank >= 1) {
6757 g_assert (klass->rank == 1);
6758 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6760 /* Bypass remoting object creation check */
6761 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6766 ves_icall_System_IO_get_temp_path (void)
6768 MONO_ARCH_SAVE_REGS;
6770 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6773 #ifndef PLATFORM_NO_DRIVEINFO
6775 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6776 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6780 ULARGE_INTEGER wapi_free_bytes_avail;
6781 ULARGE_INTEGER wapi_total_number_of_bytes;
6782 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6784 MONO_ARCH_SAVE_REGS;
6786 *error = ERROR_SUCCESS;
6787 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6788 &wapi_total_number_of_free_bytes);
6791 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6792 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6793 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6795 *free_bytes_avail = 0;
6796 *total_number_of_bytes = 0;
6797 *total_number_of_free_bytes = 0;
6798 *error = GetLastError ();
6805 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6807 MONO_ARCH_SAVE_REGS;
6809 return GetDriveType (mono_string_chars (root_path_name));
6814 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6816 MONO_ARCH_SAVE_REGS;
6818 return mono_compile_method (method);
6822 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6827 MONO_ARCH_SAVE_REGS;
6829 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6831 #if defined (HOST_WIN32)
6832 /* Avoid mixing '/' and '\\' */
6835 for (i = strlen (path) - 1; i >= 0; i--)
6836 if (path [i] == '/')
6840 mcpath = mono_string_new (mono_domain_get (), path);
6847 get_bundled_machine_config (void)
6849 const gchar *machine_config;
6851 MONO_ARCH_SAVE_REGS;
6853 machine_config = mono_get_machine_config ();
6855 if (!machine_config)
6858 return mono_string_new (mono_domain_get (), machine_config);
6862 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6867 MONO_ARCH_SAVE_REGS;
6869 path = g_path_get_dirname (mono_get_config_dir ());
6871 #if defined (HOST_WIN32)
6872 /* Avoid mixing '/' and '\\' */
6875 for (i = strlen (path) - 1; i >= 0; i--)
6876 if (path [i] == '/')
6880 ipath = mono_string_new (mono_domain_get (), path);
6887 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6889 MonoPEResourceDataEntry *entry;
6892 MONO_ARCH_SAVE_REGS;
6894 if (!assembly || !result || !size)
6899 image = assembly->assembly->image;
6900 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6904 *result = mono_image_rva_map (image, entry->rde_data_offset);
6909 *size = entry->rde_size;
6915 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6917 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6921 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6923 #if defined (HOST_WIN32)
6924 OutputDebugString (mono_string_chars (message));
6926 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6930 /* Only used for value types */
6932 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6937 MONO_ARCH_SAVE_REGS;
6939 domain = mono_object_domain (type);
6940 klass = mono_class_from_mono_type (type->type);
6942 if (mono_class_is_nullable (klass))
6943 /* No arguments -> null */
6946 return mono_object_new (domain, klass);
6949 static MonoReflectionMethod *
6950 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6952 MonoClass *klass, *parent;
6953 MonoMethod *method = m->method;
6954 MonoMethod *result = NULL;
6956 MONO_ARCH_SAVE_REGS;
6958 if (method->klass == NULL)
6961 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6962 MONO_CLASS_IS_INTERFACE (method->klass) ||
6963 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6966 klass = method->klass;
6967 if (klass->generic_class)
6968 klass = klass->generic_class->container_class;
6971 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6972 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6973 mono_class_setup_vtable (parent);
6974 if (parent->vtable_size <= method->slot)
6979 klass = klass->parent;
6984 if (klass == method->klass)
6987 result = klass->vtable [method->slot];
6988 if (result == NULL) {
6989 /* It is an abstract method */
6990 gpointer iter = NULL;
6991 while ((result = mono_class_get_methods (klass, &iter)))
6992 if (result->slot == method->slot)
6999 return mono_method_get_object (mono_domain_get (), result, NULL);
7003 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7005 MonoMethod *method = m->method;
7007 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7012 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7014 MONO_ARCH_SAVE_REGS;
7016 iter->sig = *(MonoMethodSignature**)argsp;
7018 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7019 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7022 /* FIXME: it's not documented what start is exactly... */
7026 iter->args = argsp + sizeof (gpointer);
7028 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7030 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7034 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7036 guint32 i, arg_size;
7039 MONO_ARCH_SAVE_REGS;
7041 i = iter->sig->sentinelpos + iter->next_arg;
7043 g_assert (i < iter->sig->param_count);
7045 res.type = iter->sig->params [i];
7046 res.klass = mono_class_from_mono_type (res.type);
7047 res.value = iter->args;
7048 arg_size = mono_type_stack_size (res.type, &align);
7049 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7050 if (arg_size <= sizeof (gpointer)) {
7052 int padding = arg_size - mono_type_size (res.type, &dummy);
7053 res.value = (guint8*)res.value + padding;
7056 iter->args = (char*)iter->args + arg_size;
7059 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7065 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7067 guint32 i, arg_size;
7070 MONO_ARCH_SAVE_REGS;
7072 i = iter->sig->sentinelpos + iter->next_arg;
7074 g_assert (i < iter->sig->param_count);
7076 while (i < iter->sig->param_count) {
7077 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7079 res.type = iter->sig->params [i];
7080 res.klass = mono_class_from_mono_type (res.type);
7081 /* FIXME: endianess issue... */
7082 res.value = iter->args;
7083 arg_size = mono_type_stack_size (res.type, &align);
7084 iter->args = (char*)iter->args + arg_size;
7086 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7089 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7098 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7101 MONO_ARCH_SAVE_REGS;
7103 i = iter->sig->sentinelpos + iter->next_arg;
7105 g_assert (i < iter->sig->param_count);
7107 return iter->sig->params [i];
7111 mono_TypedReference_ToObject (MonoTypedRef tref)
7113 MONO_ARCH_SAVE_REGS;
7115 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7116 MonoObject** objp = tref.value;
7120 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7124 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7126 MONO_ARCH_SAVE_REGS;
7128 if (MONO_TYPE_IS_REFERENCE (type)) {
7129 MonoObject** objp = value;
7133 return mono_value_box (mono_domain_get (), klass, value);
7137 prelink_method (MonoMethod *method)
7139 const char *exc_class, *exc_arg;
7140 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7142 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7144 mono_raise_exception(
7145 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7147 /* create the wrapper, too? */
7151 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7153 MONO_ARCH_SAVE_REGS;
7154 prelink_method (method->method);
7158 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7160 MonoClass *klass = mono_class_from_mono_type (type->type);
7162 gpointer iter = NULL;
7163 MONO_ARCH_SAVE_REGS;
7165 while ((m = mono_class_get_methods (klass, &iter)))
7169 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7171 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7172 gint32 const **exponents,
7173 gunichar2 const **digitLowerTable,
7174 gunichar2 const **digitUpperTable,
7175 gint64 const **tenPowersList,
7176 gint32 const **decHexDigits)
7178 *mantissas = Formatter_MantissaBitsTable;
7179 *exponents = Formatter_TensExponentTable;
7180 *digitLowerTable = Formatter_DigitLowerTable;
7181 *digitUpperTable = Formatter_DigitUpperTable;
7182 *tenPowersList = Formatter_TenPowersList;
7183 *decHexDigits = Formatter_DecHexDigits;
7186 /* These parameters are "readonly" in corlib/System/Char.cs */
7188 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7189 guint8 const **numeric_data,
7190 gdouble const **numeric_data_values,
7191 guint16 const **to_lower_data_low,
7192 guint16 const **to_lower_data_high,
7193 guint16 const **to_upper_data_low,
7194 guint16 const **to_upper_data_high)
7196 *category_data = CategoryData;
7197 *numeric_data = NumericData;
7198 *numeric_data_values = NumericDataValues;
7199 *to_lower_data_low = ToLowerDataLow;
7200 *to_lower_data_high = ToLowerDataHigh;
7201 *to_upper_data_low = ToUpperDataLow;
7202 *to_upper_data_high = ToUpperDataHigh;
7206 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7208 return method->method->token;
7212 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7213 * and avoid useless allocations.
7216 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7220 for (i = 0; i < type->num_mods; ++i) {
7221 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7226 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7228 for (i = 0; i < type->num_mods; ++i) {
7229 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7230 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7231 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7239 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7241 MonoType *type = param->ClassImpl->type;
7242 MonoClass *member_class = mono_object_class (param->MemberImpl);
7243 MonoMethod *method = NULL;
7246 MonoMethodSignature *sig;
7248 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7249 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7250 method = rmethod->method;
7251 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7252 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7253 if (!(method = prop->property->get))
7254 method = prop->property->set;
7257 char *type_name = mono_type_get_full_name (member_class);
7258 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7259 MonoException *ex = mono_get_exception_not_supported (msg);
7262 mono_raise_exception (ex);
7265 image = method->klass->image;
7266 pos = param->PositionImpl;
7267 sig = mono_method_signature (method);
7271 type = sig->params [pos];
7273 return type_array_from_modifiers (image, type, optional);
7277 get_property_type (MonoProperty *prop)
7279 MonoMethodSignature *sig;
7281 sig = mono_method_signature (prop->get);
7283 } else if (prop->set) {
7284 sig = mono_method_signature (prop->set);
7285 return sig->params [sig->param_count - 1];
7291 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7293 MonoType *type = get_property_type (property->property);
7294 MonoImage *image = property->klass->image;
7298 return type_array_from_modifiers (image, type, optional);
7302 *Construct a MonoType suited to be used to decode a constant blob object.
7304 * @type is the target type which will be constructed
7305 * @blob_type is the blob type, for example, that comes from the constant table
7306 * @real_type is the expected constructed type.
7309 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7311 type->type = blob_type;
7312 type->data.klass = NULL;
7313 if (blob_type == MONO_TYPE_CLASS)
7314 type->data.klass = mono_defaults.object_class;
7315 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7316 /* For enums, we need to use the base type */
7317 type->type = MONO_TYPE_VALUETYPE;
7318 type->data.klass = mono_class_from_mono_type (real_type);
7320 type->data.klass = mono_class_from_mono_type (real_type);
7324 property_info_get_default_value (MonoReflectionProperty *property)
7327 MonoProperty *prop = property->property;
7328 MonoType *type = get_property_type (prop);
7329 MonoDomain *domain = mono_object_domain (property);
7330 MonoTypeEnum def_type;
7331 const char *def_value;
7334 g_assert (!prop->parent->image->dynamic);
7336 mono_class_init (prop->parent);
7338 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7339 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7341 def_value = mono_class_get_property_default_value (prop, &def_type);
7343 mono_type_from_blob_type (&blob_type, def_type, type);
7344 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7350 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7352 MonoCustomAttrInfo *cinfo;
7355 cinfo = mono_reflection_get_custom_attrs_info (obj);
7358 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7360 mono_custom_attrs_free (cinfo);
7365 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7367 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7369 if (mono_loader_get_last_error ()) {
7370 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7371 g_assert_not_reached ();
7380 ves_icall_Mono_Runtime_GetDisplayName (void)
7383 MonoString *display_name;
7385 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7386 display_name = mono_string_new (mono_domain_get (), info);
7388 return display_name;
7392 ves_icall_Mono_Runtime_NewObject (MonoType *t)
7394 return mono_object_new (mono_domain_get (), mono_class_from_mono_type (t));
7398 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7400 MonoString *message;
7404 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7405 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7408 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7410 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7418 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
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, 62, 128, 128, 128, 63,
7421 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7422 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7423 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7424 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7425 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7429 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7434 gunichar2 last, prev_last, prev2_last;
7442 last = prev_last = 0, prev2_last = 0;
7443 for (i = 0; i < ilength; i++) {
7445 if (c >= sizeof (dbase64)) {
7446 exc = mono_exception_from_name_msg (mono_get_corlib (),
7447 "System", "FormatException",
7448 "Invalid character found.");
7449 mono_raise_exception (exc);
7450 } else if (isspace (c)) {
7453 prev2_last = prev_last;
7459 olength = ilength - ignored;
7461 if (allowWhitespaceOnly && olength == 0) {
7462 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7465 if ((olength & 3) != 0 || olength <= 0) {
7466 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7467 "FormatException", "Invalid length.");
7468 mono_raise_exception (exc);
7471 if (prev2_last == '=') {
7472 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7473 mono_raise_exception (exc);
7476 olength = (olength * 3) / 4;
7480 if (prev_last == '=')
7483 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7484 res_ptr = mono_array_addr (result, guchar, 0);
7485 for (i = 0; i < ilength; ) {
7488 for (k = 0; k < 4 && i < ilength;) {
7494 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7495 exc = mono_exception_from_name_msg (mono_get_corlib (),
7496 "System", "FormatException",
7497 "Invalid character found.");
7498 mono_raise_exception (exc);
7503 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7505 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7507 *res_ptr++ = (b [2] << 6) | b [3];
7509 while (i < ilength && isspace (start [i]))
7517 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7519 MONO_ARCH_SAVE_REGS;
7521 return base64_to_byte_array (mono_string_chars (str),
7522 mono_string_length (str), allowWhitespaceOnly);
7526 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7528 MONO_ARCH_SAVE_REGS;
7530 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7534 #define ICALL_TYPE(id,name,first)
7535 #define ICALL(id,name,func) Icall_ ## id,
7538 #include "metadata/icall-def.h"
7544 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7545 #define ICALL(id,name,func)
7547 #include "metadata/icall-def.h"
7553 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7554 #define ICALL(id,name,func)
7556 guint16 first_icall;
7559 static const IcallTypeDesc
7560 icall_type_descs [] = {
7561 #include "metadata/icall-def.h"
7565 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7568 #define ICALL_TYPE(id,name,first)
7571 #ifdef HAVE_ARRAY_ELEM_INIT
7572 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7573 #define MSGSTRFIELD1(line) str##line
7575 static const struct msgstrtn_t {
7576 #define ICALL(id,name,func)
7578 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7579 #include "metadata/icall-def.h"
7581 } icall_type_names_str = {
7582 #define ICALL_TYPE(id,name,first) (name),
7583 #include "metadata/icall-def.h"
7586 static const guint16 icall_type_names_idx [] = {
7587 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7588 #include "metadata/icall-def.h"
7591 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7593 static const struct msgstr_t {
7595 #define ICALL_TYPE(id,name,first)
7596 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7597 #include "metadata/icall-def.h"
7599 } icall_names_str = {
7600 #define ICALL(id,name,func) (name),
7601 #include "metadata/icall-def.h"
7604 static const guint16 icall_names_idx [] = {
7605 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7606 #include "metadata/icall-def.h"
7609 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7615 #define ICALL_TYPE(id,name,first) name,
7616 #define ICALL(id,name,func)
7617 static const char* const
7618 icall_type_names [] = {
7619 #include "metadata/icall-def.h"
7623 #define icall_type_name_get(id) (icall_type_names [(id)])
7627 #define ICALL_TYPE(id,name,first)
7628 #define ICALL(id,name,func) name,
7629 static const char* const
7631 #include "metadata/icall-def.h"
7634 #define icall_name_get(id) icall_names [(id)]
7636 #endif /* !HAVE_ARRAY_ELEM_INIT */
7640 #define ICALL_TYPE(id,name,first)
7641 #define ICALL(id,name,func) func,
7642 static const gconstpointer
7643 icall_functions [] = {
7644 #include "metadata/icall-def.h"
7648 static GHashTable *icall_hash = NULL;
7649 static GHashTable *jit_icall_hash_name = NULL;
7650 static GHashTable *jit_icall_hash_addr = NULL;
7653 mono_icall_init (void)
7657 /* check that tables are sorted: disable in release */
7660 const char *prev_class = NULL;
7661 const char *prev_method;
7663 for (i = 0; i < Icall_type_num; ++i) {
7664 const IcallTypeDesc *desc;
7667 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7668 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7669 prev_class = icall_type_name_get (i);
7670 desc = &icall_type_descs [i];
7671 num_icalls = icall_desc_num_icalls (desc);
7672 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7673 for (j = 0; j < num_icalls; ++j) {
7674 const char *methodn = icall_name_get (desc->first_icall + j);
7675 if (prev_method && strcmp (prev_method, methodn) >= 0)
7676 g_print ("method %s should come before method %s\n", methodn, prev_method);
7677 prev_method = methodn;
7682 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7686 mono_icall_cleanup (void)
7688 g_hash_table_destroy (icall_hash);
7689 g_hash_table_destroy (jit_icall_hash_name);
7690 g_hash_table_destroy (jit_icall_hash_addr);
7694 mono_add_internal_call (const char *name, gconstpointer method)
7696 mono_loader_lock ();
7698 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7700 mono_loader_unlock ();
7703 #ifdef HAVE_ARRAY_ELEM_INIT
7705 compare_method_imap (const void *key, const void *elem)
7707 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7708 return strcmp (key, method_name);
7712 find_method_icall (const IcallTypeDesc *imap, const char *name)
7714 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7717 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7721 compare_class_imap (const void *key, const void *elem)
7723 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7724 return strcmp (key, class_name);
7727 static const IcallTypeDesc*
7728 find_class_icalls (const char *name)
7730 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7733 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7738 compare_method_imap (const void *key, const void *elem)
7740 const char** method_name = (const char**)elem;
7741 return strcmp (key, *method_name);
7745 find_method_icall (const IcallTypeDesc *imap, const char *name)
7747 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7750 return (gpointer)icall_functions [(nameslot - icall_names)];
7754 compare_class_imap (const void *key, const void *elem)
7756 const char** class_name = (const char**)elem;
7757 return strcmp (key, *class_name);
7760 static const IcallTypeDesc*
7761 find_class_icalls (const char *name)
7763 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7766 return &icall_type_descs [nameslot - icall_type_names];
7772 * we should probably export this as an helper (handle nested types).
7773 * Returns the number of chars written in buf.
7776 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7778 int nspacelen, cnamelen;
7779 nspacelen = strlen (klass->name_space);
7780 cnamelen = strlen (klass->name);
7781 if (nspacelen + cnamelen + 2 > bufsize)
7784 memcpy (buf, klass->name_space, nspacelen);
7785 buf [nspacelen ++] = '.';
7787 memcpy (buf + nspacelen, klass->name, cnamelen);
7788 buf [nspacelen + cnamelen] = 0;
7789 return nspacelen + cnamelen;
7793 mono_lookup_internal_call (MonoMethod *method)
7798 int typelen = 0, mlen, siglen;
7800 const IcallTypeDesc *imap;
7802 g_assert (method != NULL);
7804 if (method->is_inflated)
7805 method = ((MonoMethodInflated *) method)->declaring;
7807 if (method->klass->nested_in) {
7808 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7812 mname [pos++] = '/';
7815 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7821 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7826 imap = find_class_icalls (mname);
7828 mname [typelen] = ':';
7829 mname [typelen + 1] = ':';
7831 mlen = strlen (method->name);
7832 memcpy (mname + typelen + 2, method->name, mlen);
7833 sigstart = mname + typelen + 2 + mlen;
7836 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7837 siglen = strlen (tmpsig);
7838 if (typelen + mlen + siglen + 6 > sizeof (mname))
7841 memcpy (sigstart + 1, tmpsig, siglen);
7842 sigstart [siglen + 1] = ')';
7843 sigstart [siglen + 2] = 0;
7846 mono_loader_lock ();
7848 res = g_hash_table_lookup (icall_hash, mname);
7850 mono_loader_unlock ();
7853 /* try without signature */
7855 res = g_hash_table_lookup (icall_hash, mname);
7857 mono_loader_unlock ();
7861 /* it wasn't found in the static call tables */
7863 mono_loader_unlock ();
7866 res = find_method_icall (imap, sigstart - mlen);
7868 mono_loader_unlock ();
7871 /* try _with_ signature */
7873 res = find_method_icall (imap, sigstart - mlen);
7875 mono_loader_unlock ();
7879 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7880 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7881 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7882 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7883 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");
7884 g_print ("If you see other errors or faults after this message they are probably related\n");
7885 g_print ("and you need to fix your mono install first.\n");
7887 mono_loader_unlock ();
7893 type_from_typename (char *typename)
7895 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7897 if (!strcmp (typename, "int"))
7898 klass = mono_defaults.int_class;
7899 else if (!strcmp (typename, "ptr"))
7900 klass = mono_defaults.int_class;
7901 else if (!strcmp (typename, "void"))
7902 klass = mono_defaults.void_class;
7903 else if (!strcmp (typename, "int32"))
7904 klass = mono_defaults.int32_class;
7905 else if (!strcmp (typename, "uint32"))
7906 klass = mono_defaults.uint32_class;
7907 else if (!strcmp (typename, "int8"))
7908 klass = mono_defaults.sbyte_class;
7909 else if (!strcmp (typename, "uint8"))
7910 klass = mono_defaults.byte_class;
7911 else if (!strcmp (typename, "int16"))
7912 klass = mono_defaults.int16_class;
7913 else if (!strcmp (typename, "uint16"))
7914 klass = mono_defaults.uint16_class;
7915 else if (!strcmp (typename, "long"))
7916 klass = mono_defaults.int64_class;
7917 else if (!strcmp (typename, "ulong"))
7918 klass = mono_defaults.uint64_class;
7919 else if (!strcmp (typename, "float"))
7920 klass = mono_defaults.single_class;
7921 else if (!strcmp (typename, "double"))
7922 klass = mono_defaults.double_class;
7923 else if (!strcmp (typename, "object"))
7924 klass = mono_defaults.object_class;
7925 else if (!strcmp (typename, "obj"))
7926 klass = mono_defaults.object_class;
7927 else if (!strcmp (typename, "string"))
7928 klass = mono_defaults.string_class;
7929 else if (!strcmp (typename, "bool"))
7930 klass = mono_defaults.boolean_class;
7931 else if (!strcmp (typename, "boolean"))
7932 klass = mono_defaults.boolean_class;
7934 g_error ("%s", typename);
7935 g_assert_not_reached ();
7937 return &klass->byval_arg;
7940 MonoMethodSignature*
7941 mono_create_icall_signature (const char *sigstr)
7946 MonoMethodSignature *res;
7948 mono_loader_lock ();
7949 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7951 mono_loader_unlock ();
7955 parts = g_strsplit (sigstr, " ", 256);
7964 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7969 * Under windows, the default pinvoke calling convention is STDCALL but
7972 res->call_convention = MONO_CALL_C;
7975 res->ret = type_from_typename (parts [0]);
7976 for (i = 1; i < len; ++i) {
7977 res->params [i - 1] = type_from_typename (parts [i]);
7982 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7984 mono_loader_unlock ();
7990 mono_find_jit_icall_by_name (const char *name)
7992 MonoJitICallInfo *info;
7993 g_assert (jit_icall_hash_name);
7995 mono_loader_lock ();
7996 info = g_hash_table_lookup (jit_icall_hash_name, name);
7997 mono_loader_unlock ();
8002 mono_find_jit_icall_by_addr (gconstpointer addr)
8004 MonoJitICallInfo *info;
8005 g_assert (jit_icall_hash_addr);
8007 mono_loader_lock ();
8008 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8009 mono_loader_unlock ();
8015 * mono_get_jit_icall_info:
8017 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8018 * caller should access it while holding the loader lock.
8021 mono_get_jit_icall_info (void)
8023 return jit_icall_hash_name;
8027 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8029 mono_loader_lock ();
8030 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8031 mono_loader_unlock ();
8035 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8037 MonoJitICallInfo *info;
8042 mono_loader_lock ();
8044 if (!jit_icall_hash_name) {
8045 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8046 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8049 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8050 g_warning ("jit icall already defined \"%s\"\n", name);
8051 g_assert_not_reached ();
8054 info = g_new0 (MonoJitICallInfo, 1);
8061 info->wrapper = func;
8063 info->wrapper = NULL;
8066 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8067 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8069 mono_loader_unlock ();