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 (PLATFORM_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>
76 #if defined (PLATFORM_WIN32)
82 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
85 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
87 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
88 * It works by allocating an initial small array on stack and only going to malloc'd memory if needed.
96 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
98 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\
100 (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
101 (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); \
104 #define mono_ptr_array_destroy(ARRAY) do {\
105 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
106 mono_gc_free_fixed ((ARRAY).data); \
109 #define mono_ptr_array_append(ARRAY, VALUE) do { \
110 if ((ARRAY).size >= (ARRAY).capacity) {\
111 void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \
112 memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
113 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
114 mono_gc_free_fixed ((ARRAY).data); \
115 (ARRAY).data = __tmp; \
116 (ARRAY).capacity *= 2;\
118 ((ARRAY).data [(ARRAY).size++] = VALUE); \
121 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
122 ((ARRAY).data [(IDX)] = VALUE); \
125 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
127 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
130 static inline MonoBoolean
131 is_generic_parameter (MonoType *type)
133 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
137 * We expect a pointer to a char, not a string
140 mono_double_ParseImpl (char *ptr, double *result)
142 gchar *endptr = NULL;
149 *result = strtod (ptr, &endptr);
153 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
154 EnterCriticalSection (&mono_strtod_mutex);
155 *result = mono_strtod (ptr, &endptr);
156 LeaveCriticalSection (&mono_strtod_mutex);
158 *result = mono_strtod (ptr, &endptr);
163 if (!*ptr || (endptr && *endptr))
170 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
179 ao = (MonoArray *)this;
180 ac = (MonoClass *)ao->obj.vtable->klass;
182 esize = mono_array_element_size (ac);
183 ea = (gpointer*)((char*)ao->vector + (pos * esize));
185 if (ac->element_class->valuetype)
186 return mono_value_box (this->vtable->domain, ac->element_class, ea);
192 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
200 MONO_CHECK_ARG_NULL (idxs);
202 io = (MonoArray *)idxs;
203 ic = (MonoClass *)io->obj.vtable->klass;
205 ao = (MonoArray *)this;
206 ac = (MonoClass *)ao->obj.vtable->klass;
208 g_assert (ic->rank == 1);
209 if (io->bounds != NULL || io->max_length != ac->rank)
210 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
212 ind = (gint32 *)io->vector;
214 if (ao->bounds == NULL) {
215 if (*ind < 0 || *ind >= ao->max_length)
216 mono_raise_exception (mono_get_exception_index_out_of_range ());
218 return ves_icall_System_Array_GetValueImpl (this, *ind);
221 for (i = 0; i < ac->rank; i++)
222 if ((ind [i] < ao->bounds [i].lower_bound) ||
223 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
224 mono_raise_exception (mono_get_exception_index_out_of_range ());
226 pos = ind [0] - ao->bounds [0].lower_bound;
227 for (i = 1; i < ac->rank; i++)
228 pos = pos*ao->bounds [i].length + ind [i] -
229 ao->bounds [i].lower_bound;
231 return ves_icall_System_Array_GetValueImpl (this, pos);
235 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
237 MonoClass *ac, *vc, *ec;
249 vc = value->vtable->klass;
253 ac = this->obj.vtable->klass;
254 ec = ac->element_class;
256 esize = mono_array_element_size (ac);
257 ea = (gpointer*)((char*)this->vector + (pos * esize));
258 va = (gpointer*)((char*)value + sizeof (MonoObject));
261 memset (ea, 0, esize);
265 #define NO_WIDENING_CONVERSION G_STMT_START{\
266 mono_raise_exception (mono_get_exception_argument ( \
267 "value", "not a widening conversion")); \
270 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
271 if (esize < vsize + (extra)) \
272 mono_raise_exception (mono_get_exception_argument ( \
273 "value", "not a widening conversion")); \
276 #define INVALID_CAST G_STMT_START{\
277 mono_raise_exception (mono_get_exception_invalid_cast ()); \
280 /* Check element (destination) type. */
281 switch (ec->byval_arg.type) {
282 case MONO_TYPE_STRING:
283 switch (vc->byval_arg.type) {
284 case MONO_TYPE_STRING:
290 case MONO_TYPE_BOOLEAN:
291 switch (vc->byval_arg.type) {
292 case MONO_TYPE_BOOLEAN:
305 NO_WIDENING_CONVERSION;
312 if (!ec->valuetype) {
313 if (!mono_object_isinst (value, ec))
315 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
319 if (mono_object_isinst (value, ec)) {
320 if (ec->has_references)
321 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
323 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
330 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
332 et = ec->byval_arg.type;
333 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
334 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
336 vt = vc->byval_arg.type;
337 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
338 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
340 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
346 case MONO_TYPE_CHAR: \
347 CHECK_WIDENING_CONVERSION(0); \
348 *(etype *) ea = (etype) u64; \
350 /* You can't assign a signed value to an unsigned array. */ \
355 /* You can't assign a floating point number to an integer array. */ \
358 NO_WIDENING_CONVERSION; \
362 #define ASSIGN_SIGNED(etype) G_STMT_START{\
368 CHECK_WIDENING_CONVERSION(0); \
369 *(etype *) ea = (etype) i64; \
371 /* You can assign an unsigned value to a signed array if the array's */ \
372 /* element size is larger than the value size. */ \
377 case MONO_TYPE_CHAR: \
378 CHECK_WIDENING_CONVERSION(1); \
379 *(etype *) ea = (etype) u64; \
381 /* You can't assign a floating point number to an integer array. */ \
384 NO_WIDENING_CONVERSION; \
388 #define ASSIGN_REAL(etype) G_STMT_START{\
392 CHECK_WIDENING_CONVERSION(0); \
393 *(etype *) ea = (etype) r64; \
395 /* All integer values fit into a floating point array, so we don't */ \
396 /* need to CHECK_WIDENING_CONVERSION here. */ \
401 *(etype *) ea = (etype) i64; \
407 case MONO_TYPE_CHAR: \
408 *(etype *) ea = (etype) u64; \
415 u64 = *(guint8 *) va;
418 u64 = *(guint16 *) va;
421 u64 = *(guint32 *) va;
424 u64 = *(guint64 *) va;
430 i64 = *(gint16 *) va;
433 i64 = *(gint32 *) va;
436 i64 = *(gint64 *) va;
439 r64 = *(gfloat *) va;
442 r64 = *(gdouble *) va;
445 u64 = *(guint16 *) va;
447 case MONO_TYPE_BOOLEAN:
448 /* Boolean is only compatible with itself. */
461 NO_WIDENING_CONVERSION;
468 /* If we can't do a direct copy, let's try a widening conversion. */
471 ASSIGN_UNSIGNED (guint16);
473 ASSIGN_UNSIGNED (guint8);
475 ASSIGN_UNSIGNED (guint16);
477 ASSIGN_UNSIGNED (guint32);
479 ASSIGN_UNSIGNED (guint64);
481 ASSIGN_SIGNED (gint8);
483 ASSIGN_SIGNED (gint16);
485 ASSIGN_SIGNED (gint32);
487 ASSIGN_SIGNED (gint64);
489 ASSIGN_REAL (gfloat);
491 ASSIGN_REAL (gdouble);
495 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
499 #undef NO_WIDENING_CONVERSION
500 #undef CHECK_WIDENING_CONVERSION
501 #undef ASSIGN_UNSIGNED
507 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
515 MONO_CHECK_ARG_NULL (idxs);
517 ic = idxs->obj.vtable->klass;
518 ac = this->obj.vtable->klass;
520 g_assert (ic->rank == 1);
521 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
522 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
524 ind = (gint32 *)idxs->vector;
526 if (this->bounds == NULL) {
527 if (*ind < 0 || *ind >= this->max_length)
528 mono_raise_exception (mono_get_exception_index_out_of_range ());
530 ves_icall_System_Array_SetValueImpl (this, value, *ind);
534 for (i = 0; i < ac->rank; i++)
535 if ((ind [i] < this->bounds [i].lower_bound) ||
536 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
537 mono_raise_exception (mono_get_exception_index_out_of_range ());
539 pos = ind [0] - this->bounds [0].lower_bound;
540 for (i = 1; i < ac->rank; i++)
541 pos = pos * this->bounds [i].length + ind [i] -
542 this->bounds [i].lower_bound;
544 ves_icall_System_Array_SetValueImpl (this, value, pos);
548 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
552 mono_array_size_t *sizes, i;
553 gboolean bounded = FALSE;
557 MONO_CHECK_ARG_NULL (type);
558 MONO_CHECK_ARG_NULL (lengths);
560 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
562 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
564 for (i = 0; i < mono_array_length (lengths); i++)
565 if (mono_array_get (lengths, gint32, i) < 0)
566 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
568 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
569 /* vectors are not the same as one dimensional arrays with no-zero bounds */
574 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
576 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
577 for (i = 0; i < aklass->rank; ++i) {
578 sizes [i] = mono_array_get (lengths, guint32, i);
580 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
582 sizes [i + aklass->rank] = 0;
585 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
591 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
595 mono_array_size_t *sizes, i;
596 gboolean bounded = FALSE;
600 MONO_CHECK_ARG_NULL (type);
601 MONO_CHECK_ARG_NULL (lengths);
603 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
605 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
607 for (i = 0; i < mono_array_length (lengths); i++)
608 if ((mono_array_get (lengths, gint64, i) < 0) ||
609 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
610 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
612 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
613 /* vectors are not the same as one dimensional arrays with no-zero bounds */
618 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
620 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
621 for (i = 0; i < aklass->rank; ++i) {
622 sizes [i] = mono_array_get (lengths, guint64, i);
624 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
626 sizes [i + aklass->rank] = 0;
629 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
635 ves_icall_System_Array_GetRank (MonoObject *this)
639 return this->vtable->klass->rank;
643 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
645 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
646 mono_array_size_t length;
650 if ((dimension < 0) || (dimension >= rank))
651 mono_raise_exception (mono_get_exception_index_out_of_range ());
653 if (this->bounds == NULL)
654 length = this->max_length;
656 length = this->bounds [dimension].length;
658 #ifdef MONO_BIG_ARRAYS
659 if (length > G_MAXINT32)
660 mono_raise_exception (mono_get_exception_overflow ());
666 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
668 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
672 if ((dimension < 0) || (dimension >= rank))
673 mono_raise_exception (mono_get_exception_index_out_of_range ());
675 if (this->bounds == NULL)
676 return this->max_length;
678 return this->bounds [dimension].length;
682 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
684 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
688 if ((dimension < 0) || (dimension >= rank))
689 mono_raise_exception (mono_get_exception_index_out_of_range ());
691 if (this->bounds == NULL)
694 return this->bounds [dimension].lower_bound;
698 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
700 int sz = mono_array_element_size (mono_object_class (arr));
701 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
705 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
710 MonoClass *src_class;
711 MonoClass *dest_class;
716 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
719 if (source->bounds || dest->bounds)
722 if ((dest_idx + length > mono_array_length (dest)) ||
723 (source_idx + length > mono_array_length (source)))
726 src_class = source->obj.vtable->klass->element_class;
727 dest_class = dest->obj.vtable->klass->element_class;
730 * Handle common cases.
733 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
734 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
735 int has_refs = dest_class->has_references;
736 for (i = source_idx; i < source_idx + length; ++i) {
737 MonoObject *elem = mono_array_get (source, MonoObject*, i);
738 if (elem && !mono_object_isinst (elem, dest_class))
742 element_size = mono_array_element_size (dest->obj.vtable->klass);
743 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
744 for (i = 0; i < length; ++i) {
745 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
746 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
750 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
752 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
757 /* Check if we're copying a char[] <==> (u)short[] */
758 if (src_class != dest_class) {
759 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
762 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
764 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
765 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
766 for (i = source_idx; i < source_idx + length; ++i) {
767 MonoObject *elem = mono_array_get (source, MonoObject*, i);
768 if (elem && !mono_object_isinst (elem, dest_class))
775 if (dest_class->valuetype) {
776 element_size = mono_array_element_size (source->obj.vtable->klass);
777 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
778 if (dest_class->has_references) {
779 mono_value_copy_array (dest, dest_idx, source_addr, length);
781 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
782 memmove (dest_addr, source_addr, element_size * length);
785 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
792 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
801 ao = (MonoArray *)this;
802 ac = (MonoClass *)ao->obj.vtable->klass;
804 esize = mono_array_element_size (ac);
805 ea = (gpointer*)((char*)ao->vector + (pos * esize));
807 memcpy (value, ea, esize);
811 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
820 ao = (MonoArray *)this;
821 ac = (MonoClass *)ao->obj.vtable->klass;
822 ec = ac->element_class;
824 esize = mono_array_element_size (ac);
825 ea = (gpointer*)((char*)ao->vector + (pos * esize));
827 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
828 g_assert (esize == sizeof (gpointer));
829 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
831 g_assert (ec->inited);
832 if (ec->has_references)
833 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
834 memcpy (ea, value, esize);
839 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
841 MonoClass *klass = array->obj.vtable->klass;
842 guint32 size = mono_array_element_size (klass);
843 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
845 const char *field_data;
847 if (MONO_TYPE_IS_REFERENCE (type) ||
848 (type->type == MONO_TYPE_VALUETYPE &&
849 (!mono_type_get_class (type) ||
850 mono_type_get_class (type)->has_references))) {
851 MonoException *exc = mono_get_exception_argument("array",
852 "Cannot initialize array containing references");
853 mono_raise_exception (exc);
856 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
857 MonoException *exc = mono_get_exception_argument("field_handle",
858 "Field doesn't have an RVA");
859 mono_raise_exception (exc);
862 size *= array->max_length;
863 field_data = mono_field_get_data (field_handle);
865 if (size > mono_type_size (field_handle->type, &align)) {
866 MonoException *exc = mono_get_exception_argument("field_handle",
867 "Field not large enough to fill array");
868 mono_raise_exception (exc);
871 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
873 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
874 guint ## n *src = (guint ## n *) field_data; \
875 guint ## n *end = (guint ## n *)((char*)src + size); \
877 for (; src < end; data++, src++) { \
878 *data = read ## n (src); \
882 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
884 switch (type->type) {
901 memcpy (mono_array_addr (array, char, 0), field_data, size);
905 memcpy (mono_array_addr (array, char, 0), field_data, size);
907 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
910 double *data = (double*)mono_array_addr (array, double, 0);
912 for (i = 0; i < size; i++, data++) {
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
926 return offsetof (MonoString, chars);
930 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
934 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
937 return mono_object_clone (obj);
941 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
946 MONO_CHECK_ARG_NULL (handle);
948 klass = mono_class_from_mono_type (handle);
949 MONO_CHECK_ARG (handle, klass);
951 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
953 /* This will call the type constructor */
954 mono_runtime_class_init (vtable);
958 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
962 mono_image_check_for_module_cctor (image);
963 if (image->has_module_cctor) {
964 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
965 /*It's fine to raise the exception here*/
966 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
971 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
975 return mono_object_clone (this);
979 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
982 MonoObject **values = NULL;
986 MonoClassField* field;
991 klass = mono_object_class (this);
993 if (mono_class_num_fields (klass) == 0)
994 return mono_object_hash (this);
997 * Compute the starting value of the hashcode for fields of primitive
998 * types, and return the remaining fields in an array to the managed side.
999 * This way, we can avoid costly reflection operations in managed code.
1002 while ((field = mono_class_get_fields (klass, &iter))) {
1003 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1005 if (mono_field_is_deleted (field))
1007 /* FIXME: Add more types */
1008 switch (field->type->type) {
1010 result ^= *(gint32*)((guint8*)this + field->offset);
1012 case MONO_TYPE_STRING: {
1014 s = *(MonoString**)((guint8*)this + field->offset);
1016 result ^= mono_string_hash (s);
1021 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1022 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1023 values [count++] = o;
1029 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1030 for (i = 0; i < count; ++i)
1031 mono_array_setref (*fields, i, values [i]);
1039 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1042 MonoObject **values = NULL;
1044 MonoClassField* field;
1048 MONO_ARCH_SAVE_REGS;
1050 MONO_CHECK_ARG_NULL (that);
1052 if (this->vtable != that->vtable)
1055 klass = mono_object_class (this);
1057 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1058 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1061 * Do the comparison for fields of primitive type and return a result if
1062 * possible. Otherwise, return the remaining fields in an array to the
1063 * managed side. This way, we can avoid costly reflection operations in
1068 while ((field = mono_class_get_fields (klass, &iter))) {
1069 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1071 if (mono_field_is_deleted (field))
1073 /* FIXME: Add more types */
1074 switch (field->type->type) {
1077 case MONO_TYPE_BOOLEAN:
1078 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1083 case MONO_TYPE_CHAR:
1084 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1089 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1094 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1098 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1102 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1107 case MONO_TYPE_STRING: {
1108 MonoString *s1, *s2;
1109 guint32 s1len, s2len;
1110 s1 = *(MonoString**)((guint8*)this + field->offset);
1111 s2 = *(MonoString**)((guint8*)that + field->offset);
1114 if ((s1 == NULL) || (s2 == NULL))
1116 s1len = mono_string_length (s1);
1117 s2len = mono_string_length (s2);
1121 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1127 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1128 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1129 values [count++] = o;
1130 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1131 values [count++] = o;
1134 if (klass->enumtype)
1135 /* enums only have one non-static field */
1141 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1142 for (i = 0; i < count; ++i)
1143 mono_array_setref (*fields, i, values [i]);
1150 static MonoReflectionType *
1151 ves_icall_System_Object_GetType (MonoObject *obj)
1153 MONO_ARCH_SAVE_REGS;
1155 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1156 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1158 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1162 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1164 MONO_ARCH_SAVE_REGS;
1166 mtype->type = &obj->vtable->klass->byval_arg;
1167 g_assert (mtype->type->type);
1171 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1173 MONO_ARCH_SAVE_REGS;
1175 MONO_CHECK_ARG_NULL (obj);
1177 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1181 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1182 MonoReflectionMethod *method,
1183 MonoArray *opt_param_types)
1185 MONO_ARCH_SAVE_REGS;
1187 MONO_CHECK_ARG_NULL (method);
1189 return mono_image_create_method_token (
1190 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1194 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1196 MONO_ARCH_SAVE_REGS;
1198 mono_image_create_pefile (mb, file);
1202 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1204 MONO_ARCH_SAVE_REGS;
1206 mono_image_build_metadata (mb);
1210 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1212 MONO_ARCH_SAVE_REGS;
1214 mono_image_register_token (mb->dynamic_image, token, obj);
1218 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1220 MonoMethod **dest = data;
1222 /* skip unmanaged frames */
1238 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1240 MonoMethod **dest = data;
1242 /* skip unmanaged frames */
1247 if (!strcmp (m->klass->name_space, "System.Reflection"))
1256 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1258 MonoMethod **dest = data;
1260 /* skip unmanaged frames */
1264 if (m->wrapper_type != MONO_WRAPPER_NONE)
1267 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1281 static MonoReflectionType *
1282 type_from_name (const char *str, MonoBoolean ignoreCase)
1284 MonoType *type = NULL;
1285 MonoAssembly *assembly = NULL;
1286 MonoTypeNameParse info;
1287 char *temp_str = g_strdup (str);
1288 gboolean type_resolve = FALSE;
1290 MONO_ARCH_SAVE_REGS;
1292 /* mono_reflection_parse_type() mangles the string */
1293 if (!mono_reflection_parse_type (temp_str, &info)) {
1294 mono_reflection_free_type_info (&info);
1299 if (info.assembly.name) {
1300 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1302 MonoMethod *m = mono_method_get_last_managed ();
1303 MonoMethod *dest = m;
1305 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1310 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1311 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1312 * to crash. This only seems to happen in some strange remoting
1313 * scenarios and I was unable to figure out what's happening there.
1314 * Dec 10, 2005 - Martin.
1318 assembly = dest->klass->image->assembly;
1320 g_warning (G_STRLOC);
1325 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1327 if (!info.assembly.name && !type) /* try mscorlib */
1328 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1330 mono_reflection_free_type_info (&info);
1336 return mono_type_get_object (mono_domain_get (), type);
1340 MonoReflectionType *
1341 mono_type_get (const char *str)
1343 char *copy = g_strdup (str);
1344 MonoReflectionType *type = type_from_name (copy, FALSE);
1351 static MonoReflectionType*
1352 ves_icall_type_from_name (MonoString *name,
1353 MonoBoolean throwOnError,
1354 MonoBoolean ignoreCase)
1356 char *str = mono_string_to_utf8 (name);
1357 MonoReflectionType *type;
1359 type = type_from_name (str, ignoreCase);
1362 MonoException *e = NULL;
1365 e = mono_get_exception_type_load (name, NULL);
1367 mono_loader_clear_error ();
1369 mono_raise_exception (e);
1376 static MonoReflectionType*
1377 ves_icall_type_from_handle (MonoType *handle)
1379 MonoDomain *domain = mono_domain_get ();
1380 MonoClass *klass = mono_class_from_mono_type (handle);
1382 MONO_ARCH_SAVE_REGS;
1384 mono_class_init (klass);
1385 return mono_type_get_object (domain, handle);
1389 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1391 MONO_ARCH_SAVE_REGS;
1393 if (c && type->type && c->type)
1394 return mono_metadata_type_equal (type->type, c->type);
1396 return (type == c) ? TRUE : FALSE;
1399 /* System.TypeCode */
1418 TYPECODE_STRING = 18
1422 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1424 int t = type->type->type;
1426 MONO_ARCH_SAVE_REGS;
1428 if (type->type->byref)
1429 return TYPECODE_OBJECT;
1433 case MONO_TYPE_VOID:
1434 return TYPECODE_OBJECT;
1435 case MONO_TYPE_BOOLEAN:
1436 return TYPECODE_BOOLEAN;
1438 return TYPECODE_BYTE;
1440 return TYPECODE_SBYTE;
1442 return TYPECODE_UINT16;
1444 return TYPECODE_INT16;
1445 case MONO_TYPE_CHAR:
1446 return TYPECODE_CHAR;
1450 return TYPECODE_OBJECT;
1452 return TYPECODE_UINT32;
1454 return TYPECODE_INT32;
1456 return TYPECODE_UINT64;
1458 return TYPECODE_INT64;
1460 return TYPECODE_SINGLE;
1462 return TYPECODE_DOUBLE;
1463 case MONO_TYPE_VALUETYPE:
1464 if (type->type->data.klass->enumtype) {
1465 t = mono_class_enum_basetype (type->type->data.klass)->type;
1468 MonoClass *k = type->type->data.klass;
1469 if (strcmp (k->name_space, "System") == 0) {
1470 if (strcmp (k->name, "Decimal") == 0)
1471 return TYPECODE_DECIMAL;
1472 else if (strcmp (k->name, "DateTime") == 0)
1473 return TYPECODE_DATETIME;
1476 return TYPECODE_OBJECT;
1477 case MONO_TYPE_STRING:
1478 return TYPECODE_STRING;
1479 case MONO_TYPE_SZARRAY:
1480 case MONO_TYPE_ARRAY:
1481 case MONO_TYPE_OBJECT:
1483 case MONO_TYPE_MVAR:
1484 case MONO_TYPE_TYPEDBYREF:
1485 return TYPECODE_OBJECT;
1486 case MONO_TYPE_CLASS:
1488 MonoClass *k = type->type->data.klass;
1489 if (strcmp (k->name_space, "System") == 0) {
1490 if (strcmp (k->name, "DBNull") == 0)
1491 return TYPECODE_DBNULL;
1494 return TYPECODE_OBJECT;
1495 case MONO_TYPE_GENERICINST:
1496 return TYPECODE_OBJECT;
1498 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1504 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1510 MONO_ARCH_SAVE_REGS;
1512 g_assert (type != NULL);
1514 domain = ((MonoObject *)type)->vtable->domain;
1516 if (!c) /* FIXME: dont know what do do here */
1519 klass = mono_class_from_mono_type (type->type);
1520 klassc = mono_class_from_mono_type (c->type);
1522 if (type->type->byref)
1523 return klassc == mono_defaults.object_class;
1525 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1529 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1535 MONO_ARCH_SAVE_REGS;
1537 g_assert (type != NULL);
1539 domain = ((MonoObject *)type)->vtable->domain;
1541 klass = mono_class_from_mono_type (type->type);
1542 klassc = mono_class_from_mono_type (c->type);
1544 if (type->type->byref && !c->type->byref)
1547 return mono_class_is_assignable_from (klass, klassc);
1551 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1553 MonoClass *klass = mono_class_from_mono_type (type->type);
1554 return mono_object_isinst (obj, klass) != NULL;
1558 ves_icall_get_attributes (MonoReflectionType *type)
1560 MonoClass *klass = mono_class_from_mono_type (type->type);
1562 MONO_ARCH_SAVE_REGS;
1564 return klass->flags;
1567 static MonoReflectionMarshal*
1568 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1570 MonoClass *klass = field->field->parent;
1571 MonoMarshalType *info;
1574 if (klass->generic_container ||
1575 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1578 info = mono_marshal_load_type_info (klass);
1580 for (i = 0; i < info->num_fields; ++i) {
1581 if (info->fields [i].field == field->field) {
1582 if (!info->fields [i].mspec)
1585 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1592 static MonoReflectionField*
1593 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1595 gboolean found = FALSE;
1602 klass = handle->parent;
1604 klass = mono_class_from_mono_type (type);
1606 /* Check that the field belongs to the class */
1607 for (k = klass; k; k = k->parent) {
1608 if (k == handle->parent) {
1615 /* The managed code will throw the exception */
1619 return mono_field_get_object (mono_domain_get (), klass, handle);
1622 static MonoReflectionField*
1623 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1625 MONO_ARCH_SAVE_REGS;
1629 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1633 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1635 MonoType *type = field->field->type;
1637 return type_array_from_modifiers (field->field->parent->image, type, optional);
1641 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1643 MonoDomain *domain = mono_domain_get ();
1644 MonoMethodSignature* sig;
1645 MONO_ARCH_SAVE_REGS;
1647 sig = mono_method_signature (method);
1649 g_assert (mono_loader_get_last_error ());
1650 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1653 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1654 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1655 info->attrs = method->flags;
1656 info->implattrs = method->iflags;
1657 if (sig->call_convention == MONO_CALL_DEFAULT)
1658 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1660 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1665 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1669 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1671 MonoDomain *domain = mono_domain_get ();
1673 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1676 static MonoReflectionMarshal*
1677 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1679 MonoDomain *domain = mono_domain_get ();
1680 MonoReflectionMarshal* res = NULL;
1681 MonoMarshalSpec **mspecs;
1684 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1685 mono_method_get_marshal_info (method, mspecs);
1688 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1690 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1692 mono_metadata_free_marshal_spec (mspecs [i]);
1699 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1701 return field->field->offset - sizeof (MonoObject);
1704 static MonoReflectionType*
1705 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1708 MONO_ARCH_SAVE_REGS;
1710 parent = declaring? field->field->parent: field->klass;
1712 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1716 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1719 MonoClassField *cf = field->field;
1723 MonoDomain *domain = mono_object_domain (field);
1725 gboolean is_static = FALSE;
1726 gboolean is_ref = FALSE;
1728 MONO_ARCH_SAVE_REGS;
1730 if (field->klass->image->assembly->ref_only)
1731 mono_raise_exception (mono_get_exception_invalid_operation (
1732 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1734 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1735 mono_security_core_clr_ensure_reflection_access_field (cf);
1737 mono_class_init (field->klass);
1739 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1742 if (obj && !is_static) {
1743 /* Check that the field belongs to the object */
1744 gboolean found = FALSE;
1747 for (k = obj->vtable->klass; k; k = k->parent) {
1748 if (k == cf->parent) {
1755 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);
1756 MonoException *ex = mono_get_exception_argument (NULL, msg);
1758 mono_raise_exception (ex);
1762 t = mono_type_get_underlying_type (cf->type);
1764 case MONO_TYPE_STRING:
1765 case MONO_TYPE_OBJECT:
1766 case MONO_TYPE_CLASS:
1767 case MONO_TYPE_ARRAY:
1768 case MONO_TYPE_SZARRAY:
1773 case MONO_TYPE_BOOLEAN:
1776 case MONO_TYPE_CHAR:
1785 case MONO_TYPE_VALUETYPE:
1788 case MONO_TYPE_GENERICINST:
1789 if (mono_type_generic_inst_is_valuetype (t)) {
1796 g_error ("type 0x%x not handled in "
1797 "ves_icall_Monofield_GetValue", t->type);
1803 vtable = mono_class_vtable_full (domain, cf->parent, TRUE);
1804 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1805 mono_runtime_class_init (vtable);
1810 mono_field_static_get_value (vtable, cf, &o);
1812 mono_field_get_value (obj, cf, &o);
1817 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1818 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1821 /* Convert the Nullable structure into a boxed vtype */
1823 buf = (guint8*)vtable->data + cf->offset;
1825 buf = (guint8*)obj + cf->offset;
1827 return mono_nullable_box (buf, nklass);
1830 /* boxed value type */
1831 klass = mono_class_from_mono_type (cf->type);
1832 o = mono_object_new (domain, klass);
1833 v = ((gchar *) o) + sizeof (MonoObject);
1835 mono_field_static_get_value (vtable, cf, v);
1837 mono_field_get_value (obj, cf, v);
1844 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1846 MonoClassField *cf = field->field;
1849 MONO_ARCH_SAVE_REGS;
1851 if (field->klass->image->assembly->ref_only)
1852 mono_raise_exception (mono_get_exception_invalid_operation (
1853 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1855 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1856 mono_security_core_clr_ensure_reflection_access_field (cf);
1858 v = (gchar *) value;
1859 if (!cf->type->byref) {
1860 switch (cf->type->type) {
1863 case MONO_TYPE_BOOLEAN:
1866 case MONO_TYPE_CHAR:
1875 case MONO_TYPE_VALUETYPE:
1877 v += sizeof (MonoObject);
1879 case MONO_TYPE_STRING:
1880 case MONO_TYPE_OBJECT:
1881 case MONO_TYPE_CLASS:
1882 case MONO_TYPE_ARRAY:
1883 case MONO_TYPE_SZARRAY:
1886 case MONO_TYPE_GENERICINST: {
1887 MonoGenericClass *gclass = cf->type->data.generic_class;
1888 g_assert (!gclass->context.class_inst->is_open);
1890 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1891 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1892 MonoObject *nullable;
1895 * Convert the boxed vtype into a Nullable structure.
1896 * This is complicated by the fact that Nullables have
1897 * a variable structure.
1899 nullable = mono_object_new (mono_domain_get (), nklass);
1901 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1903 v = mono_object_unbox (nullable);
1906 if (gclass->container_class->valuetype && (v != NULL))
1907 v += sizeof (MonoObject);
1911 g_error ("type 0x%x not handled in "
1912 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1917 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1918 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1919 if (!vtable->initialized)
1920 mono_runtime_class_init (vtable);
1921 mono_field_static_set_value (vtable, cf, v);
1923 mono_field_set_value (obj, cf, v);
1928 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1930 MonoObject *o = NULL;
1931 MonoClassField *field = this->field;
1933 MonoDomain *domain = mono_object_domain (this);
1935 MonoTypeEnum def_type;
1936 const char *def_value;
1938 MONO_ARCH_SAVE_REGS;
1940 mono_class_init (field->parent);
1942 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1943 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1945 if (field->parent->image->dynamic) {
1947 g_assert_not_reached ();
1950 def_value = mono_class_get_field_default_value (field, &def_type);
1955 case MONO_TYPE_BOOLEAN:
1958 case MONO_TYPE_CHAR:
1966 case MONO_TYPE_R8: {
1969 /* boxed value type */
1970 t = g_new0 (MonoType, 1);
1972 klass = mono_class_from_mono_type (t);
1974 o = mono_object_new (domain, klass);
1975 v = ((gchar *) o) + sizeof (MonoObject);
1976 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1979 case MONO_TYPE_STRING:
1980 case MONO_TYPE_CLASS:
1981 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1984 g_assert_not_reached ();
1990 static MonoReflectionType*
1991 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1993 MonoMethod *method = rmethod->method.method;
1995 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1998 /* From MonoProperty.cs */
2000 PInfo_Attributes = 1,
2001 PInfo_GetMethod = 1 << 1,
2002 PInfo_SetMethod = 1 << 2,
2003 PInfo_ReflectedType = 1 << 3,
2004 PInfo_DeclaringType = 1 << 4,
2009 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2011 MonoDomain *domain = mono_object_domain (property);
2013 MONO_ARCH_SAVE_REGS;
2015 if ((req_info & PInfo_ReflectedType) != 0)
2016 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2017 else if ((req_info & PInfo_DeclaringType) != 0)
2018 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2020 if ((req_info & PInfo_Name) != 0)
2021 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2023 if ((req_info & PInfo_Attributes) != 0)
2024 info->attrs = property->property->attrs;
2026 if ((req_info & PInfo_GetMethod) != 0)
2027 MONO_STRUCT_SETREF (info, get, property->property->get ?
2028 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2030 if ((req_info & PInfo_SetMethod) != 0)
2031 MONO_STRUCT_SETREF (info, set, property->property->set ?
2032 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2034 * There may be other methods defined for properties, though, it seems they are not exposed
2035 * in the reflection API
2040 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2042 MonoDomain *domain = mono_object_domain (event);
2044 MONO_ARCH_SAVE_REGS;
2046 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2047 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2049 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2050 info->attrs = event->event->attrs;
2051 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2052 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2053 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2055 if (event->event->other) {
2057 while (event->event->other [n])
2059 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2061 for (i = 0; i < n; i++)
2062 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2067 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2069 MonoDomain *domain = mono_object_domain (type);
2071 GPtrArray *ifaces = NULL;
2073 MonoClass *class = mono_class_from_mono_type (type->type);
2076 MonoGenericContext *context = NULL;
2078 MONO_ARCH_SAVE_REGS;
2080 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2081 context = mono_class_get_context (class);
2082 class = class->generic_class->container_class;
2085 mono_class_setup_vtable (class);
2087 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2089 for (parent = class; parent; parent = parent->parent) {
2090 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2092 for (i = 0; i < tmp_ifaces->len; ++i) {
2093 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2095 if (mono_bitset_test (slots, ic->interface_id))
2098 mono_bitset_set (slots, ic->interface_id);
2100 ifaces = g_ptr_array_new ();
2101 g_ptr_array_add (ifaces, ic);
2103 g_ptr_array_free (tmp_ifaces, TRUE);
2106 mono_bitset_free (slots);
2109 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2111 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2112 for (i = 0; i < ifaces->len; ++i) {
2113 MonoClass *ic = g_ptr_array_index (ifaces, i);
2114 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2115 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2116 inflated = ret = mono_class_inflate_generic_type (ret, context);
2118 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2120 mono_metadata_free_type (inflated);
2122 g_ptr_array_free (ifaces, TRUE);
2128 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2130 MonoClass *class = mono_class_from_mono_type (type->type);
2131 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2132 MonoReflectionMethod *member;
2135 int i = 0, len, ioffset;
2138 MONO_ARCH_SAVE_REGS;
2140 mono_class_setup_vtable (class);
2142 /* type doesn't implement iface: the exception is thrown in managed code */
2143 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2146 len = mono_class_num_methods (iclass);
2147 ioffset = mono_class_interface_offset (class, iclass);
2148 domain = mono_object_domain (type);
2149 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2150 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2153 while ((method = mono_class_get_methods (iclass, &iter))) {
2154 member = mono_method_get_object (domain, method, iclass);
2155 mono_array_setref (*methods, i, member);
2156 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2157 mono_array_setref (*targets, i, member);
2164 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2166 MonoClass *klass = mono_class_from_mono_type (type->type);
2168 if (klass->image->dynamic) {
2169 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2170 *packing = tb->packing_size;
2171 *size = tb->class_size;
2173 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2177 static MonoReflectionType*
2178 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2182 MONO_ARCH_SAVE_REGS;
2184 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2185 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2187 class = mono_class_from_mono_type (type->type);
2189 // GetElementType should only return a type for:
2190 // Array Pointer PassedByRef
2191 if (type->type->byref)
2192 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2193 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2194 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2195 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2196 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2201 static MonoReflectionType*
2202 ves_icall_get_type_parent (MonoReflectionType *type)
2204 MonoClass *class = mono_class_from_mono_type (type->type);
2206 MONO_ARCH_SAVE_REGS;
2208 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2212 ves_icall_type_ispointer (MonoReflectionType *type)
2214 MONO_ARCH_SAVE_REGS;
2216 return type->type->type == MONO_TYPE_PTR;
2220 ves_icall_type_isprimitive (MonoReflectionType *type)
2222 MONO_ARCH_SAVE_REGS;
2224 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)));
2228 ves_icall_type_isbyref (MonoReflectionType *type)
2230 MONO_ARCH_SAVE_REGS;
2232 return type->type->byref;
2236 ves_icall_type_iscomobject (MonoReflectionType *type)
2238 MonoClass *klass = mono_class_from_mono_type (type->type);
2239 MONO_ARCH_SAVE_REGS;
2241 return (klass && klass->is_com_object);
2244 static MonoReflectionModule*
2245 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2247 MonoClass *class = mono_class_from_mono_type (type->type);
2249 MONO_ARCH_SAVE_REGS;
2251 return mono_module_get_object (mono_object_domain (type), class->image);
2254 static MonoReflectionAssembly*
2255 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2257 MonoDomain *domain = mono_domain_get ();
2258 MonoClass *class = mono_class_from_mono_type (type->type);
2260 MONO_ARCH_SAVE_REGS;
2262 return mono_assembly_get_object (domain, class->image->assembly);
2265 static MonoReflectionType*
2266 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2268 MonoDomain *domain = mono_domain_get ();
2271 MONO_ARCH_SAVE_REGS;
2273 if (type->type->byref)
2275 if (type->type->type == MONO_TYPE_VAR)
2276 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2277 else if (type->type->type == MONO_TYPE_MVAR)
2278 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2280 class = mono_class_from_mono_type (type->type)->nested_in;
2282 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2285 static MonoReflectionType*
2286 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2288 MonoDomain *domain = mono_domain_get ();
2289 MonoClass *class = mono_class_from_mono_type (type->type);
2291 MONO_ARCH_SAVE_REGS;
2293 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2294 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2295 else if (class->element_class)
2296 return mono_type_get_object (domain, &class->element_class->byval_arg);
2302 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2304 MonoDomain *domain = mono_domain_get ();
2305 MonoClass *class = mono_class_from_mono_type (type->type);
2307 MONO_ARCH_SAVE_REGS;
2309 if (type->type->byref) {
2310 char *n = g_strdup_printf ("%s&", class->name);
2311 MonoString *res = mono_string_new (domain, n);
2317 return mono_string_new (domain, class->name);
2322 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2324 MonoDomain *domain = mono_domain_get ();
2325 MonoClass *class = mono_class_from_mono_type (type->type);
2327 MONO_ARCH_SAVE_REGS;
2329 while (class->nested_in)
2330 class = class->nested_in;
2332 if (class->name_space [0] == '\0')
2335 return mono_string_new (domain, class->name_space);
2339 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2343 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2344 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2346 class = mono_class_from_mono_type (type->type);
2351 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2354 MonoClass *klass, *pklass;
2355 MonoDomain *domain = mono_object_domain (type);
2356 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2358 MONO_ARCH_SAVE_REGS;
2360 klass = mono_class_from_mono_type (type->type);
2362 if (klass->generic_container) {
2363 MonoGenericContainer *container = klass->generic_container;
2364 res = mono_array_new_specific (array_vtable, container->type_argc);
2365 for (i = 0; i < container->type_argc; ++i) {
2366 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2367 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2369 } else if (klass->generic_class) {
2370 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2371 res = mono_array_new_specific (array_vtable, inst->type_argc);
2372 for (i = 0; i < inst->type_argc; ++i)
2373 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2375 res = mono_array_new_specific (array_vtable, 0);
2381 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2384 MONO_ARCH_SAVE_REGS;
2386 if (!IS_MONOTYPE (type))
2389 if (type->type->byref)
2392 klass = mono_class_from_mono_type (type->type);
2394 return klass->generic_container != NULL;
2397 static MonoReflectionType*
2398 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2401 MONO_ARCH_SAVE_REGS;
2403 if (type->type->byref)
2406 klass = mono_class_from_mono_type (type->type);
2407 if (klass->generic_container) {
2408 return type; /* check this one */
2410 if (klass->generic_class) {
2411 MonoClass *generic_class = klass->generic_class->container_class;
2413 if (generic_class->wastypebuilder && generic_class->reflection_info)
2414 return generic_class->reflection_info;
2416 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2421 static MonoReflectionType*
2422 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2424 MonoType *geninst, **types;
2427 MONO_ARCH_SAVE_REGS;
2429 count = mono_array_length (type_array);
2430 types = g_new0 (MonoType *, count);
2432 for (i = 0; i < count; i++) {
2433 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2434 types [i] = t->type;
2437 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2442 return mono_type_get_object (mono_object_domain (type), geninst);
2446 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2449 MONO_ARCH_SAVE_REGS;
2451 if (type->type->byref)
2454 klass = mono_class_from_mono_type (type->type);
2455 return klass->generic_class != NULL;
2459 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2462 MONO_ARCH_SAVE_REGS;
2464 if (!IS_MONOTYPE (type))
2467 if (type->type->byref)
2470 klass = mono_class_from_mono_type (type->type);
2471 return klass->generic_class != NULL || klass->generic_container != NULL;
2475 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2477 MONO_ARCH_SAVE_REGS;
2479 if (!IS_MONOTYPE (type))
2482 if (is_generic_parameter (type->type))
2483 return mono_type_get_generic_param_num (type->type);
2487 static GenericParameterAttributes
2488 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2490 MONO_ARCH_SAVE_REGS;
2492 g_assert (IS_MONOTYPE (type));
2493 g_assert (is_generic_parameter (type->type));
2494 return mono_generic_param_info (type->type->data.generic_param)->flags;
2498 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2500 MonoGenericParamInfo *param_info;
2506 MONO_ARCH_SAVE_REGS;
2508 g_assert (IS_MONOTYPE (type));
2510 domain = mono_object_domain (type);
2511 param_info = mono_generic_param_info (type->type->data.generic_param);
2512 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2515 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2516 for (i = 0; i < count; i++)
2517 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2524 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2526 MONO_ARCH_SAVE_REGS;
2527 return is_generic_parameter (type->type);
2531 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2533 MONO_ARCH_SAVE_REGS;
2534 return is_generic_parameter (tb->type.type);
2538 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2539 MonoReflectionType *t)
2541 enumtype->type = t->type;
2544 static MonoReflectionMethod*
2545 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2546 MonoReflectionMethod* generic)
2553 MONO_ARCH_SAVE_REGS;
2555 domain = ((MonoObject *)type)->vtable->domain;
2557 klass = mono_class_from_mono_type (type->type);
2560 while ((method = mono_class_get_methods (klass, &iter))) {
2561 if (method->token == generic->method->token)
2562 return mono_method_get_object (domain, method, klass);
2570 static MonoReflectionMethod *
2571 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2574 MonoType *type = ref_type->type;
2576 MONO_ARCH_SAVE_REGS;
2578 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2579 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2580 if (type->type == MONO_TYPE_VAR)
2583 method = mono_type_get_generic_param_owner (type)->owner.method;
2585 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2588 static MonoReflectionDllImportAttribute*
2589 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2591 static MonoClass *DllImportAttributeClass = NULL;
2592 MonoDomain *domain = mono_domain_get ();
2593 MonoReflectionDllImportAttribute *attr;
2594 MonoImage *image = method->klass->image;
2595 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2596 MonoTableInfo *tables = image->tables;
2597 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2598 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2599 guint32 im_cols [MONO_IMPLMAP_SIZE];
2600 guint32 scope_token;
2601 const char *import = NULL;
2602 const char *scope = NULL;
2605 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2608 if (!DllImportAttributeClass) {
2609 DllImportAttributeClass =
2610 mono_class_from_name (mono_defaults.corlib,
2611 "System.Runtime.InteropServices", "DllImportAttribute");
2612 g_assert (DllImportAttributeClass);
2615 if (method->klass->image->dynamic) {
2616 MonoReflectionMethodAux *method_aux =
2617 g_hash_table_lookup (
2618 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2620 import = method_aux->dllentry;
2621 scope = method_aux->dll;
2624 if (!import || !scope) {
2625 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2630 if (piinfo->implmap_idx) {
2631 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2633 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2634 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2635 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2636 scope = mono_metadata_string_heap (image, scope_token);
2639 flags = piinfo->piflags;
2641 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2643 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2644 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2645 attr->call_conv = (flags & 0x700) >> 8;
2646 attr->charset = ((flags & 0x6) >> 1) + 1;
2647 if (attr->charset == 1)
2649 attr->exact_spelling = (flags & 0x1) != 0;
2650 attr->set_last_error = (flags & 0x40) != 0;
2651 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2652 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2653 attr->preserve_sig = FALSE;
2658 static MonoReflectionMethod *
2659 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2661 MonoMethodInflated *imethod;
2664 MONO_ARCH_SAVE_REGS;
2666 if (method->method->is_generic)
2669 if (!method->method->is_inflated)
2672 imethod = (MonoMethodInflated *) method->method;
2674 result = imethod->declaring;
2675 /* Not a generic method. */
2676 if (!result->is_generic)
2679 if (method->method->klass->image->dynamic) {
2680 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2681 MonoReflectionMethod *res;
2684 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2685 * the dynamic case as well ?
2687 mono_loader_lock ();
2688 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2689 mono_loader_unlock ();
2695 if (imethod->context.class_inst) {
2696 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2697 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2700 return mono_method_get_object (mono_object_domain (method), result, NULL);
2704 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2706 MONO_ARCH_SAVE_REGS;
2708 return mono_method_signature (method->method)->generic_param_count != 0;
2712 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2714 MONO_ARCH_SAVE_REGS;
2716 return method->method->is_generic;
2720 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2725 MONO_ARCH_SAVE_REGS;
2727 domain = mono_object_domain (method);
2729 if (method->method->is_inflated) {
2730 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2733 count = inst->type_argc;
2734 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2736 for (i = 0; i < count; i++)
2737 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2743 count = mono_method_signature (method->method)->generic_param_count;
2744 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2746 for (i = 0; i < count; i++) {
2747 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2748 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2749 MonoClass *pklass = mono_class_from_generic_parameter (
2750 param, method->method->klass->image, TRUE);
2751 mono_array_setref (res, i,
2752 mono_type_get_object (domain, &pklass->byval_arg));
2759 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2762 * Invoke from reflection is supposed to always be a virtual call (the API
2763 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2764 * greater flexibility.
2766 MonoMethod *m = method->method;
2770 MONO_ARCH_SAVE_REGS;
2774 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2775 mono_security_core_clr_ensure_reflection_access_method (m);
2777 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2779 if (!mono_object_isinst (this, m->klass)) {
2780 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2783 m = mono_object_get_virtual_method (this, m);
2784 /* must pass the pointer to the value for valuetype methods */
2785 if (m->klass->valuetype)
2786 obj = mono_object_unbox (this);
2787 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2788 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2793 pcount = params? mono_array_length (params): 0;
2794 if (pcount != mono_method_signature (m)->param_count) {
2795 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2799 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2800 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."));
2804 if (m->klass->image->assembly->ref_only) {
2805 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."));
2809 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2811 mono_array_size_t *lengths;
2812 mono_array_size_t *lower_bounds;
2813 pcount = mono_array_length (params);
2814 lengths = alloca (sizeof (mono_array_size_t) * pcount);
2815 for (i = 0; i < pcount; ++i)
2816 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2818 if (m->klass->rank == pcount) {
2819 /* Only lengths provided. */
2820 lower_bounds = NULL;
2822 g_assert (pcount == (m->klass->rank * 2));
2823 /* lower bounds are first. */
2824 lower_bounds = lengths;
2825 lengths += m->klass->rank;
2828 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2830 return mono_runtime_invoke_array (m, obj, params, NULL);
2834 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2836 MonoDomain *domain = mono_object_domain (method);
2837 MonoMethod *m = method->method;
2838 MonoMethodSignature *sig = mono_method_signature (m);
2839 MonoArray *out_args;
2841 int i, j, outarg_count = 0;
2843 MONO_ARCH_SAVE_REGS;
2845 if (m->klass == mono_defaults.object_class) {
2847 if (!strcmp (m->name, "FieldGetter")) {
2848 MonoClass *k = this->vtable->klass;
2852 /* If this is a proxy, then it must be a CBO */
2853 if (k == mono_defaults.transparent_proxy_class) {
2854 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2855 this = tp->rp->unwrapped_server;
2857 k = this->vtable->klass;
2860 name = mono_array_get (params, MonoString *, 1);
2861 str = mono_string_to_utf8 (name);
2864 MonoClassField* field = mono_class_get_field_from_name (k, str);
2866 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2867 if (field_klass->valuetype)
2868 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2870 result = *((gpointer *)((char *)this + field->offset));
2872 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2873 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2874 mono_array_setref (out_args, 0, result);
2882 g_assert_not_reached ();
2884 } else if (!strcmp (m->name, "FieldSetter")) {
2885 MonoClass *k = this->vtable->klass;
2891 /* If this is a proxy, then it must be a CBO */
2892 if (k == mono_defaults.transparent_proxy_class) {
2893 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2894 this = tp->rp->unwrapped_server;
2896 k = this->vtable->klass;
2899 name = mono_array_get (params, MonoString *, 1);
2900 str = mono_string_to_utf8 (name);
2903 MonoClassField* field = mono_class_get_field_from_name (k, str);
2905 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2906 MonoObject *val = mono_array_get (params, gpointer, 2);
2908 if (field_klass->valuetype) {
2909 size = mono_type_size (field->type, &align);
2911 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2913 memcpy ((char *)this + field->offset,
2914 ((char *)val) + sizeof (MonoObject), size);
2916 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2919 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2920 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2930 g_assert_not_reached ();
2935 for (i = 0; i < mono_array_length (params); i++) {
2936 if (sig->params [i]->byref)
2940 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2942 /* handle constructors only for objects already allocated */
2943 if (!strcmp (method->method->name, ".ctor"))
2946 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2947 g_assert (!method->method->klass->valuetype);
2948 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2950 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2951 if (sig->params [i]->byref) {
2953 arg = mono_array_get (params, gpointer, i);
2954 mono_array_setref (out_args, j, arg);
2959 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2965 read_enum_value (char *mem, int type)
2969 return *(guint8*)mem;
2971 return *(gint8*)mem;
2973 return *(guint16*)mem;
2975 return *(gint16*)mem;
2977 return *(guint32*)mem;
2979 return *(gint32*)mem;
2981 return *(guint64*)mem;
2983 return *(gint64*)mem;
2985 g_assert_not_reached ();
2991 write_enum_value (char *mem, int type, guint64 value)
2995 case MONO_TYPE_I1: {
2996 guint8 *p = (guint8*)mem;
3001 case MONO_TYPE_I2: {
3002 guint16 *p = (void*)mem;
3007 case MONO_TYPE_I4: {
3008 guint32 *p = (void*)mem;
3013 case MONO_TYPE_I8: {
3014 guint64 *p = (void*)mem;
3019 g_assert_not_reached ();
3025 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3028 MonoClass *enumc, *objc;
3032 MONO_ARCH_SAVE_REGS;
3034 MONO_CHECK_ARG_NULL (enumType);
3035 MONO_CHECK_ARG_NULL (value);
3037 domain = mono_object_domain (enumType);
3038 enumc = mono_class_from_mono_type (enumType->type);
3039 objc = value->vtable->klass;
3041 if (!enumc->enumtype)
3042 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3043 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3044 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."));
3046 res = mono_object_new (domain, enumc);
3047 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3048 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3054 ves_icall_System_Enum_get_value (MonoObject *this)
3062 MONO_ARCH_SAVE_REGS;
3067 g_assert (this->vtable->klass->enumtype);
3069 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3070 res = mono_object_new (mono_object_domain (this), enumc);
3071 dst = (char *)res + sizeof (MonoObject);
3072 src = (char *)this + sizeof (MonoObject);
3073 size = mono_class_value_size (enumc, NULL);
3075 memcpy (dst, src, size);
3080 static MonoReflectionType *
3081 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3083 MONO_ARCH_SAVE_REGS;
3085 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3089 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3091 gpointer tdata = (char *)this + sizeof (MonoObject);
3092 gpointer odata = (char *)other + sizeof (MonoObject);
3093 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3094 g_assert (basetype);
3096 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3097 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3098 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3101 return me > other ? 1 : -1; \
3104 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3105 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3106 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3109 return me - other; \
3112 switch (basetype->type) {
3114 COMPARE_ENUM_VALUES (guint8);
3116 COMPARE_ENUM_VALUES (gint8);
3117 case MONO_TYPE_CHAR:
3119 COMPARE_ENUM_VALUES_RANGE (guint16);
3121 COMPARE_ENUM_VALUES (gint16);
3123 COMPARE_ENUM_VALUES (guint32);
3125 COMPARE_ENUM_VALUES (gint32);
3127 COMPARE_ENUM_VALUES (guint64);
3129 COMPARE_ENUM_VALUES (gint64);
3131 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3133 #undef COMPARE_ENUM_VALUES_RANGE
3134 #undef COMPARE_ENUM_VALUES
3139 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3141 gpointer data = (char *)this + sizeof (MonoObject);
3142 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3143 g_assert (basetype);
3145 switch (basetype->type) {
3147 return *((gint8*)data);
3149 return *((guint8*)data);
3150 case MONO_TYPE_CHAR:
3152 return *((guint16*)data);
3155 return *((gint16*)data);
3157 return *((guint32*)data);
3159 return *((gint32*)data);
3161 case MONO_TYPE_I8: {
3162 gint64 value = *((gint64*)data);
3163 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3166 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3172 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3174 MonoDomain *domain = mono_object_domain (type);
3175 MonoClass *enumc = mono_class_from_mono_type (type->type);
3176 guint j = 0, nvalues, crow;
3178 MonoClassField *field;
3180 MONO_ARCH_SAVE_REGS;
3182 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3183 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3184 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3185 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3189 while ((field = mono_class_get_fields (enumc, &iter))) {
3192 MonoTypeEnum def_type;
3194 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3196 if (mono_field_is_deleted (field))
3198 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3200 p = mono_class_get_field_default_value (field, &def_type);
3201 len = mono_metadata_decode_blob_size (p, &p);
3202 switch (mono_class_enum_basetype (enumc)->type) {
3205 mono_array_set (info->values, gchar, j, *p);
3207 case MONO_TYPE_CHAR:
3210 mono_array_set (info->values, gint16, j, read16 (p));
3214 mono_array_set (info->values, gint32, j, read32 (p));
3218 mono_array_set (info->values, gint64, j, read64 (p));
3221 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3228 BFLAGS_IgnoreCase = 1,
3229 BFLAGS_DeclaredOnly = 2,
3230 BFLAGS_Instance = 4,
3232 BFLAGS_Public = 0x10,
3233 BFLAGS_NonPublic = 0x20,
3234 BFLAGS_FlattenHierarchy = 0x40,
3235 BFLAGS_InvokeMethod = 0x100,
3236 BFLAGS_CreateInstance = 0x200,
3237 BFLAGS_GetField = 0x400,
3238 BFLAGS_SetField = 0x800,
3239 BFLAGS_GetProperty = 0x1000,
3240 BFLAGS_SetProperty = 0x2000,
3241 BFLAGS_ExactBinding = 0x10000,
3242 BFLAGS_SuppressChangeType = 0x20000,
3243 BFLAGS_OptionalParamBinding = 0x40000
3246 static MonoReflectionField *
3247 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3250 MonoClass *startklass, *klass;
3252 MonoClassField *field;
3255 int (*compare_func) (const char *s1, const char *s2) = NULL;
3256 domain = ((MonoObject *)type)->vtable->domain;
3257 klass = startklass = mono_class_from_mono_type (type->type);
3259 MONO_ARCH_SAVE_REGS;
3262 mono_raise_exception (mono_get_exception_argument_null ("name"));
3263 if (type->type->byref)
3266 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3269 if (klass->exception_type != MONO_EXCEPTION_NONE)
3270 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3273 while ((field = mono_class_get_fields (klass, &iter))) {
3276 if (field->type == NULL)
3278 if (mono_field_is_deleted (field))
3280 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3281 if (bflags & BFLAGS_Public)
3283 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3284 if (bflags & BFLAGS_NonPublic) {
3291 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3292 if (bflags & BFLAGS_Static)
3293 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3296 if (bflags & BFLAGS_Instance)
3303 utf8_name = mono_string_to_utf8 (name);
3305 if (compare_func (mono_field_get_name (field), utf8_name)) {
3311 return mono_field_get_object (domain, klass, field);
3313 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3320 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3323 MonoClass *startklass, *klass, *refklass;
3328 MonoClassField *field;
3329 MonoPtrArray tmp_array;
3331 MONO_ARCH_SAVE_REGS;
3333 domain = ((MonoObject *)type)->vtable->domain;
3334 if (type->type->byref)
3335 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3336 klass = startklass = mono_class_from_mono_type (type->type);
3337 refklass = mono_class_from_mono_type (reftype->type);
3339 mono_ptr_array_init (tmp_array, 2);
3342 if (klass->exception_type != MONO_EXCEPTION_NONE)
3343 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3346 while ((field = mono_class_get_fields (klass, &iter))) {
3348 if (mono_field_is_deleted (field))
3350 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3351 if (bflags & BFLAGS_Public)
3353 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3354 if (bflags & BFLAGS_NonPublic) {
3361 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3362 if (bflags & BFLAGS_Static)
3363 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3366 if (bflags & BFLAGS_Instance)
3372 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3373 mono_ptr_array_append (tmp_array, member);
3375 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3378 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3380 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3381 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3383 mono_ptr_array_destroy (tmp_array);
3389 method_nonpublic (MonoMethod* method, gboolean start_klass)
3391 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3392 case METHOD_ATTRIBUTE_ASSEM:
3393 return (start_klass || mono_defaults.generic_ilist_class);
3394 case METHOD_ATTRIBUTE_PRIVATE:
3396 case METHOD_ATTRIBUTE_PUBLIC:
3404 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3406 static MonoClass *MethodInfo_array;
3408 MonoClass *startklass, *klass, *refklass;
3413 int i, len, match, nslots;
3414 /*FIXME, use MonoBitSet*/
3415 guint32 method_slots_default [8];
3416 guint32 *method_slots = NULL;
3417 gchar *mname = NULL;
3418 int (*compare_func) (const char *s1, const char *s2) = NULL;
3419 MonoVTable *array_vtable;
3421 MonoPtrArray tmp_array;
3423 MONO_ARCH_SAVE_REGS;
3425 mono_ptr_array_init (tmp_array, 4);
3427 if (!MethodInfo_array) {
3428 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3429 mono_memory_barrier ();
3430 MethodInfo_array = klass;
3433 domain = ((MonoObject *)type)->vtable->domain;
3434 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3435 if (type->type->byref)
3436 return mono_array_new_specific (array_vtable, 0);
3437 klass = startklass = mono_class_from_mono_type (type->type);
3438 refklass = mono_class_from_mono_type (reftype->type);
3441 mname = mono_string_to_utf8 (name);
3442 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3445 /* An optimization for calls made from Delegate:CreateDelegate () */
3446 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3447 method = mono_get_delegate_invoke (klass);
3448 if (mono_loader_get_last_error ())
3451 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3453 res = mono_array_new_specific (array_vtable, 1);
3454 mono_array_setref (res, 0, member);
3459 mono_class_setup_vtable (klass);
3460 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3463 if (is_generic_parameter (type->type))
3464 nslots = mono_class_get_vtable_size (klass->parent);
3466 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3467 if (nslots >= sizeof (method_slots_default) * 8) {
3468 method_slots = g_new0 (guint32, nslots / 32 + 1);
3470 method_slots = method_slots_default;
3471 memset (method_slots, 0, sizeof (method_slots_default));
3474 mono_class_setup_vtable (klass);
3475 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3479 while ((method = mono_class_get_methods (klass, &iter))) {
3481 if (method->slot != -1) {
3482 g_assert (method->slot < nslots);
3483 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3485 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3488 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3490 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3491 if (bflags & BFLAGS_Public)
3493 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3499 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3500 if (bflags & BFLAGS_Static)
3501 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3504 if (bflags & BFLAGS_Instance)
3512 if (compare_func (mname, method->name))
3518 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3520 mono_ptr_array_append (tmp_array, member);
3522 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3526 if (method_slots != method_slots_default)
3527 g_free (method_slots);
3529 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3531 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3532 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3534 mono_ptr_array_destroy (tmp_array);
3539 if (method_slots != method_slots_default)
3540 g_free (method_slots);
3541 mono_ptr_array_destroy (tmp_array);
3542 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3543 ex = mono_class_get_exception_for_failure (klass);
3545 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3546 mono_loader_clear_error ();
3548 mono_raise_exception (ex);
3553 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3556 static MonoClass *System_Reflection_ConstructorInfo;
3557 MonoClass *startklass, *klass, *refklass;
3562 gpointer iter = NULL;
3563 MonoPtrArray tmp_array;
3565 MONO_ARCH_SAVE_REGS;
3567 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3569 domain = ((MonoObject *)type)->vtable->domain;
3570 if (type->type->byref)
3571 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3572 klass = startklass = mono_class_from_mono_type (type->type);
3573 refklass = mono_class_from_mono_type (reftype->type);
3575 if (klass->exception_type != MONO_EXCEPTION_NONE)
3576 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3578 if (!System_Reflection_ConstructorInfo)
3579 System_Reflection_ConstructorInfo = mono_class_from_name (
3580 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3583 while ((method = mono_class_get_methods (klass, &iter))) {
3585 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3587 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3588 if (bflags & BFLAGS_Public)
3591 if (bflags & BFLAGS_NonPublic)
3597 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3598 if (bflags & BFLAGS_Static)
3599 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3602 if (bflags & BFLAGS_Instance)
3608 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3610 mono_ptr_array_append (tmp_array, member);
3613 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3615 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3616 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3618 mono_ptr_array_destroy (tmp_array);
3624 property_hash (gconstpointer data)
3626 MonoProperty *prop = (MonoProperty*)data;
3628 return g_str_hash (prop->name);
3632 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3634 // Properties are hide-by-name-and-signature
3635 if (!g_str_equal (prop1->name, prop2->name))
3638 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3640 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3646 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3651 return method_nonpublic (accessor, start_klass);
3655 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3658 static MonoClass *System_Reflection_PropertyInfo;
3659 MonoClass *startklass, *klass;
3665 gchar *propname = NULL;
3666 int (*compare_func) (const char *s1, const char *s2) = NULL;
3668 GHashTable *properties;
3669 MonoPtrArray tmp_array;
3671 MONO_ARCH_SAVE_REGS;
3673 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3675 if (!System_Reflection_PropertyInfo)
3676 System_Reflection_PropertyInfo = mono_class_from_name (
3677 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3679 domain = ((MonoObject *)type)->vtable->domain;
3680 if (type->type->byref)
3681 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3682 klass = startklass = mono_class_from_mono_type (type->type);
3684 propname = mono_string_to_utf8 (name);
3685 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3688 mono_class_setup_vtable (klass);
3690 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3692 mono_class_setup_vtable (klass);
3693 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3694 g_hash_table_destroy (properties);
3697 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3701 while ((prop = mono_class_get_properties (klass, &iter))) {
3707 flags = method->flags;
3710 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3711 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3712 if (bflags & BFLAGS_Public)
3714 } else if (bflags & BFLAGS_NonPublic) {
3715 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3716 property_accessor_nonpublic(prop->set, startklass == klass)) {
3723 if (flags & METHOD_ATTRIBUTE_STATIC) {
3724 if (bflags & BFLAGS_Static)
3725 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3728 if (bflags & BFLAGS_Instance)
3737 if (compare_func (propname, prop->name))
3741 if (g_hash_table_lookup (properties, prop))
3744 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3746 g_hash_table_insert (properties, prop, prop);
3748 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3751 g_hash_table_destroy (properties);
3754 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3755 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3756 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3758 mono_ptr_array_destroy (tmp_array);
3763 static MonoReflectionEvent *
3764 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3767 MonoClass *klass, *startklass;
3773 MONO_ARCH_SAVE_REGS;
3775 event_name = mono_string_to_utf8 (name);
3776 if (type->type->byref)
3778 klass = startklass = mono_class_from_mono_type (type->type);
3779 domain = mono_object_domain (type);
3782 if (klass->exception_type != MONO_EXCEPTION_NONE)
3783 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3786 while ((event = mono_class_get_events (klass, &iter))) {
3787 if (strcmp (event->name, event_name))
3790 method = event->add;
3792 method = event->remove;
3794 method = event->raise;
3796 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3797 if (!(bflags & BFLAGS_Public))
3800 if (!(bflags & BFLAGS_NonPublic))
3802 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3806 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3807 if (!(bflags & BFLAGS_Static))
3809 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3812 if (!(bflags & BFLAGS_Instance))
3816 if (!(bflags & BFLAGS_NonPublic))
3819 g_free (event_name);
3820 return mono_event_get_object (domain, startklass, event);
3823 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3826 g_free (event_name);
3831 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3834 static MonoClass *System_Reflection_EventInfo;
3835 MonoClass *startklass, *klass;
3842 MonoPtrArray tmp_array;
3844 MONO_ARCH_SAVE_REGS;
3846 mono_ptr_array_init (tmp_array, 4);
3848 if (!System_Reflection_EventInfo)
3849 System_Reflection_EventInfo = mono_class_from_name (
3850 mono_defaults.corlib, "System.Reflection", "EventInfo");
3852 domain = mono_object_domain (type);
3853 if (type->type->byref)
3854 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3855 klass = startklass = mono_class_from_mono_type (type->type);
3858 if (klass->exception_type != MONO_EXCEPTION_NONE)
3859 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3862 while ((event = mono_class_get_events (klass, &iter))) {
3864 method = event->add;
3866 method = event->remove;
3868 method = event->raise;
3870 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3871 if (bflags & BFLAGS_Public)
3873 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3874 if (bflags & BFLAGS_NonPublic)
3879 if (bflags & BFLAGS_NonPublic)
3885 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3886 if (bflags & BFLAGS_Static)
3887 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3890 if (bflags & BFLAGS_Instance)
3895 if (bflags & BFLAGS_Instance)
3899 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3901 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3904 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3906 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3907 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3909 mono_ptr_array_destroy (tmp_array);
3914 static MonoReflectionType *
3915 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3923 MONO_ARCH_SAVE_REGS;
3926 mono_raise_exception (mono_get_exception_argument_null ("name"));
3928 domain = ((MonoObject *)type)->vtable->domain;
3929 if (type->type->byref)
3931 klass = mono_class_from_mono_type (type->type);
3932 str = mono_string_to_utf8 (name);
3935 if (klass->exception_type != MONO_EXCEPTION_NONE)
3936 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3939 * If a nested type is generic, return its generic type definition.
3940 * Note that this means that the return value is essentially a
3941 * nested type of the generic type definition of @klass.
3943 * A note in MSDN claims that a generic type definition can have
3944 * nested types that aren't generic. In any case, the container of that
3945 * nested type would be the generic type definition.
3947 if (klass->generic_class)
3948 klass = klass->generic_class->container_class;
3951 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3953 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3954 if (bflags & BFLAGS_Public)
3957 if (bflags & BFLAGS_NonPublic)
3962 if (strcmp (nested->name, str) == 0){
3964 return mono_type_get_object (domain, &nested->byval_arg);
3967 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3974 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3983 MonoPtrArray tmp_array;
3985 MONO_ARCH_SAVE_REGS;
3987 domain = ((MonoObject *)type)->vtable->domain;
3988 if (type->type->byref)
3989 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3990 klass = mono_class_from_mono_type (type->type);
3991 if (klass->exception_type != MONO_EXCEPTION_NONE)
3992 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3995 * If a nested type is generic, return its generic type definition.
3996 * Note that this means that the return value is essentially the set
3997 * of nested types of the generic type definition of @klass.
3999 * A note in MSDN claims that a generic type definition can have
4000 * nested types that aren't generic. In any case, the container of that
4001 * nested type would be the generic type definition.
4003 if (klass->generic_class)
4004 klass = klass->generic_class->container_class;
4006 mono_ptr_array_init (tmp_array, 1);
4008 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4010 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4011 if (bflags & BFLAGS_Public)
4014 if (bflags & BFLAGS_NonPublic)
4019 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4020 mono_ptr_array_append (tmp_array, member);
4023 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4025 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4026 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4028 mono_ptr_array_destroy (tmp_array);
4033 static MonoReflectionType*
4034 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4037 MonoType *type = NULL;
4038 MonoTypeNameParse info;
4039 gboolean type_resolve;
4041 MONO_ARCH_SAVE_REGS;
4043 /* On MS.NET, this does not fire a TypeResolve event */
4044 type_resolve = TRUE;
4045 str = mono_string_to_utf8 (name);
4046 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4047 if (!mono_reflection_parse_type (str, &info)) {
4049 mono_reflection_free_type_info (&info);
4050 if (throwOnError) /* uhm: this is a parse error, though... */
4051 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4052 /*g_print ("failed parse\n");*/
4056 if (info.assembly.name) {
4058 mono_reflection_free_type_info (&info);
4060 /* 1.0 and 2.0 throw different exceptions */
4061 if (mono_defaults.generic_ilist_class)
4062 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4064 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4069 if (module != NULL) {
4071 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4076 if (assembly->assembly->dynamic) {
4077 /* Enumerate all modules */
4078 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4082 if (abuilder->modules) {
4083 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4084 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4085 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4091 if (!type && abuilder->loaded_modules) {
4092 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4093 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4094 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4101 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4103 mono_reflection_free_type_info (&info);
4105 MonoException *e = NULL;
4108 e = mono_get_exception_type_load (name, NULL);
4110 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4111 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4113 mono_loader_clear_error ();
4116 mono_raise_exception (e);
4121 if (type->type == MONO_TYPE_CLASS) {
4122 MonoClass *klass = mono_type_get_class (type);
4124 if (mono_is_security_manager_active () && !klass->exception_type)
4125 /* Some security problems are detected during generic vtable construction */
4126 mono_class_setup_vtable (klass);
4127 /* need to report exceptions ? */
4128 if (throwOnError && klass->exception_type) {
4129 /* report SecurityException (or others) that occured when loading the assembly */
4130 MonoException *exc = mono_class_get_exception_for_failure (klass);
4131 mono_loader_clear_error ();
4132 mono_raise_exception (exc);
4133 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4138 /* g_print ("got it\n"); */
4139 return mono_type_get_object (mono_object_domain (assembly), type);
4143 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4146 gchar *shadow_ini_file;
4149 /* Check for shadow-copied assembly */
4150 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4151 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4153 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4154 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4160 g_free (shadow_ini_file);
4161 if (content != NULL) {
4164 *filename = content;
4172 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4174 MonoDomain *domain = mono_object_domain (assembly);
4175 MonoAssembly *mass = assembly->assembly;
4176 MonoString *res = NULL;
4181 MONO_ARCH_SAVE_REGS;
4183 if (g_path_is_absolute (mass->image->name)) {
4184 absolute = g_strdup (mass->image->name);
4185 dirname = g_path_get_dirname (absolute);
4187 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4188 dirname = g_strdup (mass->basedir);
4191 replace_shadow_path (domain, dirname, &absolute);
4196 for (i = strlen (absolute) - 1; i >= 0; i--)
4197 if (absolute [i] == '\\')
4202 uri = g_filename_to_uri (absolute, NULL, NULL);
4204 const char *prepend = "file://";
4206 if (*absolute == '/' && *(absolute + 1) == '/') {
4209 prepend = "file:///";
4212 uri = g_strconcat (prepend, absolute, NULL);
4216 res = mono_string_new (domain, uri);
4224 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4226 MonoAssembly *mass = assembly->assembly;
4228 MONO_ARCH_SAVE_REGS;
4230 return mass->in_gac;
4233 static MonoReflectionAssembly*
4234 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4238 MonoImageOpenStatus status;
4240 MONO_ARCH_SAVE_REGS;
4242 name = mono_string_to_utf8 (mname);
4243 res = mono_assembly_load_with_partial_name (name, &status);
4249 return mono_assembly_get_object (mono_domain_get (), res);
4253 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4255 MonoDomain *domain = mono_object_domain (assembly);
4258 MONO_ARCH_SAVE_REGS;
4260 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4266 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4268 MONO_ARCH_SAVE_REGS;
4270 return assembly->assembly->ref_only;
4274 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4276 MonoDomain *domain = mono_object_domain (assembly);
4278 MONO_ARCH_SAVE_REGS;
4280 return mono_string_new (domain, assembly->assembly->image->version);
4283 static MonoReflectionMethod*
4284 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4286 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4288 MONO_ARCH_SAVE_REGS;
4292 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4295 static MonoReflectionModule*
4296 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4298 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4302 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4304 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4305 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4309 MONO_ARCH_SAVE_REGS;
4311 for (i = 0; i < table->rows; ++i) {
4312 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4313 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4319 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4321 static MonoClass *System_Version = NULL;
4322 static MonoMethod *create_version = NULL;
4326 if (!System_Version) {
4327 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4328 g_assert (System_Version);
4331 if (!create_version) {
4332 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4333 create_version = mono_method_desc_search_in_class (desc, System_Version);
4334 g_assert (create_version);
4335 mono_method_desc_free (desc);
4341 args [3] = &revision;
4342 result = mono_object_new (domain, System_Version);
4343 mono_runtime_invoke (create_version, result, args, NULL);
4349 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4351 static MonoClass *System_Reflection_AssemblyName;
4353 MonoDomain *domain = mono_object_domain (assembly);
4355 static MonoMethod *create_culture = NULL;
4356 MonoImage *image = assembly->assembly->image;
4359 MONO_ARCH_SAVE_REGS;
4361 if (!System_Reflection_AssemblyName)
4362 System_Reflection_AssemblyName = mono_class_from_name (
4363 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4365 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4368 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4370 if (count > 0 && !create_culture) {
4371 MonoMethodDesc *desc = mono_method_desc_new (
4372 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4373 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4374 g_assert (create_culture);
4375 mono_method_desc_free (desc);
4378 for (i = 0; i < count; i++) {
4379 MonoReflectionAssemblyName *aname;
4380 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4382 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4384 aname = (MonoReflectionAssemblyName *) mono_object_new (
4385 domain, System_Reflection_AssemblyName);
4387 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4389 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4390 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4391 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4392 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4393 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4394 aname->versioncompat = 1; /* SameMachine (default) */
4395 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4396 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4398 if (create_culture) {
4400 MonoBoolean assembly_ref = 1;
4401 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4402 args [1] = &assembly_ref;
4403 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4406 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4407 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4408 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4410 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4411 /* public key token isn't copied - the class library will
4412 automatically generate it from the public key if required */
4413 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4414 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4416 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4417 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4420 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4423 /* note: this function doesn't return the codebase on purpose (i.e. it can
4424 be used under partial trust as path information isn't present). */
4426 mono_array_setref (result, i, aname);
4437 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4439 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4441 mono_array_setref (info->res, info->idx, name);
4446 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4448 MonoImage *img = assembly->assembly->image;
4453 MONO_ARCH_SAVE_REGS;
4455 mono_image_lock (img);
4456 mono_image_init_name_cache (img);
4459 len = g_hash_table_size (img->name_cache);
4460 mono_image_unlock (img);
4462 /*we can't create objects holding the image lock */
4463 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4465 mono_image_lock (img);
4466 /*len might have changed, create a new array*/
4467 if (len != g_hash_table_size (img->name_cache))
4472 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4473 mono_image_unlock (img);
4478 /* move this in some file in mono/util/ */
4480 g_concat_dir_and_file (const char *dir, const char *file)
4482 g_return_val_if_fail (dir != NULL, NULL);
4483 g_return_val_if_fail (file != NULL, NULL);
4486 * If the directory name doesn't have a / on the end, we need
4487 * to add one so we get a proper path to the file
4489 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4490 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4492 return g_strconcat (dir, file, NULL);
4496 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4498 char *n = mono_string_to_utf8 (name);
4499 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4501 guint32 cols [MONO_MANIFEST_SIZE];
4502 guint32 impl, file_idx;
4506 MONO_ARCH_SAVE_REGS;
4508 for (i = 0; i < table->rows; ++i) {
4509 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4510 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4511 if (strcmp (val, n) == 0)
4515 if (i == table->rows)
4518 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4521 * this code should only be called after obtaining the
4522 * ResourceInfo and handling the other cases.
4524 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4525 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4527 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4532 module = assembly->assembly->image;
4534 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4536 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4540 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4542 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4544 guint32 cols [MONO_MANIFEST_SIZE];
4545 guint32 file_cols [MONO_FILE_SIZE];
4549 MONO_ARCH_SAVE_REGS;
4551 n = mono_string_to_utf8 (name);
4552 for (i = 0; i < table->rows; ++i) {
4553 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4554 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4555 if (strcmp (val, n) == 0)
4559 if (i == table->rows)
4562 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4563 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4566 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4567 case MONO_IMPLEMENTATION_FILE:
4568 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4569 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4570 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4571 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4572 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4573 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4576 info->location = RESOURCE_LOCATION_EMBEDDED;
4579 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4580 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4581 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4582 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4583 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4584 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4586 mono_raise_exception (ex);
4588 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4590 /* Obtain info recursively */
4591 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4592 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4595 case MONO_IMPLEMENTATION_EXP_TYPE:
4596 g_assert_not_reached ();
4605 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4607 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4608 MonoArray *result = NULL;
4613 MONO_ARCH_SAVE_REGS;
4615 /* check hash if needed */
4617 n = mono_string_to_utf8 (name);
4618 for (i = 0; i < table->rows; ++i) {
4619 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4620 if (strcmp (val, n) == 0) {
4623 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4624 fn = mono_string_new (mono_object_domain (assembly), n);
4626 return (MonoObject*)fn;
4634 for (i = 0; i < table->rows; ++i) {
4635 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4639 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4642 for (i = 0; i < table->rows; ++i) {
4643 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4644 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4645 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4646 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4651 return (MonoObject*)result;
4655 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4657 MonoDomain *domain = mono_domain_get();
4660 int i, j, file_count = 0;
4661 MonoImage **modules;
4662 guint32 module_count, real_module_count;
4663 MonoTableInfo *table;
4664 guint32 cols [MONO_FILE_SIZE];
4665 MonoImage *image = assembly->assembly->image;
4667 g_assert (image != NULL);
4668 g_assert (!assembly->assembly->dynamic);
4670 table = &image->tables [MONO_TABLE_FILE];
4671 file_count = table->rows;
4673 modules = image->modules;
4674 module_count = image->module_count;
4676 real_module_count = 0;
4677 for (i = 0; i < module_count; ++i)
4679 real_module_count ++;
4681 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4682 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4684 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4686 for (i = 0; i < module_count; ++i)
4688 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4692 for (i = 0; i < file_count; ++i, ++j) {
4693 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4694 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4695 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4697 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4699 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4700 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4702 mono_array_setref (res, j, mono_module_get_object (domain, m));
4709 static MonoReflectionMethod*
4710 ves_icall_GetCurrentMethod (void)
4712 MonoMethod *m = mono_method_get_last_managed ();
4714 MONO_ARCH_SAVE_REGS;
4716 return mono_method_get_object (mono_domain_get (), m, NULL);
4721 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4724 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4725 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4726 //method is inflated, we should inflate it on the other class
4727 MonoGenericContext ctx;
4728 ctx.method_inst = inflated->context.method_inst;
4729 ctx.class_inst = inflated->context.class_inst;
4730 if (klass->generic_class)
4731 ctx.class_inst = klass->generic_class->context.class_inst;
4732 else if (klass->generic_container)
4733 ctx.class_inst = klass->generic_container->context.class_inst;
4734 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4737 mono_class_setup_methods (method->klass);
4738 for (i = 0; i < method->klass->method.count; ++i) {
4739 if (method->klass->methods [i] == method) {
4744 mono_class_setup_methods (klass);
4745 g_assert (offset >= 0 && offset < klass->method.count);
4746 return klass->methods [offset];
4749 static MonoReflectionMethod*
4750 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4754 klass = mono_class_from_mono_type (type);
4755 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4757 if (method->klass != klass)
4758 method = mono_method_get_equivalent_method (method, klass);
4760 klass = method->klass;
4761 return mono_method_get_object (mono_domain_get (), method, klass);
4764 static MonoReflectionMethod*
4765 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4767 return mono_method_get_object (mono_domain_get (), method, NULL);
4770 static MonoReflectionMethodBody*
4771 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4773 return mono_method_body_get_object (mono_domain_get (), method);
4776 static MonoReflectionAssembly*
4777 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4779 MonoMethod *dest = NULL;
4781 MONO_ARCH_SAVE_REGS;
4783 mono_stack_walk_no_il (get_executing, &dest);
4784 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4788 static MonoReflectionAssembly*
4789 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4791 MonoDomain* domain = mono_domain_get ();
4793 MONO_ARCH_SAVE_REGS;
4795 if (!domain->entry_assembly)
4798 return mono_assembly_get_object (domain, domain->entry_assembly);
4801 static MonoReflectionAssembly*
4802 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4807 MONO_ARCH_SAVE_REGS;
4810 mono_stack_walk_no_il (get_executing, &dest);
4812 mono_stack_walk_no_il (get_caller, &dest);
4815 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4819 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4820 gboolean assembly_qualified)
4822 MonoDomain *domain = mono_object_domain (object);
4823 MonoTypeNameFormat format;
4827 MONO_ARCH_SAVE_REGS;
4829 format = assembly_qualified ?
4830 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4831 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4833 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4835 name = mono_type_get_name_full (object->type, format);
4839 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4844 res = mono_string_new (domain, name);
4851 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4853 static MonoMethod *create_culture = NULL;
4856 const char *pkey_ptr;
4858 MonoBoolean assembly_ref = 0;
4860 MONO_ARCH_SAVE_REGS;
4862 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4863 aname->major = name->major;
4864 aname->minor = name->minor;
4865 aname->build = name->build;
4866 aname->flags = name->flags;
4867 aname->revision = name->revision;
4868 aname->hashalg = name->hash_alg;
4869 aname->versioncompat = 1; /* SameMachine (default) */
4871 if (by_default_version)
4872 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4875 if (absolute != NULL && *absolute != '\0') {
4876 const gchar *prepend = "file://";
4879 codebase = g_strdup (absolute);
4884 for (i = strlen (codebase) - 1; i >= 0; i--)
4885 if (codebase [i] == '\\')
4888 if (*codebase == '/' && *(codebase + 1) == '/') {
4891 prepend = "file:///";
4895 result = g_strconcat (prepend, codebase, NULL);
4901 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4905 if (!create_culture) {
4906 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4907 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4908 g_assert (create_culture);
4909 mono_method_desc_free (desc);
4912 if (name->culture) {
4913 args [0] = mono_string_new (domain, name->culture);
4914 args [1] = &assembly_ref;
4915 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4918 if (name->public_key) {
4919 pkey_ptr = (char*)name->public_key;
4920 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4922 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4923 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4924 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4925 } else if (default_publickey) {
4926 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4927 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4930 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4931 if (name->public_key_token [0]) {
4935 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4936 p = mono_array_addr (aname->keyToken, char, 0);
4938 for (i = 0, j = 0; i < 8; i++) {
4939 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4940 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4943 } else if (default_token) {
4944 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4949 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4951 MonoDomain *domain = mono_object_domain (assembly);
4952 MonoAssembly *mass = assembly->assembly;
4956 name = g_strdup_printf (
4957 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4959 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4960 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4961 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4962 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4964 res = mono_string_new (domain, name);
4971 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4974 MonoAssembly *mass = assembly->assembly;
4976 MONO_ARCH_SAVE_REGS;
4978 if (g_path_is_absolute (mass->image->name)) {
4979 fill_reflection_assembly_name (mono_object_domain (assembly),
4980 aname, &mass->aname, mass->image->name, TRUE,
4981 TRUE, mono_framework_version () >= 2);
4984 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4986 fill_reflection_assembly_name (mono_object_domain (assembly),
4987 aname, &mass->aname, absolute, TRUE, TRUE,
4988 mono_framework_version () >= 2);
4994 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4997 MonoImageOpenStatus status = MONO_IMAGE_OK;
5000 MonoAssemblyName name;
5003 MONO_ARCH_SAVE_REGS;
5005 filename = mono_string_to_utf8 (fname);
5007 dirname = g_path_get_dirname (filename);
5008 replace_shadow_path (mono_domain_get (), dirname, &filename);
5011 image = mono_image_open (filename, &status);
5017 if (status == MONO_IMAGE_IMAGE_INVALID)
5018 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5020 exc = mono_get_exception_file_not_found2 (NULL, fname);
5021 mono_raise_exception (exc);
5024 res = mono_assembly_fill_assembly_name (image, &name);
5026 mono_image_close (image);
5028 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5031 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5032 TRUE, mono_framework_version () == 1,
5033 mono_framework_version () >= 2);
5036 mono_image_close (image);
5040 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5041 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5043 MonoBoolean result = FALSE;
5044 MonoDeclSecurityEntry entry;
5046 /* SecurityAction.RequestMinimum */
5047 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5048 *minimum = entry.blob;
5049 *minLength = entry.size;
5052 /* SecurityAction.RequestOptional */
5053 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5054 *optional = entry.blob;
5055 *optLength = entry.size;
5058 /* SecurityAction.RequestRefuse */
5059 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5060 *refused = entry.blob;
5061 *refLength = entry.size;
5069 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5073 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5075 guint32 attrs, visibility;
5077 /* we start the count from 1 because we skip the special type <Module> */
5080 for (i = 1; i < tdef->rows; ++i) {
5081 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5082 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5083 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5087 count = tdef->rows - 1;
5089 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5090 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5092 for (i = 1; i < tdef->rows; ++i) {
5093 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5094 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5095 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5096 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5098 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5100 MonoLoaderError *error;
5103 error = mono_loader_get_last_error ();
5104 g_assert (error != NULL);
5106 ex = mono_loader_error_prepare_exception (error);
5107 mono_array_setref (*exceptions, count, ex);
5109 if (mono_loader_get_last_error ())
5110 mono_loader_clear_error ();
5119 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5121 MonoArray *res = NULL;
5122 MonoArray *exceptions = NULL;
5123 MonoImage *image = NULL;
5124 MonoTableInfo *table = NULL;
5127 int i, len, ex_count;
5129 MONO_ARCH_SAVE_REGS;
5131 domain = mono_object_domain (assembly);
5133 g_assert (!assembly->assembly->dynamic);
5134 image = assembly->assembly->image;
5135 table = &image->tables [MONO_TABLE_FILE];
5136 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5138 /* Append data from all modules in the assembly */
5139 for (i = 0; i < table->rows; ++i) {
5140 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5141 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5144 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5145 /* Append the new types to the end of the array */
5146 if (mono_array_length (res2) > 0) {
5148 MonoArray *res3, *ex3;
5150 len1 = mono_array_length (res);
5151 len2 = mono_array_length (res2);
5153 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5154 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5155 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5158 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5159 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5160 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5167 /* the ReflectionTypeLoadException must have all the types (Types property),
5168 * NULL replacing types which throws an exception. The LoaderException must
5169 * contain all exceptions for NULL items.
5172 len = mono_array_length (res);
5175 for (i = 0; i < len; i++) {
5176 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5180 klass = mono_type_get_class (t->type);
5181 if ((klass != NULL) && klass->exception_type) {
5182 /* keep the class in the list */
5183 list = g_list_append (list, klass);
5184 /* and replace Type with NULL */
5185 mono_array_setref (res, i, NULL);
5192 if (list || ex_count) {
5194 MonoException *exc = NULL;
5195 MonoArray *exl = NULL;
5196 int j, length = g_list_length (list) + ex_count;
5198 mono_loader_clear_error ();
5200 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5201 /* Types for which mono_class_get () succeeded */
5202 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5203 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5204 mono_array_setref (exl, i, exc);
5206 /* Types for which it don't */
5207 for (j = 0; j < mono_array_length (exceptions); ++j) {
5208 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5210 g_assert (i < length);
5211 mono_array_setref (exl, i, exc);
5218 exc = mono_get_exception_reflection_type_load (res, exl);
5219 mono_loader_clear_error ();
5220 mono_raise_exception (exc);
5227 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5229 MonoAssemblyName aname;
5230 MonoDomain *domain = mono_object_domain (name);
5232 gboolean is_version_defined;
5233 gboolean is_token_defined;
5235 aname.public_key = NULL;
5236 val = mono_string_to_utf8 (assname);
5237 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5238 g_free ((guint8*) aname.public_key);
5243 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5244 FALSE, is_token_defined);
5246 mono_assembly_name_free (&aname);
5247 g_free ((guint8*) aname.public_key);
5253 static MonoReflectionType*
5254 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5256 MonoDomain *domain = mono_object_domain (module);
5259 MONO_ARCH_SAVE_REGS;
5261 g_assert (module->image);
5263 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5264 /* These images do not have a global type */
5267 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5268 return mono_type_get_object (domain, &klass->byval_arg);
5272 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5274 /*if (module->image)
5275 mono_image_close (module->image);*/
5279 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5281 MonoDomain *domain = mono_object_domain (module);
5283 MONO_ARCH_SAVE_REGS;
5285 g_assert (module->image);
5286 return mono_string_new (domain, module->image->guid);
5290 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5292 #ifdef PLATFORM_WIN32
5293 if (module->image && module->image->is_module_handle)
5294 return module->image->raw_data;
5297 return (gpointer) (-1);
5301 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5303 if (image->dynamic) {
5304 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5305 *pe_kind = dyn->pe_kind;
5306 *machine = dyn->machine;
5309 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5310 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5315 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5317 return (image->md_version_major << 16) | (image->md_version_minor);
5321 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5323 MonoArray *exceptions;
5326 MONO_ARCH_SAVE_REGS;
5329 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5331 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5332 for (i = 0; i < mono_array_length (exceptions); ++i) {
5333 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5335 mono_raise_exception (ex);
5342 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5344 guint32 cols [MONO_MEMBERREF_SIZE];
5346 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5347 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5348 mono_metadata_decode_blob_size (sig, &sig);
5349 return (*sig != 0x6);
5353 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5356 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5357 mono_array_addr (type_args, MonoType*, 0));
5359 context->class_inst = NULL;
5361 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5362 mono_array_addr (method_args, MonoType*, 0));
5364 context->method_inst = NULL;
5368 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5371 int table = mono_metadata_token_table (token);
5372 int index = mono_metadata_token_index (token);
5373 MonoGenericContext context;
5375 *error = ResolveTokenError_Other;
5377 /* Validate token */
5378 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5379 (table != MONO_TABLE_TYPESPEC)) {
5380 *error = ResolveTokenError_BadTable;
5384 if (image->dynamic) {
5385 if (type_args || method_args)
5386 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5387 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5390 return &klass->byval_arg;
5393 if ((index <= 0) || (index > image->tables [table].rows)) {
5394 *error = ResolveTokenError_OutOfRange;
5398 init_generic_context_from_args (&context, type_args, method_args);
5399 klass = mono_class_get_full (image, token, &context);
5401 if (mono_loader_get_last_error ())
5402 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5405 return &klass->byval_arg;
5411 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5413 int table = mono_metadata_token_table (token);
5414 int index = mono_metadata_token_index (token);
5415 MonoGenericContext context;
5418 *error = ResolveTokenError_Other;
5420 /* Validate token */
5421 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5422 (table != MONO_TABLE_MEMBERREF)) {
5423 *error = ResolveTokenError_BadTable;
5427 if (image->dynamic) {
5428 if (type_args || method_args)
5429 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5430 /* FIXME: validate memberref token type */
5431 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5434 if ((index <= 0) || (index > image->tables [table].rows)) {
5435 *error = ResolveTokenError_OutOfRange;
5438 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5439 *error = ResolveTokenError_BadTable;
5443 init_generic_context_from_args (&context, type_args, method_args);
5444 method = mono_get_method_full (image, token, NULL, &context);
5446 if (mono_loader_get_last_error ())
5447 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5453 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5455 int index = mono_metadata_token_index (token);
5457 *error = ResolveTokenError_Other;
5459 /* Validate token */
5460 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5461 *error = ResolveTokenError_BadTable;
5466 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5468 if ((index <= 0) || (index >= image->heap_us.size)) {
5469 *error = ResolveTokenError_OutOfRange;
5473 /* FIXME: What to do if the index points into the middle of a string ? */
5475 return mono_ldstr (mono_domain_get (), image, index);
5478 static MonoClassField*
5479 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5482 int table = mono_metadata_token_table (token);
5483 int index = mono_metadata_token_index (token);
5484 MonoGenericContext context;
5485 MonoClassField *field;
5487 *error = ResolveTokenError_Other;
5489 /* Validate token */
5490 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5491 *error = ResolveTokenError_BadTable;
5495 if (image->dynamic) {
5496 if (type_args || method_args)
5497 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5498 /* FIXME: validate memberref token type */
5499 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5502 if ((index <= 0) || (index > image->tables [table].rows)) {
5503 *error = ResolveTokenError_OutOfRange;
5506 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5507 *error = ResolveTokenError_BadTable;
5511 init_generic_context_from_args (&context, type_args, method_args);
5512 field = mono_field_from_token (image, token, &klass, &context);
5514 if (mono_loader_get_last_error ())
5515 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5522 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5524 int table = mono_metadata_token_table (token);
5526 *error = ResolveTokenError_Other;
5529 case MONO_TABLE_TYPEDEF:
5530 case MONO_TABLE_TYPEREF:
5531 case MONO_TABLE_TYPESPEC: {
5532 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5534 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5538 case MONO_TABLE_METHOD:
5539 case MONO_TABLE_METHODSPEC: {
5540 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5542 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5546 case MONO_TABLE_FIELD: {
5547 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5549 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5553 case MONO_TABLE_MEMBERREF:
5554 if (mono_metadata_memberref_is_method (image, token)) {
5555 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5557 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5562 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5564 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5571 *error = ResolveTokenError_BadTable;
5578 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5580 int table = mono_metadata_token_table (token);
5581 int idx = mono_metadata_token_index (token);
5582 MonoTableInfo *tables = image->tables;
5587 *error = ResolveTokenError_OutOfRange;
5589 /* FIXME: Support other tables ? */
5590 if (table != MONO_TABLE_STANDALONESIG)
5596 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5599 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5601 ptr = mono_metadata_blob_heap (image, sig);
5602 len = mono_metadata_decode_blob_size (ptr, &ptr);
5604 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5605 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5609 static MonoReflectionType*
5610 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5613 int isbyref = 0, rank;
5614 char *str = mono_string_to_utf8 (smodifiers);
5617 MONO_ARCH_SAVE_REGS;
5619 klass = mono_class_from_mono_type (tb->type.type);
5621 /* logic taken from mono_reflection_parse_type(): keep in sync */
5625 if (isbyref) { /* only one level allowed by the spec */
5632 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5635 klass = mono_ptr_class_get (&klass->byval_arg);
5636 mono_class_init (klass);
5647 else if (*p != '*') { /* '*' means unknown lower bound */
5658 klass = mono_array_class_get (klass, rank);
5659 mono_class_init (klass);
5666 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5670 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5675 MONO_ARCH_SAVE_REGS;
5678 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5683 static MonoReflectionType *
5684 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5686 MonoClass *klass, *aklass;
5688 MONO_ARCH_SAVE_REGS;
5690 klass = mono_class_from_mono_type (type->type);
5691 if (rank == 0) //single dimentional array
5692 aklass = mono_array_class_get (klass, 1);
5694 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5696 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5699 static MonoReflectionType *
5700 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5704 MONO_ARCH_SAVE_REGS;
5706 klass = mono_class_from_mono_type (type->type);
5708 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5711 static MonoReflectionType *
5712 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5716 MONO_ARCH_SAVE_REGS;
5718 pklass = mono_ptr_class_get (type->type);
5720 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5724 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5725 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5727 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5728 MonoObject *delegate;
5730 MonoMethod *method = info->method;
5732 MONO_ARCH_SAVE_REGS;
5734 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5736 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5737 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5741 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5743 if (method->dynamic) {
5744 /* Creating a trampoline would leak memory */
5745 func = mono_compile_method (method);
5747 func = mono_create_ftnptr (mono_domain_get (),
5748 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5751 mono_delegate_ctor_with_method (delegate, target, func, method);
5757 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5759 /* Reset the invoke impl to the default one */
5760 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5764 * Magic number to convert a time which is relative to
5765 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5767 #define EPOCH_ADJUST ((guint64)62135596800LL)
5770 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5772 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5774 #ifdef PLATFORM_WIN32
5775 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5777 convert_to_absolute_date(SYSTEMTIME *date)
5779 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5780 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5781 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5782 /* from the calendar FAQ */
5783 int a = (14 - date->wMonth) / 12;
5784 int y = date->wYear - a;
5785 int m = date->wMonth + 12 * a - 2;
5786 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5788 /* d is now the day of the week for the first of the month (0 == Sunday) */
5790 int day_of_week = date->wDayOfWeek;
5792 /* set day_in_month to the first day in the month which falls on day_of_week */
5793 int day_in_month = 1 + (day_of_week - d);
5794 if (day_in_month <= 0)
5797 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5798 date->wDay = day_in_month + (date->wDay - 1) * 7;
5799 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5804 #ifndef PLATFORM_WIN32
5806 * Return's the offset from GMT of a local time.
5808 * tm is a local time
5809 * t is the same local time as seconds.
5812 gmt_offset(struct tm *tm, time_t t)
5814 #if defined (HAVE_TM_GMTOFF)
5815 return tm->tm_gmtoff;
5820 g.tm_isdst = tm->tm_isdst;
5822 return (int)difftime(t, t2);
5827 * This is heavily based on zdump.c from glibc 2.2.
5829 * * data[0]: start of daylight saving time (in DateTime ticks).
5830 * * data[1]: end of daylight saving time (in DateTime ticks).
5831 * * data[2]: utcoffset (in TimeSpan ticks).
5832 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5833 * * name[0]: name of this timezone when not daylight saving.
5834 * * name[1]: name of this timezone when daylight saving.
5836 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5837 * the class library allows years between 1 and 9999.
5839 * Returns true on success and zero on failure.
5842 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5844 #ifndef PLATFORM_WIN32
5845 MonoDomain *domain = mono_domain_get ();
5846 struct tm start, tt;
5850 int is_daylight = 0, day;
5853 MONO_ARCH_SAVE_REGS;
5855 MONO_CHECK_ARG_NULL (data);
5856 MONO_CHECK_ARG_NULL (names);
5858 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5859 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5862 * no info is better than crashing: we'll need our own tz data
5863 * to make this work properly, anyway. The range is probably
5864 * reduced to 1970 .. 2037 because that is what mktime is
5865 * guaranteed to support (we get into an infinite loop
5869 memset (&start, 0, sizeof (start));
5872 start.tm_year = year-1900;
5874 t = mktime (&start);
5876 if ((year < 1970) || (year > 2037) || (t == -1)) {
5878 tt = *localtime (&t);
5879 strftime (tzone, sizeof (tzone), "%Z", &tt);
5880 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5881 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5885 gmtoff = gmt_offset (&start, t);
5887 /* For each day of the year, calculate the tm_gmtoff. */
5888 for (day = 0; day < 365; day++) {
5891 tt = *localtime (&t);
5893 /* Daylight saving starts or ends here. */
5894 if (gmt_offset (&tt, t) != gmtoff) {
5898 /* Try to find the exact hour when daylight saving starts/ends. */
5902 tt1 = *localtime (&t1);
5903 } while (gmt_offset (&tt1, t1) != gmtoff);
5905 /* Try to find the exact minute when daylight saving starts/ends. */
5908 tt1 = *localtime (&t1);
5909 } while (gmt_offset (&tt1, t1) == gmtoff);
5911 strftime (tzone, sizeof (tzone), "%Z", &tt);
5913 /* Write data, if we're already in daylight saving, we're done. */
5915 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5916 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5919 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5920 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5924 /* This is only set once when we enter daylight saving. */
5925 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5926 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5928 gmtoff = gmt_offset (&tt, t);
5933 strftime (tzone, sizeof (tzone), "%Z", &tt);
5934 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5935 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5936 mono_array_set ((*data), gint64, 0, 0);
5937 mono_array_set ((*data), gint64, 1, 0);
5938 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5939 mono_array_set ((*data), gint64, 3, 0);
5944 MonoDomain *domain = mono_domain_get ();
5945 TIME_ZONE_INFORMATION tz_info;
5950 tz_id = GetTimeZoneInformation (&tz_info);
5951 if (tz_id == TIME_ZONE_ID_INVALID)
5954 MONO_CHECK_ARG_NULL (data);
5955 MONO_CHECK_ARG_NULL (names);
5957 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
5958 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
5960 for (i = 0; i < 32; ++i)
5961 if (!tz_info.DaylightName [i])
5963 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5964 for (i = 0; i < 32; ++i)
5965 if (!tz_info.StandardName [i])
5967 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5969 if ((year <= 1601) || (year > 30827)) {
5971 * According to MSDN, the MS time functions can't handle dates outside
5977 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5978 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5979 tz_info.StandardDate.wYear = year;
5980 convert_to_absolute_date(&tz_info.StandardDate);
5981 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5986 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5987 tz_info.DaylightDate.wYear = year;
5988 convert_to_absolute_date(&tz_info.DaylightDate);
5989 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5994 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5996 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
5997 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6004 ves_icall_System_Object_obj_address (MonoObject *this)
6006 MONO_ARCH_SAVE_REGS;
6013 static inline gint32
6014 mono_array_get_byte_length (MonoArray *array)
6020 klass = array->obj.vtable->klass;
6022 if (array->bounds == NULL)
6023 length = array->max_length;
6026 for (i = 0; i < klass->rank; ++ i)
6027 length *= array->bounds [i].length;
6030 switch (klass->element_class->byval_arg.type) {
6033 case MONO_TYPE_BOOLEAN:
6037 case MONO_TYPE_CHAR:
6045 return length * sizeof (gpointer);
6056 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6058 MONO_ARCH_SAVE_REGS;
6060 return mono_array_get_byte_length (array);
6064 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6066 MONO_ARCH_SAVE_REGS;
6068 return mono_array_get (array, gint8, idx);
6072 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6074 MONO_ARCH_SAVE_REGS;
6076 mono_array_set (array, gint8, idx, value);
6080 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6082 guint8 *src_buf, *dest_buf;
6084 MONO_ARCH_SAVE_REGS;
6086 /* watch out for integer overflow */
6087 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6090 src_buf = (guint8 *)src->vector + src_offset;
6091 dest_buf = (guint8 *)dest->vector + dest_offset;
6094 memcpy (dest_buf, src_buf, count);
6096 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6102 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6104 MonoDomain *domain = mono_object_domain (this);
6106 MonoRealProxy *rp = ((MonoRealProxy *)this);
6107 MonoTransparentProxy *tp;
6111 MONO_ARCH_SAVE_REGS;
6113 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6114 tp = (MonoTransparentProxy*) res;
6116 MONO_OBJECT_SETREF (tp, rp, rp);
6117 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6118 klass = mono_class_from_mono_type (type);
6120 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6121 tp->remote_class = mono_remote_class (domain, class_name, klass);
6123 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6127 static MonoReflectionType *
6128 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6130 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6133 /* System.Environment */
6136 ves_icall_System_Environment_get_UserName (void)
6138 MONO_ARCH_SAVE_REGS;
6140 /* using glib is more portable */
6141 return mono_string_new (mono_domain_get (), g_get_user_name ());
6146 ves_icall_System_Environment_get_MachineName (void)
6148 #if defined (PLATFORM_WIN32)
6153 len = MAX_COMPUTERNAME_LENGTH + 1;
6154 buf = g_new (gunichar2, len);
6157 if (GetComputerName (buf, (PDWORD) &len))
6158 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6162 #elif !defined(DISABLE_SOCKETS)
6166 if (gethostname (buf, sizeof (buf)) == 0)
6167 result = mono_string_new (mono_domain_get (), buf);
6173 return mono_string_new (mono_domain_get (), "mono");
6178 ves_icall_System_Environment_get_Platform (void)
6180 #if defined (PLATFORM_WIN32)
6183 #elif defined(__MACH__)
6185 if (mono_framework_version () < 2)
6189 // For compatibility with our client code, this will be 4 for a while.
6190 // We will eventually move to 6 to match .NET, but it requires all client
6191 // code to be updated and the documentation everywhere to be updated
6197 if (mono_framework_version () < 2)
6204 ves_icall_System_Environment_get_NewLine (void)
6206 MONO_ARCH_SAVE_REGS;
6208 #if defined (PLATFORM_WIN32)
6209 return mono_string_new (mono_domain_get (), "\r\n");
6211 return mono_string_new (mono_domain_get (), "\n");
6216 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6221 MONO_ARCH_SAVE_REGS;
6226 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6227 value = g_getenv (utf8_name);
6234 return mono_string_new (mono_domain_get (), value);
6238 * There is no standard way to get at environ.
6241 #ifndef __MINGW32_VERSION
6243 /* Apple defines this in crt_externs.h but doesn't provide that header for
6244 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6245 * in fact exist on all implementations (so far)
6247 gchar ***_NSGetEnviron(void);
6248 #define environ (*_NSGetEnviron())
6257 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6259 #ifdef PLATFORM_WIN32
6268 env_strings = GetEnvironmentStrings();
6271 env_string = env_strings;
6272 while (*env_string != '\0') {
6273 /* weird case that MS seems to skip */
6274 if (*env_string != '=')
6276 while (*env_string != '\0')
6282 domain = mono_domain_get ();
6283 names = mono_array_new (domain, mono_defaults.string_class, n);
6287 env_string = env_strings;
6288 while (*env_string != '\0') {
6289 /* weird case that MS seems to skip */
6290 if (*env_string != '=') {
6291 equal_str = wcschr(env_string, '=');
6292 g_assert(equal_str);
6293 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6294 mono_array_setref (names, n, str);
6297 while (*env_string != '\0')
6302 FreeEnvironmentStrings (env_strings);
6314 MONO_ARCH_SAVE_REGS;
6317 for (e = environ; *e != 0; ++ e)
6320 domain = mono_domain_get ();
6321 names = mono_array_new (domain, mono_defaults.string_class, n);
6324 for (e = environ; *e != 0; ++ e) {
6325 parts = g_strsplit (*e, "=", 2);
6327 str = mono_string_new (domain, *parts);
6328 mono_array_setref (names, n, str);
6341 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6343 #if !GLIB_CHECK_VERSION(2,4,0)
6344 #define g_setenv(a,b,c) setenv(a,b,c)
6345 #define g_unsetenv(a) unsetenv(a)
6349 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6351 #ifdef PLATFORM_WIN32
6352 gunichar2 *utf16_name, *utf16_value;
6354 gchar *utf8_name, *utf8_value;
6357 MONO_ARCH_SAVE_REGS;
6359 #ifdef PLATFORM_WIN32
6360 utf16_name = mono_string_to_utf16 (name);
6361 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6362 SetEnvironmentVariable (utf16_name, NULL);
6363 g_free (utf16_name);
6367 utf16_value = mono_string_to_utf16 (value);
6369 SetEnvironmentVariable (utf16_name, utf16_value);
6371 g_free (utf16_name);
6372 g_free (utf16_value);
6374 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6376 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6377 g_unsetenv (utf8_name);
6382 utf8_value = mono_string_to_utf8 (value);
6383 g_setenv (utf8_name, utf8_value, TRUE);
6386 g_free (utf8_value);
6391 ves_icall_System_Environment_Exit (int result)
6393 MONO_ARCH_SAVE_REGS;
6395 mono_threads_set_shutting_down ();
6397 mono_runtime_set_shutting_down ();
6399 /* Suspend all managed threads since the runtime is going away */
6400 mono_thread_suspend_all_other_threads ();
6402 mono_runtime_quit ();
6404 /* we may need to do some cleanup here... */
6409 ves_icall_System_Environment_GetGacPath (void)
6411 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6415 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6417 #if defined (PLATFORM_WIN32)
6418 #ifndef CSIDL_FLAG_CREATE
6419 #define CSIDL_FLAG_CREATE 0x8000
6422 WCHAR path [MAX_PATH];
6423 /* Create directory if no existing */
6424 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6428 return mono_string_new_utf16 (mono_domain_get (), path, len);
6431 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6433 return mono_string_new (mono_domain_get (), "");
6437 ves_icall_System_Environment_GetLogicalDrives (void)
6439 gunichar2 buf [128], *ptr, *dname;
6441 guint initial_size = 127, size = 128;
6444 MonoString *drivestr;
6445 MonoDomain *domain = mono_domain_get ();
6448 MONO_ARCH_SAVE_REGS;
6453 while (size > initial_size) {
6454 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6455 if (size > initial_size) {
6458 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6459 initial_size = size;
6473 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6478 while (*u16) { u16++; len ++; }
6479 drivestr = mono_string_new_utf16 (domain, dname, len);
6480 mono_array_setref (result, ndrives++, drivestr);
6491 ves_icall_System_Environment_InternalGetHome (void)
6493 MONO_ARCH_SAVE_REGS;
6495 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6498 static const char *encodings [] = {
6500 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6501 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6502 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6504 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6505 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6506 "x_unicode_2_0_utf_7",
6508 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6509 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6511 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6514 "unicodefffe", "utf_16be",
6521 * Returns the internal codepage, if the value of "int_code_page" is
6522 * 1 at entry, and we can not compute a suitable code page number,
6523 * returns the code page as a string
6526 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6531 char *codepage = NULL;
6533 int want_name = *int_code_page;
6536 *int_code_page = -1;
6537 MONO_ARCH_SAVE_REGS;
6539 g_get_charset (&cset);
6540 c = codepage = strdup (cset);
6541 for (c = codepage; *c; c++){
6542 if (isascii (*c) && isalpha (*c))
6547 /* g_print ("charset: %s\n", cset); */
6549 /* handle some common aliases */
6552 for (i = 0; p != 0; ){
6553 if ((gssize) p < 7){
6555 p = encodings [++i];
6558 if (strcmp (p, codepage) == 0){
6559 *int_code_page = code;
6562 p = encodings [++i];
6565 if (strstr (codepage, "utf_8") != NULL)
6566 *int_code_page |= 0x10000000;
6569 if (want_name && *int_code_page == -1)
6570 return mono_string_new (mono_domain_get (), cset);
6576 ves_icall_System_Environment_get_HasShutdownStarted (void)
6578 if (mono_runtime_is_shutting_down ())
6581 if (mono_domain_is_unloading (mono_domain_get ()))
6588 ves_icall_System_Environment_BroadcastSettingChange (void)
6590 #ifdef PLATFORM_WIN32
6591 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6596 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6597 MonoReflectionMethod *method,
6598 MonoArray *out_args)
6600 MONO_ARCH_SAVE_REGS;
6602 mono_message_init (mono_object_domain (this), this, method, out_args);
6606 ves_icall_IsTransparentProxy (MonoObject *proxy)
6608 MONO_ARCH_SAVE_REGS;
6613 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6619 static MonoReflectionMethod *
6620 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6621 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6625 MonoMethod **vtable;
6626 MonoMethod *res = NULL;
6628 MONO_CHECK_ARG_NULL (rtype);
6629 MONO_CHECK_ARG_NULL (rmethod);
6631 method = rmethod->method;
6632 klass = mono_class_from_mono_type (rtype->type);
6634 if (MONO_CLASS_IS_INTERFACE (klass))
6637 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6640 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6641 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6647 mono_class_setup_vtable (klass);
6648 vtable = klass->vtable;
6650 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6651 int offs = mono_class_interface_offset (klass, method->klass);
6653 res = vtable [offs + method->slot];
6655 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6658 if (method->slot != -1)
6659 res = vtable [method->slot];
6665 return mono_method_get_object (mono_domain_get (), res, NULL);
6669 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6674 MONO_ARCH_SAVE_REGS;
6676 klass = mono_class_from_mono_type (type->type);
6677 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6679 if (enable) vtable->remote = 1;
6680 else vtable->remote = 0;
6684 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6689 MONO_ARCH_SAVE_REGS;
6691 domain = mono_object_domain (type);
6692 klass = mono_class_from_mono_type (type->type);
6694 if (klass->rank >= 1) {
6695 g_assert (klass->rank == 1);
6696 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6698 /* Bypass remoting object creation check */
6699 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6704 ves_icall_System_IO_get_temp_path (void)
6706 MONO_ARCH_SAVE_REGS;
6708 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6711 #ifndef PLATFORM_NO_DRIVEINFO
6713 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6714 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6718 ULARGE_INTEGER wapi_free_bytes_avail;
6719 ULARGE_INTEGER wapi_total_number_of_bytes;
6720 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6722 MONO_ARCH_SAVE_REGS;
6724 *error = ERROR_SUCCESS;
6725 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6726 &wapi_total_number_of_free_bytes);
6729 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6730 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6731 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6733 *free_bytes_avail = 0;
6734 *total_number_of_bytes = 0;
6735 *total_number_of_free_bytes = 0;
6736 *error = GetLastError ();
6743 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6745 MONO_ARCH_SAVE_REGS;
6747 return GetDriveType (mono_string_chars (root_path_name));
6752 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6754 MONO_ARCH_SAVE_REGS;
6756 return mono_compile_method (method);
6760 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6765 MONO_ARCH_SAVE_REGS;
6767 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6769 #if defined (PLATFORM_WIN32)
6770 /* Avoid mixing '/' and '\\' */
6773 for (i = strlen (path) - 1; i >= 0; i--)
6774 if (path [i] == '/')
6778 mcpath = mono_string_new (mono_domain_get (), path);
6785 get_bundled_machine_config (void)
6787 const gchar *machine_config;
6789 MONO_ARCH_SAVE_REGS;
6791 machine_config = mono_get_machine_config ();
6793 if (!machine_config)
6796 return mono_string_new (mono_domain_get (), machine_config);
6800 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6805 MONO_ARCH_SAVE_REGS;
6807 path = g_path_get_dirname (mono_get_config_dir ());
6809 #if defined (PLATFORM_WIN32)
6810 /* Avoid mixing '/' and '\\' */
6813 for (i = strlen (path) - 1; i >= 0; i--)
6814 if (path [i] == '/')
6818 ipath = mono_string_new (mono_domain_get (), path);
6825 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6827 MonoPEResourceDataEntry *entry;
6830 MONO_ARCH_SAVE_REGS;
6832 if (!assembly || !result || !size)
6837 image = assembly->assembly->image;
6838 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6842 *result = mono_image_rva_map (image, entry->rde_data_offset);
6847 *size = entry->rde_size;
6853 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6855 return mono_debug_using_mono_debugger ();
6859 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6861 #if defined (PLATFORM_WIN32)
6862 OutputDebugString (mono_string_chars (message));
6864 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
6868 /* Only used for value types */
6870 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6875 MONO_ARCH_SAVE_REGS;
6877 domain = mono_object_domain (type);
6878 klass = mono_class_from_mono_type (type->type);
6880 if (mono_class_is_nullable (klass))
6881 /* No arguments -> null */
6884 return mono_object_new (domain, klass);
6887 static MonoReflectionMethod *
6888 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
6890 MonoClass *klass, *parent;
6891 MonoMethod *method = m->method;
6892 MonoMethod *result = NULL;
6894 MONO_ARCH_SAVE_REGS;
6896 if (method->klass == NULL)
6899 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6900 MONO_CLASS_IS_INTERFACE (method->klass) ||
6901 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6904 klass = method->klass;
6905 if (klass->generic_class)
6906 klass = klass->generic_class->container_class;
6908 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6909 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6910 mono_class_setup_vtable (parent);
6911 if (parent->vtable_size <= method->slot)
6916 if (klass == method->klass)
6919 result = klass->vtable [method->slot];
6920 if (result == NULL) {
6921 /* It is an abstract method */
6922 gpointer iter = NULL;
6923 while ((result = mono_class_get_methods (klass, &iter)))
6924 if (result->slot == method->slot)
6931 return mono_method_get_object (mono_domain_get (), result, NULL);
6935 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6937 MonoMethod *method = m->method;
6939 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6944 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6946 MONO_ARCH_SAVE_REGS;
6948 iter->sig = *(MonoMethodSignature**)argsp;
6950 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6951 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6954 /* FIXME: it's not documented what start is exactly... */
6958 iter->args = argsp + sizeof (gpointer);
6959 #ifndef MONO_ARCH_REGPARMS
6961 guint32 i, arg_size;
6963 for (i = 0; i < iter->sig->sentinelpos; ++i) {
6964 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
6965 iter->args = (char*)iter->args + arg_size;
6970 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6972 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6976 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6978 guint32 i, arg_size;
6981 MONO_ARCH_SAVE_REGS;
6983 i = iter->sig->sentinelpos + iter->next_arg;
6985 g_assert (i < iter->sig->param_count);
6987 res.type = iter->sig->params [i];
6988 res.klass = mono_class_from_mono_type (res.type);
6989 res.value = iter->args;
6990 arg_size = mono_type_stack_size (res.type, &align);
6991 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6992 if (arg_size <= sizeof (gpointer)) {
6994 int padding = arg_size - mono_type_size (res.type, &dummy);
6995 res.value = (guint8*)res.value + padding;
6998 iter->args = (char*)iter->args + arg_size;
7001 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7007 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7009 guint32 i, arg_size;
7012 MONO_ARCH_SAVE_REGS;
7014 i = iter->sig->sentinelpos + iter->next_arg;
7016 g_assert (i < iter->sig->param_count);
7018 while (i < iter->sig->param_count) {
7019 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7021 res.type = iter->sig->params [i];
7022 res.klass = mono_class_from_mono_type (res.type);
7023 /* FIXME: endianess issue... */
7024 res.value = iter->args;
7025 arg_size = mono_type_stack_size (res.type, &align);
7026 iter->args = (char*)iter->args + arg_size;
7028 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7031 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7040 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7043 MONO_ARCH_SAVE_REGS;
7045 i = iter->sig->sentinelpos + iter->next_arg;
7047 g_assert (i < iter->sig->param_count);
7049 return iter->sig->params [i];
7053 mono_TypedReference_ToObject (MonoTypedRef tref)
7055 MONO_ARCH_SAVE_REGS;
7057 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7058 MonoObject** objp = tref.value;
7062 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7066 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7068 MONO_ARCH_SAVE_REGS;
7070 if (MONO_TYPE_IS_REFERENCE (type)) {
7071 MonoObject** objp = value;
7075 return mono_value_box (mono_domain_get (), klass, value);
7079 prelink_method (MonoMethod *method)
7081 const char *exc_class, *exc_arg;
7082 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7084 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7086 mono_raise_exception(
7087 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7089 /* create the wrapper, too? */
7093 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7095 MONO_ARCH_SAVE_REGS;
7096 prelink_method (method->method);
7100 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7102 MonoClass *klass = mono_class_from_mono_type (type->type);
7104 gpointer iter = NULL;
7105 MONO_ARCH_SAVE_REGS;
7107 while ((m = mono_class_get_methods (klass, &iter)))
7111 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7113 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7114 gint32 const **exponents,
7115 gunichar2 const **digitLowerTable,
7116 gunichar2 const **digitUpperTable,
7117 gint64 const **tenPowersList,
7118 gint32 const **decHexDigits)
7120 *mantissas = Formatter_MantissaBitsTable;
7121 *exponents = Formatter_TensExponentTable;
7122 *digitLowerTable = Formatter_DigitLowerTable;
7123 *digitUpperTable = Formatter_DigitUpperTable;
7124 *tenPowersList = Formatter_TenPowersList;
7125 *decHexDigits = Formatter_DecHexDigits;
7128 /* These parameters are "readonly" in corlib/System/Char.cs */
7130 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7131 guint8 const **numeric_data,
7132 gdouble const **numeric_data_values,
7133 guint16 const **to_lower_data_low,
7134 guint16 const **to_lower_data_high,
7135 guint16 const **to_upper_data_low,
7136 guint16 const **to_upper_data_high)
7138 *category_data = CategoryData;
7139 *numeric_data = NumericData;
7140 *numeric_data_values = NumericDataValues;
7141 *to_lower_data_low = ToLowerDataLow;
7142 *to_lower_data_high = ToLowerDataHigh;
7143 *to_upper_data_low = ToUpperDataLow;
7144 *to_upper_data_high = ToUpperDataHigh;
7148 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7150 return method->method->token;
7154 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7155 * and avoid useless allocations.
7158 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7162 for (i = 0; i < type->num_mods; ++i) {
7163 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7168 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7170 for (i = 0; i < type->num_mods; ++i) {
7171 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7172 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7173 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7181 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7183 MonoType *type = param->ClassImpl->type;
7184 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7185 MonoImage *image = method->method->klass->image;
7186 int pos = param->PositionImpl;
7187 MonoMethodSignature *sig = mono_method_signature (method->method);
7191 type = sig->params [pos];
7193 return type_array_from_modifiers (image, type, optional);
7197 get_property_type (MonoProperty *prop)
7199 MonoMethodSignature *sig;
7201 sig = mono_method_signature (prop->get);
7203 } else if (prop->set) {
7204 sig = mono_method_signature (prop->set);
7205 return sig->params [sig->param_count - 1];
7211 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7213 MonoType *type = get_property_type (property->property);
7214 MonoImage *image = property->klass->image;
7218 return type_array_from_modifiers (image, type, optional);
7222 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7224 MonoCustomAttrInfo *cinfo;
7227 cinfo = mono_reflection_get_custom_attrs_info (obj);
7230 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7232 mono_custom_attrs_free (cinfo);
7237 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7239 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7241 if (mono_loader_get_last_error ()) {
7242 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7243 g_assert_not_reached ();
7252 ves_icall_Mono_Runtime_GetDisplayName (void)
7255 MonoString *display_name;
7257 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7258 display_name = mono_string_new (mono_domain_get (), info);
7260 return display_name;
7264 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7266 MonoString *message;
7270 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7271 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7274 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7276 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7284 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7285 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7286 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7287 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7288 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7289 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7290 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7291 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7295 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7300 gunichar2 last, prev_last, prev2_last;
7308 last = prev_last = 0, prev2_last = 0;
7309 for (i = 0; i < ilength; i++) {
7311 if (c >= sizeof (dbase64)) {
7312 exc = mono_exception_from_name_msg (mono_get_corlib (),
7313 "System", "FormatException",
7314 "Invalid character found.");
7315 mono_raise_exception (exc);
7316 } else if (isspace (c)) {
7319 prev2_last = prev_last;
7325 olength = ilength - ignored;
7327 if (allowWhitespaceOnly && olength == 0) {
7328 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7331 if ((olength & 3) != 0 || olength <= 0) {
7332 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7333 "FormatException", "Invalid length.");
7334 mono_raise_exception (exc);
7337 if (prev2_last == '=') {
7338 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7339 mono_raise_exception (exc);
7342 olength = (olength * 3) / 4;
7346 if (prev_last == '=')
7349 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7350 res_ptr = mono_array_addr (result, guchar, 0);
7351 for (i = 0; i < ilength; ) {
7354 for (k = 0; k < 4 && i < ilength;) {
7360 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7361 exc = mono_exception_from_name_msg (mono_get_corlib (),
7362 "System", "FormatException",
7363 "Invalid character found.");
7364 mono_raise_exception (exc);
7369 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7371 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7373 *res_ptr++ = (b [2] << 6) | b [3];
7375 while (i < ilength && isspace (start [i]))
7383 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7385 MONO_ARCH_SAVE_REGS;
7387 return base64_to_byte_array (mono_string_chars (str),
7388 mono_string_length (str), allowWhitespaceOnly);
7392 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7394 MONO_ARCH_SAVE_REGS;
7396 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7400 #define ICALL_TYPE(id,name,first)
7401 #define ICALL(id,name,func) Icall_ ## id,
7404 #include "metadata/icall-def.h"
7410 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7411 #define ICALL(id,name,func)
7413 #include "metadata/icall-def.h"
7419 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7420 #define ICALL(id,name,func)
7422 guint16 first_icall;
7425 static const IcallTypeDesc
7426 icall_type_descs [] = {
7427 #include "metadata/icall-def.h"
7431 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7434 #define ICALL_TYPE(id,name,first)
7437 #ifdef HAVE_ARRAY_ELEM_INIT
7438 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7439 #define MSGSTRFIELD1(line) str##line
7441 static const struct msgstrtn_t {
7442 #define ICALL(id,name,func)
7444 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7445 #include "metadata/icall-def.h"
7447 } icall_type_names_str = {
7448 #define ICALL_TYPE(id,name,first) (name),
7449 #include "metadata/icall-def.h"
7452 static const guint16 icall_type_names_idx [] = {
7453 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7454 #include "metadata/icall-def.h"
7457 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7459 static const struct msgstr_t {
7461 #define ICALL_TYPE(id,name,first)
7462 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7463 #include "metadata/icall-def.h"
7465 } icall_names_str = {
7466 #define ICALL(id,name,func) (name),
7467 #include "metadata/icall-def.h"
7470 static const guint16 icall_names_idx [] = {
7471 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7472 #include "metadata/icall-def.h"
7475 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7481 #define ICALL_TYPE(id,name,first) name,
7482 #define ICALL(id,name,func)
7483 static const char* const
7484 icall_type_names [] = {
7485 #include "metadata/icall-def.h"
7489 #define icall_type_name_get(id) (icall_type_names [(id)])
7493 #define ICALL_TYPE(id,name,first)
7494 #define ICALL(id,name,func) name,
7495 static const char* const
7497 #include "metadata/icall-def.h"
7500 #define icall_name_get(id) icall_names [(id)]
7502 #endif /* !HAVE_ARRAY_ELEM_INIT */
7506 #define ICALL_TYPE(id,name,first)
7507 #define ICALL(id,name,func) func,
7508 static const gconstpointer
7509 icall_functions [] = {
7510 #include "metadata/icall-def.h"
7514 static GHashTable *icall_hash = NULL;
7515 static GHashTable *jit_icall_hash_name = NULL;
7516 static GHashTable *jit_icall_hash_addr = NULL;
7519 mono_icall_init (void)
7523 /* check that tables are sorted: disable in release */
7526 const char *prev_class = NULL;
7527 const char *prev_method;
7529 for (i = 0; i < Icall_type_num; ++i) {
7530 const IcallTypeDesc *desc;
7533 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7534 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7535 prev_class = icall_type_name_get (i);
7536 desc = &icall_type_descs [i];
7537 num_icalls = icall_desc_num_icalls (desc);
7538 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7539 for (j = 0; j < num_icalls; ++j) {
7540 const char *methodn = icall_name_get (desc->first_icall + j);
7541 if (prev_method && strcmp (prev_method, methodn) >= 0)
7542 g_print ("method %s should come before method %s\n", methodn, prev_method);
7543 prev_method = methodn;
7548 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7552 mono_icall_cleanup (void)
7554 g_hash_table_destroy (icall_hash);
7555 g_hash_table_destroy (jit_icall_hash_name);
7556 g_hash_table_destroy (jit_icall_hash_addr);
7560 mono_add_internal_call (const char *name, gconstpointer method)
7562 mono_loader_lock ();
7564 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7566 mono_loader_unlock ();
7569 #ifdef HAVE_ARRAY_ELEM_INIT
7571 compare_method_imap (const void *key, const void *elem)
7573 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7574 return strcmp (key, method_name);
7578 find_method_icall (const IcallTypeDesc *imap, const char *name)
7580 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7583 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7587 compare_class_imap (const void *key, const void *elem)
7589 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7590 return strcmp (key, class_name);
7593 static const IcallTypeDesc*
7594 find_class_icalls (const char *name)
7596 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7599 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7604 compare_method_imap (const void *key, const void *elem)
7606 const char** method_name = (const char**)elem;
7607 return strcmp (key, *method_name);
7611 find_method_icall (const IcallTypeDesc *imap, const char *name)
7613 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7616 return (gpointer)icall_functions [(nameslot - icall_names)];
7620 compare_class_imap (const void *key, const void *elem)
7622 const char** class_name = (const char**)elem;
7623 return strcmp (key, *class_name);
7626 static const IcallTypeDesc*
7627 find_class_icalls (const char *name)
7629 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7632 return &icall_type_descs [nameslot - icall_type_names];
7638 * we should probably export this as an helper (handle nested types).
7639 * Returns the number of chars written in buf.
7642 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7644 int nspacelen, cnamelen;
7645 nspacelen = strlen (klass->name_space);
7646 cnamelen = strlen (klass->name);
7647 if (nspacelen + cnamelen + 2 > bufsize)
7650 memcpy (buf, klass->name_space, nspacelen);
7651 buf [nspacelen ++] = '.';
7653 memcpy (buf + nspacelen, klass->name, cnamelen);
7654 buf [nspacelen + cnamelen] = 0;
7655 return nspacelen + cnamelen;
7659 mono_lookup_internal_call (MonoMethod *method)
7664 int typelen = 0, mlen, siglen;
7666 const IcallTypeDesc *imap;
7668 g_assert (method != NULL);
7670 if (method->is_inflated)
7671 method = ((MonoMethodInflated *) method)->declaring;
7673 if (method->klass->nested_in) {
7674 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7678 mname [pos++] = '/';
7681 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7687 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7692 imap = find_class_icalls (mname);
7694 mname [typelen] = ':';
7695 mname [typelen + 1] = ':';
7697 mlen = strlen (method->name);
7698 memcpy (mname + typelen + 2, method->name, mlen);
7699 sigstart = mname + typelen + 2 + mlen;
7702 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7703 siglen = strlen (tmpsig);
7704 if (typelen + mlen + siglen + 6 > sizeof (mname))
7707 memcpy (sigstart + 1, tmpsig, siglen);
7708 sigstart [siglen + 1] = ')';
7709 sigstart [siglen + 2] = 0;
7712 mono_loader_lock ();
7714 res = g_hash_table_lookup (icall_hash, mname);
7716 mono_loader_unlock ();
7719 /* try without signature */
7721 res = g_hash_table_lookup (icall_hash, mname);
7723 mono_loader_unlock ();
7727 /* it wasn't found in the static call tables */
7729 mono_loader_unlock ();
7732 res = find_method_icall (imap, sigstart - mlen);
7734 mono_loader_unlock ();
7737 /* try _with_ signature */
7739 res = find_method_icall (imap, sigstart - mlen);
7741 mono_loader_unlock ();
7745 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7746 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7747 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7748 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7749 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");
7750 g_print ("If you see other errors or faults after this message they are probably related\n");
7751 g_print ("and you need to fix your mono install first.\n");
7753 mono_loader_unlock ();
7759 type_from_typename (char *typename)
7761 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7763 if (!strcmp (typename, "int"))
7764 klass = mono_defaults.int_class;
7765 else if (!strcmp (typename, "ptr"))
7766 klass = mono_defaults.int_class;
7767 else if (!strcmp (typename, "void"))
7768 klass = mono_defaults.void_class;
7769 else if (!strcmp (typename, "int32"))
7770 klass = mono_defaults.int32_class;
7771 else if (!strcmp (typename, "uint32"))
7772 klass = mono_defaults.uint32_class;
7773 else if (!strcmp (typename, "int8"))
7774 klass = mono_defaults.sbyte_class;
7775 else if (!strcmp (typename, "uint8"))
7776 klass = mono_defaults.byte_class;
7777 else if (!strcmp (typename, "int16"))
7778 klass = mono_defaults.int16_class;
7779 else if (!strcmp (typename, "uint16"))
7780 klass = mono_defaults.uint16_class;
7781 else if (!strcmp (typename, "long"))
7782 klass = mono_defaults.int64_class;
7783 else if (!strcmp (typename, "ulong"))
7784 klass = mono_defaults.uint64_class;
7785 else if (!strcmp (typename, "float"))
7786 klass = mono_defaults.single_class;
7787 else if (!strcmp (typename, "double"))
7788 klass = mono_defaults.double_class;
7789 else if (!strcmp (typename, "object"))
7790 klass = mono_defaults.object_class;
7791 else if (!strcmp (typename, "obj"))
7792 klass = mono_defaults.object_class;
7793 else if (!strcmp (typename, "string"))
7794 klass = mono_defaults.string_class;
7795 else if (!strcmp (typename, "bool"))
7796 klass = mono_defaults.boolean_class;
7797 else if (!strcmp (typename, "boolean"))
7798 klass = mono_defaults.boolean_class;
7800 g_error ("%s", typename);
7801 g_assert_not_reached ();
7803 return &klass->byval_arg;
7806 MonoMethodSignature*
7807 mono_create_icall_signature (const char *sigstr)
7812 MonoMethodSignature *res;
7814 mono_loader_lock ();
7815 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7817 mono_loader_unlock ();
7821 parts = g_strsplit (sigstr, " ", 256);
7830 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7833 #ifdef PLATFORM_WIN32
7835 * Under windows, the default pinvoke calling convention is STDCALL but
7838 res->call_convention = MONO_CALL_C;
7841 res->ret = type_from_typename (parts [0]);
7842 for (i = 1; i < len; ++i) {
7843 res->params [i - 1] = type_from_typename (parts [i]);
7848 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7850 mono_loader_unlock ();
7856 mono_find_jit_icall_by_name (const char *name)
7858 MonoJitICallInfo *info;
7859 g_assert (jit_icall_hash_name);
7861 mono_loader_lock ();
7862 info = g_hash_table_lookup (jit_icall_hash_name, name);
7863 mono_loader_unlock ();
7868 mono_find_jit_icall_by_addr (gconstpointer addr)
7870 MonoJitICallInfo *info;
7871 g_assert (jit_icall_hash_addr);
7873 mono_loader_lock ();
7874 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7875 mono_loader_unlock ();
7881 * mono_get_jit_icall_info:
7883 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7884 * caller should access it while holding the loader lock.
7887 mono_get_jit_icall_info (void)
7889 return jit_icall_hash_name;
7893 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7895 mono_loader_lock ();
7896 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7897 mono_loader_unlock ();
7901 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7903 MonoJitICallInfo *info;
7908 mono_loader_lock ();
7910 if (!jit_icall_hash_name) {
7911 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7912 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7915 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7916 g_warning ("jit icall already defined \"%s\"\n", name);
7917 g_assert_not_reached ();
7920 info = g_new0 (MonoJitICallInfo, 1);
7927 info->wrapper = func;
7929 info->wrapper = NULL;
7932 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7933 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7935 mono_loader_unlock ();