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 (mono_domain_get (), klass);
952 if (klass->exception_type != MONO_EXCEPTION_NONE)
953 mono_raise_exception (mono_class_get_exception_for_failure (klass));
955 MONO_CHECK_ARG (handle, vtable);
957 /* This will call the type constructor */
958 mono_runtime_class_init (vtable);
962 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
966 mono_image_check_for_module_cctor (image);
967 if (image->has_module_cctor) {
968 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
969 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
974 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
978 return mono_object_clone (this);
982 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
985 MonoObject **values = NULL;
989 MonoClassField* field;
994 klass = mono_object_class (this);
996 if (mono_class_num_fields (klass) == 0)
997 return mono_object_hash (this);
1000 * Compute the starting value of the hashcode for fields of primitive
1001 * types, and return the remaining fields in an array to the managed side.
1002 * This way, we can avoid costly reflection operations in managed code.
1005 while ((field = mono_class_get_fields (klass, &iter))) {
1006 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1008 if (mono_field_is_deleted (field))
1010 /* FIXME: Add more types */
1011 switch (field->type->type) {
1013 result ^= *(gint32*)((guint8*)this + field->offset);
1015 case MONO_TYPE_STRING: {
1017 s = *(MonoString**)((guint8*)this + field->offset);
1019 result ^= mono_string_hash (s);
1024 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1025 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1026 values [count++] = o;
1032 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1033 for (i = 0; i < count; ++i)
1034 mono_array_setref (*fields, i, values [i]);
1042 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1045 MonoObject **values = NULL;
1047 MonoClassField* field;
1051 MONO_ARCH_SAVE_REGS;
1053 MONO_CHECK_ARG_NULL (that);
1055 if (this->vtable != that->vtable)
1058 klass = mono_object_class (this);
1060 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1061 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1064 * Do the comparison for fields of primitive type and return a result if
1065 * possible. Otherwise, return the remaining fields in an array to the
1066 * managed side. This way, we can avoid costly reflection operations in
1071 while ((field = mono_class_get_fields (klass, &iter))) {
1072 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1074 if (mono_field_is_deleted (field))
1076 /* FIXME: Add more types */
1077 switch (field->type->type) {
1080 case MONO_TYPE_BOOLEAN:
1081 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1086 case MONO_TYPE_CHAR:
1087 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1092 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1097 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1101 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1105 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1110 case MONO_TYPE_STRING: {
1111 MonoString *s1, *s2;
1112 guint32 s1len, s2len;
1113 s1 = *(MonoString**)((guint8*)this + field->offset);
1114 s2 = *(MonoString**)((guint8*)that + field->offset);
1117 if ((s1 == NULL) || (s2 == NULL))
1119 s1len = mono_string_length (s1);
1120 s2len = mono_string_length (s2);
1124 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1130 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1131 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1132 values [count++] = o;
1133 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1134 values [count++] = o;
1137 if (klass->enumtype)
1138 /* enums only have one non-static field */
1144 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1145 for (i = 0; i < count; ++i)
1146 mono_array_setref (*fields, i, values [i]);
1153 static MonoReflectionType *
1154 ves_icall_System_Object_GetType (MonoObject *obj)
1156 MONO_ARCH_SAVE_REGS;
1158 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1159 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1161 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1165 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1167 MONO_ARCH_SAVE_REGS;
1169 mtype->type = &obj->vtable->klass->byval_arg;
1170 g_assert (mtype->type->type);
1174 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1176 MONO_ARCH_SAVE_REGS;
1178 MONO_CHECK_ARG_NULL (obj);
1180 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1184 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1185 MonoReflectionMethod *method,
1186 MonoArray *opt_param_types)
1188 MONO_ARCH_SAVE_REGS;
1190 MONO_CHECK_ARG_NULL (method);
1192 return mono_image_create_method_token (
1193 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1197 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1199 MONO_ARCH_SAVE_REGS;
1201 mono_image_create_pefile (mb, file);
1205 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1207 MONO_ARCH_SAVE_REGS;
1209 mono_image_build_metadata (mb);
1213 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1215 MONO_ARCH_SAVE_REGS;
1217 mono_image_register_token (mb->dynamic_image, token, obj);
1221 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1223 MonoMethod **dest = data;
1225 /* skip unmanaged frames */
1241 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1243 MonoMethod **dest = data;
1245 /* skip unmanaged frames */
1250 if (!strcmp (m->klass->name_space, "System.Reflection"))
1259 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1261 MonoMethod **dest = data;
1263 /* skip unmanaged frames */
1267 if (m->wrapper_type != MONO_WRAPPER_NONE)
1270 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1284 static MonoReflectionType *
1285 type_from_name (const char *str, MonoBoolean ignoreCase)
1287 MonoType *type = NULL;
1288 MonoAssembly *assembly = NULL;
1289 MonoTypeNameParse info;
1290 char *temp_str = g_strdup (str);
1291 gboolean type_resolve = FALSE;
1293 MONO_ARCH_SAVE_REGS;
1295 /* mono_reflection_parse_type() mangles the string */
1296 if (!mono_reflection_parse_type (temp_str, &info)) {
1297 mono_reflection_free_type_info (&info);
1302 if (info.assembly.name) {
1303 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1305 MonoMethod *m = mono_method_get_last_managed ();
1306 MonoMethod *dest = m;
1308 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1313 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1314 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1315 * to crash. This only seems to happen in some strange remoting
1316 * scenarios and I was unable to figure out what's happening there.
1317 * Dec 10, 2005 - Martin.
1321 assembly = dest->klass->image->assembly;
1323 g_warning (G_STRLOC);
1328 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1330 if (!info.assembly.name && !type) /* try mscorlib */
1331 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1333 mono_reflection_free_type_info (&info);
1339 return mono_type_get_object (mono_domain_get (), type);
1343 MonoReflectionType *
1344 mono_type_get (const char *str)
1346 char *copy = g_strdup (str);
1347 MonoReflectionType *type = type_from_name (copy, FALSE);
1354 static MonoReflectionType*
1355 ves_icall_type_from_name (MonoString *name,
1356 MonoBoolean throwOnError,
1357 MonoBoolean ignoreCase)
1359 char *str = mono_string_to_utf8 (name);
1360 MonoReflectionType *type;
1362 type = type_from_name (str, ignoreCase);
1365 MonoException *e = NULL;
1368 e = mono_get_exception_type_load (name, NULL);
1370 mono_loader_clear_error ();
1372 mono_raise_exception (e);
1379 static MonoReflectionType*
1380 ves_icall_type_from_handle (MonoType *handle)
1382 MonoDomain *domain = mono_domain_get ();
1383 MonoClass *klass = mono_class_from_mono_type (handle);
1385 MONO_ARCH_SAVE_REGS;
1387 mono_class_init (klass);
1388 return mono_type_get_object (domain, handle);
1392 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1394 MONO_ARCH_SAVE_REGS;
1396 if (c && type->type && c->type)
1397 return mono_metadata_type_equal (type->type, c->type);
1399 return (type == c) ? TRUE : FALSE;
1402 /* System.TypeCode */
1421 TYPECODE_STRING = 18
1425 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1427 int t = type->type->type;
1429 MONO_ARCH_SAVE_REGS;
1431 if (type->type->byref)
1432 return TYPECODE_OBJECT;
1436 case MONO_TYPE_VOID:
1437 return TYPECODE_OBJECT;
1438 case MONO_TYPE_BOOLEAN:
1439 return TYPECODE_BOOLEAN;
1441 return TYPECODE_BYTE;
1443 return TYPECODE_SBYTE;
1445 return TYPECODE_UINT16;
1447 return TYPECODE_INT16;
1448 case MONO_TYPE_CHAR:
1449 return TYPECODE_CHAR;
1453 return TYPECODE_OBJECT;
1455 return TYPECODE_UINT32;
1457 return TYPECODE_INT32;
1459 return TYPECODE_UINT64;
1461 return TYPECODE_INT64;
1463 return TYPECODE_SINGLE;
1465 return TYPECODE_DOUBLE;
1466 case MONO_TYPE_VALUETYPE:
1467 if (type->type->data.klass->enumtype) {
1468 t = mono_class_enum_basetype (type->type->data.klass)->type;
1471 MonoClass *k = type->type->data.klass;
1472 if (strcmp (k->name_space, "System") == 0) {
1473 if (strcmp (k->name, "Decimal") == 0)
1474 return TYPECODE_DECIMAL;
1475 else if (strcmp (k->name, "DateTime") == 0)
1476 return TYPECODE_DATETIME;
1479 return TYPECODE_OBJECT;
1480 case MONO_TYPE_STRING:
1481 return TYPECODE_STRING;
1482 case MONO_TYPE_SZARRAY:
1483 case MONO_TYPE_ARRAY:
1484 case MONO_TYPE_OBJECT:
1486 case MONO_TYPE_MVAR:
1487 case MONO_TYPE_TYPEDBYREF:
1488 return TYPECODE_OBJECT;
1489 case MONO_TYPE_CLASS:
1491 MonoClass *k = type->type->data.klass;
1492 if (strcmp (k->name_space, "System") == 0) {
1493 if (strcmp (k->name, "DBNull") == 0)
1494 return TYPECODE_DBNULL;
1497 return TYPECODE_OBJECT;
1498 case MONO_TYPE_GENERICINST:
1499 return TYPECODE_OBJECT;
1501 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1507 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1513 MONO_ARCH_SAVE_REGS;
1515 g_assert (type != NULL);
1517 domain = ((MonoObject *)type)->vtable->domain;
1519 if (!c) /* FIXME: dont know what do do here */
1522 klass = mono_class_from_mono_type (type->type);
1523 klassc = mono_class_from_mono_type (c->type);
1525 if (type->type->byref)
1526 return klassc == mono_defaults.object_class;
1528 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1532 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1538 MONO_ARCH_SAVE_REGS;
1540 g_assert (type != NULL);
1542 domain = ((MonoObject *)type)->vtable->domain;
1544 klass = mono_class_from_mono_type (type->type);
1545 klassc = mono_class_from_mono_type (c->type);
1547 if (type->type->byref && !c->type->byref)
1550 return mono_class_is_assignable_from (klass, klassc);
1554 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1556 MonoClass *klass = mono_class_from_mono_type (type->type);
1557 return mono_object_isinst (obj, klass) != NULL;
1561 ves_icall_get_attributes (MonoReflectionType *type)
1563 MonoClass *klass = mono_class_from_mono_type (type->type);
1565 MONO_ARCH_SAVE_REGS;
1567 return klass->flags;
1570 static MonoReflectionMarshal*
1571 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1573 MonoClass *klass = field->field->parent;
1574 MonoMarshalType *info;
1577 if (klass->generic_container ||
1578 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1581 info = mono_marshal_load_type_info (klass);
1583 for (i = 0; i < info->num_fields; ++i) {
1584 if (info->fields [i].field == field->field) {
1585 if (!info->fields [i].mspec)
1588 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1595 static MonoReflectionField*
1596 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1598 gboolean found = FALSE;
1605 klass = handle->parent;
1607 klass = mono_class_from_mono_type (type);
1609 /* Check that the field belongs to the class */
1610 for (k = klass; k; k = k->parent) {
1611 if (k == handle->parent) {
1618 /* The managed code will throw the exception */
1622 return mono_field_get_object (mono_domain_get (), klass, handle);
1625 static MonoReflectionField*
1626 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1628 MONO_ARCH_SAVE_REGS;
1632 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1636 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1638 MonoType *type = field->field->type;
1640 return type_array_from_modifiers (field->field->parent->image, type, optional);
1644 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1646 MonoDomain *domain = mono_domain_get ();
1647 MonoMethodSignature* sig;
1648 MONO_ARCH_SAVE_REGS;
1650 sig = mono_method_signature (method);
1652 g_assert (mono_loader_get_last_error ());
1653 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1656 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1657 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1658 info->attrs = method->flags;
1659 info->implattrs = method->iflags;
1660 if (sig->call_convention == MONO_CALL_DEFAULT)
1661 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1663 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1668 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1672 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1674 MonoDomain *domain = mono_domain_get ();
1676 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1679 static MonoReflectionMarshal*
1680 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1682 MonoDomain *domain = mono_domain_get ();
1683 MonoReflectionMarshal* res = NULL;
1684 MonoMarshalSpec **mspecs;
1687 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1688 mono_method_get_marshal_info (method, mspecs);
1691 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1693 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1695 mono_metadata_free_marshal_spec (mspecs [i]);
1702 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1704 return field->field->offset - sizeof (MonoObject);
1707 static MonoReflectionType*
1708 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1711 MONO_ARCH_SAVE_REGS;
1713 parent = declaring? field->field->parent: field->klass;
1715 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1719 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1722 MonoClassField *cf = field->field;
1726 MonoDomain *domain = mono_object_domain (field);
1728 gboolean is_static = FALSE;
1729 gboolean is_ref = FALSE;
1731 MONO_ARCH_SAVE_REGS;
1733 if (field->klass->image->assembly->ref_only)
1734 mono_raise_exception (mono_get_exception_invalid_operation (
1735 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1737 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1738 mono_security_core_clr_ensure_reflection_access_field (cf);
1740 mono_class_init (field->klass);
1742 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1745 if (obj && !is_static) {
1746 /* Check that the field belongs to the object */
1747 gboolean found = FALSE;
1750 for (k = obj->vtable->klass; k; k = k->parent) {
1751 if (k == cf->parent) {
1758 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);
1759 MonoException *ex = mono_get_exception_argument (NULL, msg);
1761 mono_raise_exception (ex);
1765 t = mono_type_get_underlying_type (cf->type);
1767 case MONO_TYPE_STRING:
1768 case MONO_TYPE_OBJECT:
1769 case MONO_TYPE_CLASS:
1770 case MONO_TYPE_ARRAY:
1771 case MONO_TYPE_SZARRAY:
1776 case MONO_TYPE_BOOLEAN:
1779 case MONO_TYPE_CHAR:
1788 case MONO_TYPE_VALUETYPE:
1791 case MONO_TYPE_GENERICINST:
1792 if (mono_type_generic_inst_is_valuetype (t)) {
1799 g_error ("type 0x%x not handled in "
1800 "ves_icall_Monofield_GetValue", t->type);
1806 vtable = mono_class_vtable (domain, cf->parent);
1807 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1808 mono_runtime_class_init (vtable);
1813 mono_field_static_get_value (vtable, cf, &o);
1815 mono_field_get_value (obj, cf, &o);
1820 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1821 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1824 /* Convert the Nullable structure into a boxed vtype */
1826 buf = (guint8*)vtable->data + cf->offset;
1828 buf = (guint8*)obj + cf->offset;
1830 return mono_nullable_box (buf, nklass);
1833 /* boxed value type */
1834 klass = mono_class_from_mono_type (cf->type);
1835 o = mono_object_new (domain, klass);
1836 v = ((gchar *) o) + sizeof (MonoObject);
1838 mono_field_static_get_value (vtable, cf, v);
1840 mono_field_get_value (obj, cf, v);
1847 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1849 MonoClassField *cf = field->field;
1852 MONO_ARCH_SAVE_REGS;
1854 if (field->klass->image->assembly->ref_only)
1855 mono_raise_exception (mono_get_exception_invalid_operation (
1856 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1858 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1859 mono_security_core_clr_ensure_reflection_access_field (cf);
1861 v = (gchar *) value;
1862 if (!cf->type->byref) {
1863 switch (cf->type->type) {
1866 case MONO_TYPE_BOOLEAN:
1869 case MONO_TYPE_CHAR:
1878 case MONO_TYPE_VALUETYPE:
1880 v += sizeof (MonoObject);
1882 case MONO_TYPE_STRING:
1883 case MONO_TYPE_OBJECT:
1884 case MONO_TYPE_CLASS:
1885 case MONO_TYPE_ARRAY:
1886 case MONO_TYPE_SZARRAY:
1889 case MONO_TYPE_GENERICINST: {
1890 MonoGenericClass *gclass = cf->type->data.generic_class;
1891 g_assert (!gclass->context.class_inst->is_open);
1893 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1894 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1895 MonoObject *nullable;
1898 * Convert the boxed vtype into a Nullable structure.
1899 * This is complicated by the fact that Nullables have
1900 * a variable structure.
1902 nullable = mono_object_new (mono_domain_get (), nklass);
1904 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1906 v = mono_object_unbox (nullable);
1909 if (gclass->container_class->valuetype && (v != NULL))
1910 v += sizeof (MonoObject);
1914 g_error ("type 0x%x not handled in "
1915 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1920 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1921 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1922 if (!vtable->initialized)
1923 mono_runtime_class_init (vtable);
1924 mono_field_static_set_value (vtable, cf, v);
1926 mono_field_set_value (obj, cf, v);
1931 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1933 MonoObject *o = NULL;
1934 MonoClassField *field = this->field;
1936 MonoDomain *domain = mono_object_domain (this);
1938 MonoTypeEnum def_type;
1939 const char *def_value;
1941 MONO_ARCH_SAVE_REGS;
1943 mono_class_init (field->parent);
1945 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1946 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1948 if (field->parent->image->dynamic) {
1950 g_assert_not_reached ();
1953 def_value = mono_class_get_field_default_value (field, &def_type);
1958 case MONO_TYPE_BOOLEAN:
1961 case MONO_TYPE_CHAR:
1969 case MONO_TYPE_R8: {
1972 /* boxed value type */
1973 t = g_new0 (MonoType, 1);
1975 klass = mono_class_from_mono_type (t);
1977 o = mono_object_new (domain, klass);
1978 v = ((gchar *) o) + sizeof (MonoObject);
1979 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1982 case MONO_TYPE_STRING:
1983 case MONO_TYPE_CLASS:
1984 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1987 g_assert_not_reached ();
1993 static MonoReflectionType*
1994 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1996 MonoMethod *method = rmethod->method.method;
1998 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
2001 /* From MonoProperty.cs */
2003 PInfo_Attributes = 1,
2004 PInfo_GetMethod = 1 << 1,
2005 PInfo_SetMethod = 1 << 2,
2006 PInfo_ReflectedType = 1 << 3,
2007 PInfo_DeclaringType = 1 << 4,
2012 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2014 MonoDomain *domain = mono_object_domain (property);
2016 MONO_ARCH_SAVE_REGS;
2018 if ((req_info & PInfo_ReflectedType) != 0)
2019 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2020 else if ((req_info & PInfo_DeclaringType) != 0)
2021 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2023 if ((req_info & PInfo_Name) != 0)
2024 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2026 if ((req_info & PInfo_Attributes) != 0)
2027 info->attrs = property->property->attrs;
2029 if ((req_info & PInfo_GetMethod) != 0)
2030 MONO_STRUCT_SETREF (info, get, property->property->get ?
2031 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2033 if ((req_info & PInfo_SetMethod) != 0)
2034 MONO_STRUCT_SETREF (info, set, property->property->set ?
2035 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2037 * There may be other methods defined for properties, though, it seems they are not exposed
2038 * in the reflection API
2043 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2045 MonoDomain *domain = mono_object_domain (event);
2047 MONO_ARCH_SAVE_REGS;
2049 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2050 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2052 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2053 info->attrs = event->event->attrs;
2054 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2055 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2056 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2058 if (event->event->other) {
2060 while (event->event->other [n])
2062 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2064 for (i = 0; i < n; i++)
2065 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2070 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2072 MonoDomain *domain = mono_object_domain (type);
2074 GPtrArray *ifaces = NULL;
2076 MonoClass *class = mono_class_from_mono_type (type->type);
2079 MonoGenericContext *context = NULL;
2081 MONO_ARCH_SAVE_REGS;
2083 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2084 context = mono_class_get_context (class);
2085 class = class->generic_class->container_class;
2088 mono_class_setup_vtable (class);
2090 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2092 for (parent = class; parent; parent = parent->parent) {
2093 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2095 for (i = 0; i < tmp_ifaces->len; ++i) {
2096 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2098 if (mono_bitset_test (slots, ic->interface_id))
2101 mono_bitset_set (slots, ic->interface_id);
2103 ifaces = g_ptr_array_new ();
2104 g_ptr_array_add (ifaces, ic);
2106 g_ptr_array_free (tmp_ifaces, TRUE);
2109 mono_bitset_free (slots);
2112 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2114 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2115 for (i = 0; i < ifaces->len; ++i) {
2116 MonoClass *ic = g_ptr_array_index (ifaces, i);
2117 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2118 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2119 inflated = ret = mono_class_inflate_generic_type (ret, context);
2121 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2123 mono_metadata_free_type (inflated);
2125 g_ptr_array_free (ifaces, TRUE);
2131 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2133 MonoClass *class = mono_class_from_mono_type (type->type);
2134 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2135 MonoReflectionMethod *member;
2138 int i = 0, len, ioffset;
2141 MONO_ARCH_SAVE_REGS;
2143 mono_class_setup_vtable (class);
2145 /* type doesn't implement iface: the exception is thrown in managed code */
2146 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2149 len = mono_class_num_methods (iclass);
2150 ioffset = mono_class_interface_offset (class, iclass);
2151 domain = mono_object_domain (type);
2152 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2153 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2156 while ((method = mono_class_get_methods (iclass, &iter))) {
2157 member = mono_method_get_object (domain, method, iclass);
2158 mono_array_setref (*methods, i, member);
2159 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2160 mono_array_setref (*targets, i, member);
2167 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2169 MonoClass *klass = mono_class_from_mono_type (type->type);
2171 if (klass->image->dynamic) {
2172 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2173 *packing = tb->packing_size;
2174 *size = tb->class_size;
2176 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2180 static MonoReflectionType*
2181 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2185 MONO_ARCH_SAVE_REGS;
2187 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2188 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2190 class = mono_class_from_mono_type (type->type);
2192 // GetElementType should only return a type for:
2193 // Array Pointer PassedByRef
2194 if (type->type->byref)
2195 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2196 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2197 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2198 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2199 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2204 static MonoReflectionType*
2205 ves_icall_get_type_parent (MonoReflectionType *type)
2207 MonoClass *class = mono_class_from_mono_type (type->type);
2209 MONO_ARCH_SAVE_REGS;
2211 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2215 ves_icall_type_ispointer (MonoReflectionType *type)
2217 MONO_ARCH_SAVE_REGS;
2219 return type->type->type == MONO_TYPE_PTR;
2223 ves_icall_type_isprimitive (MonoReflectionType *type)
2225 MONO_ARCH_SAVE_REGS;
2227 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)));
2231 ves_icall_type_isbyref (MonoReflectionType *type)
2233 MONO_ARCH_SAVE_REGS;
2235 return type->type->byref;
2239 ves_icall_type_iscomobject (MonoReflectionType *type)
2241 MonoClass *klass = mono_class_from_mono_type (type->type);
2242 MONO_ARCH_SAVE_REGS;
2244 return (klass && klass->is_com_object);
2247 static MonoReflectionModule*
2248 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2250 MonoClass *class = mono_class_from_mono_type (type->type);
2252 MONO_ARCH_SAVE_REGS;
2254 return mono_module_get_object (mono_object_domain (type), class->image);
2257 static MonoReflectionAssembly*
2258 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2260 MonoDomain *domain = mono_domain_get ();
2261 MonoClass *class = mono_class_from_mono_type (type->type);
2263 MONO_ARCH_SAVE_REGS;
2265 return mono_assembly_get_object (domain, class->image->assembly);
2268 static MonoReflectionType*
2269 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2271 MonoDomain *domain = mono_domain_get ();
2274 MONO_ARCH_SAVE_REGS;
2276 if (type->type->byref)
2278 if (type->type->type == MONO_TYPE_VAR)
2279 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2280 else if (type->type->type == MONO_TYPE_MVAR)
2281 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2283 class = mono_class_from_mono_type (type->type)->nested_in;
2285 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2288 static MonoReflectionType*
2289 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2291 MonoDomain *domain = mono_domain_get ();
2292 MonoClass *class = mono_class_from_mono_type (type->type);
2294 MONO_ARCH_SAVE_REGS;
2296 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2297 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2298 else if (class->element_class)
2299 return mono_type_get_object (domain, &class->element_class->byval_arg);
2305 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2307 MonoDomain *domain = mono_domain_get ();
2308 MonoClass *class = mono_class_from_mono_type (type->type);
2310 MONO_ARCH_SAVE_REGS;
2312 if (type->type->byref) {
2313 char *n = g_strdup_printf ("%s&", class->name);
2314 MonoString *res = mono_string_new (domain, n);
2320 return mono_string_new (domain, class->name);
2325 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2327 MonoDomain *domain = mono_domain_get ();
2328 MonoClass *class = mono_class_from_mono_type (type->type);
2330 MONO_ARCH_SAVE_REGS;
2332 while (class->nested_in)
2333 class = class->nested_in;
2335 if (class->name_space [0] == '\0')
2338 return mono_string_new (domain, class->name_space);
2342 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2346 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2347 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2349 class = mono_class_from_mono_type (type->type);
2354 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2357 MonoClass *klass, *pklass;
2358 MonoDomain *domain = mono_object_domain (type);
2359 MonoVTable *array_vtable = mono_class_vtable (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1));
2361 MONO_ARCH_SAVE_REGS;
2363 klass = mono_class_from_mono_type (type->type);
2365 if (klass->generic_container) {
2366 MonoGenericContainer *container = klass->generic_container;
2367 res = mono_array_new_specific (array_vtable, container->type_argc);
2368 for (i = 0; i < container->type_argc; ++i) {
2369 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2370 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2372 } else if (klass->generic_class) {
2373 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2374 res = mono_array_new_specific (array_vtable, inst->type_argc);
2375 for (i = 0; i < inst->type_argc; ++i)
2376 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2378 res = mono_array_new_specific (array_vtable, 0);
2384 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2387 MONO_ARCH_SAVE_REGS;
2389 if (!IS_MONOTYPE (type))
2392 if (type->type->byref)
2395 klass = mono_class_from_mono_type (type->type);
2397 return klass->generic_container != NULL;
2400 static MonoReflectionType*
2401 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2404 MONO_ARCH_SAVE_REGS;
2406 if (type->type->byref)
2409 klass = mono_class_from_mono_type (type->type);
2410 if (klass->generic_container) {
2411 return type; /* check this one */
2413 if (klass->generic_class) {
2414 MonoClass *generic_class = klass->generic_class->container_class;
2416 if (generic_class->wastypebuilder && generic_class->reflection_info)
2417 return generic_class->reflection_info;
2419 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2424 static MonoReflectionType*
2425 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2427 MonoType *geninst, **types;
2430 MONO_ARCH_SAVE_REGS;
2432 count = mono_array_length (type_array);
2433 types = g_new0 (MonoType *, count);
2435 for (i = 0; i < count; i++) {
2436 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2437 types [i] = t->type;
2440 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2445 return mono_type_get_object (mono_object_domain (type), geninst);
2449 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2452 MONO_ARCH_SAVE_REGS;
2454 if (type->type->byref)
2457 klass = mono_class_from_mono_type (type->type);
2458 return klass->generic_class != NULL;
2462 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2465 MONO_ARCH_SAVE_REGS;
2467 if (!IS_MONOTYPE (type))
2470 if (type->type->byref)
2473 klass = mono_class_from_mono_type (type->type);
2474 return klass->generic_class != NULL || klass->generic_container != NULL;
2478 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2480 MONO_ARCH_SAVE_REGS;
2482 if (!IS_MONOTYPE (type))
2485 if (is_generic_parameter (type->type))
2486 return mono_type_get_generic_param_num (type->type);
2490 static GenericParameterAttributes
2491 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2493 MONO_ARCH_SAVE_REGS;
2495 g_assert (IS_MONOTYPE (type));
2496 g_assert (is_generic_parameter (type->type));
2497 return mono_generic_param_info (type->type->data.generic_param)->flags;
2501 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2503 MonoGenericParamInfo *param_info;
2509 MONO_ARCH_SAVE_REGS;
2511 g_assert (IS_MONOTYPE (type));
2513 domain = mono_object_domain (type);
2514 param_info = mono_generic_param_info (type->type->data.generic_param);
2515 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2518 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2519 for (i = 0; i < count; i++)
2520 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2527 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2529 MONO_ARCH_SAVE_REGS;
2530 return is_generic_parameter (type->type);
2534 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2536 MONO_ARCH_SAVE_REGS;
2537 return is_generic_parameter (tb->type.type);
2541 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2542 MonoReflectionType *t)
2544 enumtype->type = t->type;
2547 static MonoReflectionType*
2548 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2550 MonoDynamicGenericClass *gclass;
2551 MonoReflectionType *parent = NULL, *res;
2557 MONO_ARCH_SAVE_REGS;
2559 g_assert (type->type.type->data.generic_class->is_dynamic);
2560 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2562 domain = mono_object_domain (type);
2563 klass = mono_class_from_mono_type (type->generic_type->type.type);
2565 if (!klass->generic_class && !klass->generic_container)
2568 parent = monotype_cast (type->generic_type->parent);
2570 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2573 inflated = mono_class_inflate_generic_type (
2574 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2576 res = mono_type_get_object (domain, inflated);
2577 mono_metadata_free_type (inflated);
2582 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2584 static MonoClass *System_Reflection_MonoGenericClass;
2585 MonoGenericClass *gclass;
2586 MonoReflectionTypeBuilder *tb = NULL;
2587 MonoClass *klass = NULL;
2592 MONO_ARCH_SAVE_REGS;
2594 if (!System_Reflection_MonoGenericClass) {
2595 System_Reflection_MonoGenericClass = mono_class_from_name (
2596 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2597 g_assert (System_Reflection_MonoGenericClass);
2600 domain = mono_object_domain (type);
2602 gclass = type->type.type->data.generic_class;
2603 g_assert (gclass->is_dynamic);
2605 tb = type->generic_type;
2606 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2608 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2610 for (i = 0; i < icount; i++) {
2611 MonoReflectionType *iface;
2615 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2618 it = &klass->interfaces [i]->byval_arg;
2620 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2622 iface = mono_type_get_object (domain, it);
2623 mono_array_setref (res, i, iface);
2624 mono_metadata_free_type (it);
2630 static MonoReflectionMethod*
2631 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2632 MonoReflectionMethod* generic)
2634 MonoGenericClass *gclass;
2635 MonoDynamicGenericClass *dgclass;
2639 MONO_ARCH_SAVE_REGS;
2641 gclass = type->type.type->data.generic_class;
2642 g_assert (gclass->is_dynamic);
2644 dgclass = (MonoDynamicGenericClass *) gclass;
2646 domain = mono_object_domain (type);
2648 for (i = 0; i < dgclass->count_methods; i++)
2649 if (generic->method->token == dgclass->methods [i]->token)
2650 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2655 static MonoReflectionMethod*
2656 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2657 MonoReflectionMethod* generic)
2659 MonoGenericClass *gclass;
2660 MonoDynamicGenericClass *dgclass;
2664 MONO_ARCH_SAVE_REGS;
2666 gclass = type->type.type->data.generic_class;
2667 g_assert (gclass->is_dynamic);
2669 dgclass = (MonoDynamicGenericClass *) gclass;
2671 domain = mono_object_domain (type);
2673 for (i = 0; i < dgclass->count_ctors; i++)
2674 if (generic->method->token == dgclass->ctors [i]->token)
2675 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2681 static MonoReflectionField*
2682 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2683 MonoString* generic_name)
2685 MonoGenericClass *gclass;
2686 MonoDynamicGenericClass *dgclass;
2688 MonoClass *refclass;
2689 char *utf8_name = mono_string_to_utf8 (generic_name);
2692 MONO_ARCH_SAVE_REGS;
2694 gclass = type->type.type->data.generic_class;
2695 g_assert (gclass->is_dynamic);
2697 dgclass = (MonoDynamicGenericClass *) gclass;
2699 refclass = mono_class_from_mono_type (type->type.type);
2701 domain = mono_object_domain (type);
2703 for (i = 0; i < dgclass->count_fields; i++)
2704 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2706 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2715 static MonoReflectionMethod*
2716 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2717 MonoReflectionMethod* generic)
2724 MONO_ARCH_SAVE_REGS;
2726 domain = ((MonoObject *)type)->vtable->domain;
2728 klass = mono_class_from_mono_type (type->type);
2731 while ((method = mono_class_get_methods (klass, &iter))) {
2732 if (method->token == generic->method->token)
2733 return mono_method_get_object (domain, method, klass);
2740 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2741 MonoReflectionType *reflected_type)
2743 MonoGenericClass *gclass;
2744 MonoDynamicGenericClass *dgclass;
2746 MonoClass *refclass;
2750 MONO_ARCH_SAVE_REGS;
2752 gclass = type->type.type->data.generic_class;
2753 g_assert (gclass->is_dynamic);
2754 dgclass = (MonoDynamicGenericClass *) gclass;
2756 refclass = mono_class_from_mono_type (reflected_type->type);
2758 domain = mono_object_domain (type);
2759 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2761 for (i = 0; i < dgclass->count_methods; i++)
2762 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2768 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2769 MonoReflectionType *reflected_type)
2771 static MonoClass *System_Reflection_ConstructorInfo;
2772 MonoGenericClass *gclass;
2773 MonoDynamicGenericClass *dgclass;
2775 MonoClass *refclass;
2779 MONO_ARCH_SAVE_REGS;
2781 if (!System_Reflection_ConstructorInfo)
2782 System_Reflection_ConstructorInfo = mono_class_from_name (
2783 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2785 gclass = type->type.type->data.generic_class;
2786 g_assert (gclass->is_dynamic);
2787 dgclass = (MonoDynamicGenericClass *) gclass;
2789 refclass = mono_class_from_mono_type (reflected_type->type);
2791 domain = mono_object_domain (type);
2792 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2794 for (i = 0; i < dgclass->count_ctors; i++)
2795 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2801 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2802 MonoReflectionType *reflected_type)
2804 MonoGenericClass *gclass;
2805 MonoDynamicGenericClass *dgclass;
2807 MonoClass *refclass;
2811 MONO_ARCH_SAVE_REGS;
2813 gclass = type->type.type->data.generic_class;
2814 g_assert (gclass->is_dynamic);
2815 dgclass = (MonoDynamicGenericClass *) gclass;
2817 refclass = mono_class_from_mono_type (reflected_type->type);
2819 domain = mono_object_domain (type);
2820 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2822 for (i = 0; i < dgclass->count_fields; i++)
2823 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2829 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2830 MonoReflectionType *reflected_type)
2832 static MonoClass *System_Reflection_PropertyInfo;
2833 MonoGenericClass *gclass;
2834 MonoDynamicGenericClass *dgclass;
2836 MonoClass *refclass;
2840 MONO_ARCH_SAVE_REGS;
2842 if (!System_Reflection_PropertyInfo)
2843 System_Reflection_PropertyInfo = mono_class_from_name (
2844 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2846 gclass = type->type.type->data.generic_class;
2847 g_assert (gclass->is_dynamic);
2848 dgclass = (MonoDynamicGenericClass *) gclass;
2850 refclass = mono_class_from_mono_type (reflected_type->type);
2852 domain = mono_object_domain (type);
2853 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2855 for (i = 0; i < dgclass->count_properties; i++)
2856 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2862 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2863 MonoReflectionType *reflected_type)
2865 static MonoClass *System_Reflection_EventInfo;
2866 MonoGenericClass *gclass;
2867 MonoDynamicGenericClass *dgclass;
2869 MonoClass *refclass;
2873 MONO_ARCH_SAVE_REGS;
2875 if (!System_Reflection_EventInfo)
2876 System_Reflection_EventInfo = mono_class_from_name (
2877 mono_defaults.corlib, "System.Reflection", "EventInfo");
2879 gclass = type->type.type->data.generic_class;
2880 g_assert (gclass->is_dynamic);
2881 dgclass = (MonoDynamicGenericClass *) gclass;
2883 refclass = mono_class_from_mono_type (reflected_type->type);
2885 domain = mono_object_domain (type);
2886 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2888 for (i = 0; i < dgclass->count_events; i++)
2889 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2894 static MonoReflectionType*
2895 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2896 MonoReflectionType *target)
2900 MonoReflectionType *res;
2902 MONO_ARCH_SAVE_REGS;
2904 gklass = mono_class_from_mono_type (type->type.type);
2905 res_type = mono_class_inflate_generic_type (mono_reflection_type_get_handle (target), mono_class_get_context (gklass));
2906 res = mono_type_get_object (mono_object_domain (type), res_type);
2907 mono_metadata_free_type (res_type);
2911 static MonoReflectionMethod *
2912 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2915 MonoType *type = ref_type->type;
2917 MONO_ARCH_SAVE_REGS;
2919 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2920 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2921 if (type->type == MONO_TYPE_VAR)
2924 method = mono_type_get_generic_param_owner (type)->owner.method;
2926 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2929 static MonoReflectionDllImportAttribute*
2930 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2932 static MonoClass *DllImportAttributeClass = NULL;
2933 MonoDomain *domain = mono_domain_get ();
2934 MonoReflectionDllImportAttribute *attr;
2935 MonoImage *image = method->klass->image;
2936 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2937 MonoTableInfo *tables = image->tables;
2938 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2939 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2940 guint32 im_cols [MONO_IMPLMAP_SIZE];
2941 guint32 scope_token;
2942 const char *import = NULL;
2943 const char *scope = NULL;
2946 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2949 if (!DllImportAttributeClass) {
2950 DllImportAttributeClass =
2951 mono_class_from_name (mono_defaults.corlib,
2952 "System.Runtime.InteropServices", "DllImportAttribute");
2953 g_assert (DllImportAttributeClass);
2956 if (method->klass->image->dynamic) {
2957 MonoReflectionMethodAux *method_aux =
2958 g_hash_table_lookup (
2959 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2961 import = method_aux->dllentry;
2962 scope = method_aux->dll;
2966 if (piinfo->implmap_idx) {
2967 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2969 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2970 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2971 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2972 scope = mono_metadata_string_heap (image, scope_token);
2975 flags = piinfo->piflags;
2977 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2979 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2980 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2981 attr->call_conv = (flags & 0x700) >> 8;
2982 attr->charset = ((flags & 0x6) >> 1) + 1;
2983 if (attr->charset == 1)
2985 attr->exact_spelling = (flags & 0x1) != 0;
2986 attr->set_last_error = (flags & 0x40) != 0;
2987 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2988 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2989 attr->preserve_sig = FALSE;
2994 static MonoReflectionMethod *
2995 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2997 MonoMethodInflated *imethod;
3000 MONO_ARCH_SAVE_REGS;
3002 if (method->method->is_generic)
3005 if (!method->method->is_inflated)
3008 imethod = (MonoMethodInflated *) method->method;
3010 result = imethod->declaring;
3011 /* Not a generic method. */
3012 if (!result->is_generic)
3015 if (method->method->klass->image->dynamic) {
3016 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
3017 MonoReflectionMethod *res;
3020 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
3021 * the dynamic case as well ?
3023 mono_loader_lock ();
3024 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
3025 mono_loader_unlock ();
3031 if (imethod->context.class_inst) {
3032 MonoClass *klass = ((MonoMethod *) imethod)->klass;
3033 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
3036 return mono_method_get_object (mono_object_domain (method), result, NULL);
3040 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3042 MONO_ARCH_SAVE_REGS;
3044 return mono_method_signature (method->method)->generic_param_count != 0;
3048 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3050 MONO_ARCH_SAVE_REGS;
3052 return method->method->is_generic;
3056 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3061 MONO_ARCH_SAVE_REGS;
3063 domain = mono_object_domain (method);
3065 if (method->method->is_inflated) {
3066 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3069 count = inst->type_argc;
3070 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3072 for (i = 0; i < count; i++)
3073 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
3079 count = mono_method_signature (method->method)->generic_param_count;
3080 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3082 for (i = 0; i < count; i++) {
3083 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3084 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3085 MonoClass *pklass = mono_class_from_generic_parameter (
3086 param, method->method->klass->image, TRUE);
3087 mono_array_setref (res, i,
3088 mono_type_get_object (domain, &pklass->byval_arg));
3095 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
3098 * Invoke from reflection is supposed to always be a virtual call (the API
3099 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3100 * greater flexibility.
3102 MonoMethod *m = method->method;
3106 MONO_ARCH_SAVE_REGS;
3110 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
3111 mono_security_core_clr_ensure_reflection_access_method (m);
3113 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3115 if (!mono_object_isinst (this, m->klass)) {
3116 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
3119 m = mono_object_get_virtual_method (this, m);
3120 /* must pass the pointer to the value for valuetype methods */
3121 if (m->klass->valuetype)
3122 obj = mono_object_unbox (this);
3123 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3124 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
3129 pcount = params? mono_array_length (params): 0;
3130 if (pcount != mono_method_signature (m)->param_count) {
3131 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
3135 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3136 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."));
3140 if (m->klass->image->assembly->ref_only) {
3141 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."));
3145 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3147 mono_array_size_t *lengths;
3148 mono_array_size_t *lower_bounds;
3149 pcount = mono_array_length (params);
3150 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3151 for (i = 0; i < pcount; ++i)
3152 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3154 if (m->klass->rank == pcount) {
3155 /* Only lengths provided. */
3156 lower_bounds = NULL;
3158 g_assert (pcount == (m->klass->rank * 2));
3159 /* lower bounds are first. */
3160 lower_bounds = lengths;
3161 lengths += m->klass->rank;
3164 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3166 return mono_runtime_invoke_array (m, obj, params, NULL);
3170 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3172 MonoDomain *domain = mono_object_domain (method);
3173 MonoMethod *m = method->method;
3174 MonoMethodSignature *sig = mono_method_signature (m);
3175 MonoArray *out_args;
3177 int i, j, outarg_count = 0;
3179 MONO_ARCH_SAVE_REGS;
3181 if (m->klass == mono_defaults.object_class) {
3183 if (!strcmp (m->name, "FieldGetter")) {
3184 MonoClass *k = this->vtable->klass;
3188 /* If this is a proxy, then it must be a CBO */
3189 if (k == mono_defaults.transparent_proxy_class) {
3190 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3191 this = tp->rp->unwrapped_server;
3193 k = this->vtable->klass;
3196 name = mono_array_get (params, MonoString *, 1);
3197 str = mono_string_to_utf8 (name);
3200 MonoClassField* field = mono_class_get_field_from_name (k, str);
3202 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3203 if (field_klass->valuetype)
3204 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3206 result = *((gpointer *)((char *)this + field->offset));
3208 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3209 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3210 mono_array_setref (out_args, 0, result);
3218 g_assert_not_reached ();
3220 } else if (!strcmp (m->name, "FieldSetter")) {
3221 MonoClass *k = this->vtable->klass;
3227 /* If this is a proxy, then it must be a CBO */
3228 if (k == mono_defaults.transparent_proxy_class) {
3229 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3230 this = tp->rp->unwrapped_server;
3232 k = this->vtable->klass;
3235 name = mono_array_get (params, MonoString *, 1);
3236 str = mono_string_to_utf8 (name);
3239 MonoClassField* field = mono_class_get_field_from_name (k, str);
3241 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3242 MonoObject *val = mono_array_get (params, gpointer, 2);
3244 if (field_klass->valuetype) {
3245 size = mono_type_size (field->type, &align);
3247 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3249 memcpy ((char *)this + field->offset,
3250 ((char *)val) + sizeof (MonoObject), size);
3252 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3255 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3256 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3266 g_assert_not_reached ();
3271 for (i = 0; i < mono_array_length (params); i++) {
3272 if (sig->params [i]->byref)
3276 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3278 /* handle constructors only for objects already allocated */
3279 if (!strcmp (method->method->name, ".ctor"))
3282 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3283 g_assert (!method->method->klass->valuetype);
3284 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3286 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3287 if (sig->params [i]->byref) {
3289 arg = mono_array_get (params, gpointer, i);
3290 mono_array_setref (out_args, j, arg);
3295 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3301 read_enum_value (char *mem, int type)
3305 return *(guint8*)mem;
3307 return *(gint8*)mem;
3309 return *(guint16*)mem;
3311 return *(gint16*)mem;
3313 return *(guint32*)mem;
3315 return *(gint32*)mem;
3317 return *(guint64*)mem;
3319 return *(gint64*)mem;
3321 g_assert_not_reached ();
3327 write_enum_value (char *mem, int type, guint64 value)
3331 case MONO_TYPE_I1: {
3332 guint8 *p = (guint8*)mem;
3337 case MONO_TYPE_I2: {
3338 guint16 *p = (void*)mem;
3343 case MONO_TYPE_I4: {
3344 guint32 *p = (void*)mem;
3349 case MONO_TYPE_I8: {
3350 guint64 *p = (void*)mem;
3355 g_assert_not_reached ();
3361 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3364 MonoClass *enumc, *objc;
3368 MONO_ARCH_SAVE_REGS;
3370 MONO_CHECK_ARG_NULL (enumType);
3371 MONO_CHECK_ARG_NULL (value);
3373 domain = mono_object_domain (enumType);
3374 enumc = mono_class_from_mono_type (enumType->type);
3375 objc = value->vtable->klass;
3377 if (!enumc->enumtype)
3378 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3379 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3380 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."));
3382 res = mono_object_new (domain, enumc);
3383 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3384 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3390 ves_icall_System_Enum_get_value (MonoObject *this)
3398 MONO_ARCH_SAVE_REGS;
3403 g_assert (this->vtable->klass->enumtype);
3405 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3406 res = mono_object_new (mono_object_domain (this), enumc);
3407 dst = (char *)res + sizeof (MonoObject);
3408 src = (char *)this + sizeof (MonoObject);
3409 size = mono_class_value_size (enumc, NULL);
3411 memcpy (dst, src, size);
3416 static MonoReflectionType *
3417 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3419 MONO_ARCH_SAVE_REGS;
3421 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3425 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3427 gpointer tdata = (char *)this + sizeof (MonoObject);
3428 gpointer odata = (char *)other + sizeof (MonoObject);
3429 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3430 g_assert (basetype);
3432 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3433 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3434 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3437 return me > other ? 1 : -1; \
3440 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3441 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3442 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3445 return me - other; \
3448 switch (basetype->type) {
3450 COMPARE_ENUM_VALUES (guint8);
3452 COMPARE_ENUM_VALUES (gint8);
3453 case MONO_TYPE_CHAR:
3455 COMPARE_ENUM_VALUES_RANGE (guint16);
3457 COMPARE_ENUM_VALUES (gint16);
3459 COMPARE_ENUM_VALUES (guint32);
3461 COMPARE_ENUM_VALUES (gint32);
3463 COMPARE_ENUM_VALUES (guint64);
3465 COMPARE_ENUM_VALUES (gint64);
3467 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3469 #undef COMPARE_ENUM_VALUES_RANGE
3470 #undef COMPARE_ENUM_VALUES
3475 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3477 gpointer data = (char *)this + sizeof (MonoObject);
3478 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3479 g_assert (basetype);
3481 switch (basetype->type) {
3483 return *((gint8*)data);
3485 return *((guint8*)data);
3486 case MONO_TYPE_CHAR:
3488 return *((guint16*)data);
3491 return *((gint16*)data);
3493 return *((guint32*)data);
3495 return *((gint32*)data);
3497 case MONO_TYPE_I8: {
3498 gint64 value = *((gint64*)data);
3499 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3502 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3508 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3510 MonoDomain *domain = mono_object_domain (type);
3511 MonoClass *enumc = mono_class_from_mono_type (type->type);
3512 guint j = 0, nvalues, crow;
3514 MonoClassField *field;
3516 MONO_ARCH_SAVE_REGS;
3518 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3519 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3520 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3521 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3525 while ((field = mono_class_get_fields (enumc, &iter))) {
3528 MonoTypeEnum def_type;
3530 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3532 if (mono_field_is_deleted (field))
3534 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3536 p = mono_class_get_field_default_value (field, &def_type);
3537 len = mono_metadata_decode_blob_size (p, &p);
3538 switch (mono_class_enum_basetype (enumc)->type) {
3541 mono_array_set (info->values, gchar, j, *p);
3543 case MONO_TYPE_CHAR:
3546 mono_array_set (info->values, gint16, j, read16 (p));
3550 mono_array_set (info->values, gint32, j, read32 (p));
3554 mono_array_set (info->values, gint64, j, read64 (p));
3557 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3564 BFLAGS_IgnoreCase = 1,
3565 BFLAGS_DeclaredOnly = 2,
3566 BFLAGS_Instance = 4,
3568 BFLAGS_Public = 0x10,
3569 BFLAGS_NonPublic = 0x20,
3570 BFLAGS_FlattenHierarchy = 0x40,
3571 BFLAGS_InvokeMethod = 0x100,
3572 BFLAGS_CreateInstance = 0x200,
3573 BFLAGS_GetField = 0x400,
3574 BFLAGS_SetField = 0x800,
3575 BFLAGS_GetProperty = 0x1000,
3576 BFLAGS_SetProperty = 0x2000,
3577 BFLAGS_ExactBinding = 0x10000,
3578 BFLAGS_SuppressChangeType = 0x20000,
3579 BFLAGS_OptionalParamBinding = 0x40000
3582 static MonoReflectionField *
3583 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3586 MonoClass *startklass, *klass;
3588 MonoClassField *field;
3591 int (*compare_func) (const char *s1, const char *s2) = NULL;
3592 domain = ((MonoObject *)type)->vtable->domain;
3593 klass = startklass = mono_class_from_mono_type (type->type);
3595 MONO_ARCH_SAVE_REGS;
3598 mono_raise_exception (mono_get_exception_argument_null ("name"));
3599 if (type->type->byref)
3602 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3605 if (klass->exception_type != MONO_EXCEPTION_NONE)
3606 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3609 while ((field = mono_class_get_fields (klass, &iter))) {
3612 if (field->type == NULL)
3614 if (mono_field_is_deleted (field))
3616 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3617 if (bflags & BFLAGS_Public)
3619 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3620 if (bflags & BFLAGS_NonPublic) {
3627 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3628 if (bflags & BFLAGS_Static)
3629 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3632 if (bflags & BFLAGS_Instance)
3639 utf8_name = mono_string_to_utf8 (name);
3641 if (compare_func (mono_field_get_name (field), utf8_name)) {
3647 return mono_field_get_object (domain, klass, field);
3649 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3656 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3659 MonoClass *startklass, *klass, *refklass;
3664 MonoClassField *field;
3665 MonoPtrArray tmp_array;
3667 MONO_ARCH_SAVE_REGS;
3669 domain = ((MonoObject *)type)->vtable->domain;
3670 if (type->type->byref)
3671 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3672 klass = startklass = mono_class_from_mono_type (type->type);
3673 refklass = mono_class_from_mono_type (reftype->type);
3675 mono_ptr_array_init (tmp_array, 2);
3678 if (klass->exception_type != MONO_EXCEPTION_NONE)
3679 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3682 while ((field = mono_class_get_fields (klass, &iter))) {
3684 if (mono_field_is_deleted (field))
3686 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3687 if (bflags & BFLAGS_Public)
3689 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3690 if (bflags & BFLAGS_NonPublic) {
3697 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3698 if (bflags & BFLAGS_Static)
3699 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3702 if (bflags & BFLAGS_Instance)
3708 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3709 mono_ptr_array_append (tmp_array, member);
3711 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3714 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3716 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3717 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3719 mono_ptr_array_destroy (tmp_array);
3725 method_nonpublic (MonoMethod* method, gboolean start_klass)
3727 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3728 case METHOD_ATTRIBUTE_ASSEM:
3729 return (start_klass || mono_defaults.generic_ilist_class);
3730 case METHOD_ATTRIBUTE_PRIVATE:
3732 case METHOD_ATTRIBUTE_PUBLIC:
3740 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3742 static MonoClass *MethodInfo_array;
3744 MonoClass *startklass, *klass, *refklass;
3749 int i, len, match, nslots;
3750 /*FIXME, use MonoBitSet*/
3751 guint32 method_slots_default [8];
3752 guint32 *method_slots = NULL;
3753 gchar *mname = NULL;
3754 int (*compare_func) (const char *s1, const char *s2) = NULL;
3755 MonoVTable *array_vtable;
3757 MonoPtrArray tmp_array;
3759 MONO_ARCH_SAVE_REGS;
3761 mono_ptr_array_init (tmp_array, 4);
3763 if (!MethodInfo_array) {
3764 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3765 mono_memory_barrier ();
3766 MethodInfo_array = klass;
3769 domain = ((MonoObject *)type)->vtable->domain;
3770 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3771 if (type->type->byref)
3772 return mono_array_new_specific (array_vtable, 0);
3773 klass = startklass = mono_class_from_mono_type (type->type);
3774 refklass = mono_class_from_mono_type (reftype->type);
3777 mname = mono_string_to_utf8 (name);
3778 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3781 /* An optimization for calls made from Delegate:CreateDelegate () */
3782 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3783 method = mono_get_delegate_invoke (klass);
3784 if (mono_loader_get_last_error ())
3787 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3789 res = mono_array_new_specific (array_vtable, 1);
3790 mono_array_setref (res, 0, member);
3795 mono_class_setup_vtable (klass);
3796 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3799 if (is_generic_parameter (type->type))
3800 nslots = mono_class_get_vtable_size (klass->parent);
3802 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3803 if (nslots >= sizeof (method_slots_default) * 8) {
3804 method_slots = g_new0 (guint32, nslots / 32 + 1);
3806 method_slots = method_slots_default;
3807 memset (method_slots, 0, sizeof (method_slots_default));
3810 mono_class_setup_vtable (klass);
3811 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3815 while ((method = mono_class_get_methods (klass, &iter))) {
3817 if (method->slot != -1) {
3818 g_assert (method->slot < nslots);
3819 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3821 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3824 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3826 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3827 if (bflags & BFLAGS_Public)
3829 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3835 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3836 if (bflags & BFLAGS_Static)
3837 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3840 if (bflags & BFLAGS_Instance)
3848 if (compare_func (mname, method->name))
3854 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3856 mono_ptr_array_append (tmp_array, member);
3858 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3862 if (method_slots != method_slots_default)
3863 g_free (method_slots);
3865 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3867 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3868 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3870 mono_ptr_array_destroy (tmp_array);
3875 if (method_slots != method_slots_default)
3876 g_free (method_slots);
3877 mono_ptr_array_destroy (tmp_array);
3878 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3879 ex = mono_class_get_exception_for_failure (klass);
3881 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3882 mono_loader_clear_error ();
3884 mono_raise_exception (ex);
3889 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3892 static MonoClass *System_Reflection_ConstructorInfo;
3893 MonoClass *startklass, *klass, *refklass;
3898 gpointer iter = NULL;
3899 MonoPtrArray tmp_array;
3901 MONO_ARCH_SAVE_REGS;
3903 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3905 domain = ((MonoObject *)type)->vtable->domain;
3906 if (type->type->byref)
3907 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3908 klass = startklass = mono_class_from_mono_type (type->type);
3909 refklass = mono_class_from_mono_type (reftype->type);
3911 if (klass->exception_type != MONO_EXCEPTION_NONE)
3912 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3914 if (!System_Reflection_ConstructorInfo)
3915 System_Reflection_ConstructorInfo = mono_class_from_name (
3916 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3919 while ((method = mono_class_get_methods (klass, &iter))) {
3921 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3923 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3924 if (bflags & BFLAGS_Public)
3927 if (bflags & BFLAGS_NonPublic)
3933 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3934 if (bflags & BFLAGS_Static)
3935 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3938 if (bflags & BFLAGS_Instance)
3944 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3946 mono_ptr_array_append (tmp_array, member);
3949 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3951 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3952 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3954 mono_ptr_array_destroy (tmp_array);
3960 property_hash (gconstpointer data)
3962 MonoProperty *prop = (MonoProperty*)data;
3964 return g_str_hash (prop->name);
3968 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3970 // Properties are hide-by-name-and-signature
3971 if (!g_str_equal (prop1->name, prop2->name))
3974 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3976 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3982 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3987 return method_nonpublic (accessor, start_klass);
3991 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3994 static MonoClass *System_Reflection_PropertyInfo;
3995 MonoClass *startklass, *klass;
4001 gchar *propname = NULL;
4002 int (*compare_func) (const char *s1, const char *s2) = NULL;
4004 GHashTable *properties;
4005 MonoPtrArray tmp_array;
4007 MONO_ARCH_SAVE_REGS;
4009 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
4011 if (!System_Reflection_PropertyInfo)
4012 System_Reflection_PropertyInfo = mono_class_from_name (
4013 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
4015 domain = ((MonoObject *)type)->vtable->domain;
4016 if (type->type->byref)
4017 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
4018 klass = startklass = mono_class_from_mono_type (type->type);
4020 propname = mono_string_to_utf8 (name);
4021 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
4024 mono_class_setup_vtable (klass);
4026 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
4028 mono_class_setup_vtable (klass);
4029 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4030 g_hash_table_destroy (properties);
4033 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4037 while ((prop = mono_class_get_properties (klass, &iter))) {
4043 flags = method->flags;
4046 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
4047 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
4048 if (bflags & BFLAGS_Public)
4050 } else if (bflags & BFLAGS_NonPublic) {
4051 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
4052 property_accessor_nonpublic(prop->set, startklass == klass)) {
4059 if (flags & METHOD_ATTRIBUTE_STATIC) {
4060 if (bflags & BFLAGS_Static)
4061 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4064 if (bflags & BFLAGS_Instance)
4073 if (compare_func (propname, prop->name))
4077 if (g_hash_table_lookup (properties, prop))
4080 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4082 g_hash_table_insert (properties, prop, prop);
4084 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4087 g_hash_table_destroy (properties);
4090 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4091 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4092 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4094 mono_ptr_array_destroy (tmp_array);
4099 static MonoReflectionEvent *
4100 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
4103 MonoClass *klass, *startklass;
4109 MONO_ARCH_SAVE_REGS;
4111 event_name = mono_string_to_utf8 (name);
4112 if (type->type->byref)
4114 klass = startklass = mono_class_from_mono_type (type->type);
4115 domain = mono_object_domain (type);
4118 if (klass->exception_type != MONO_EXCEPTION_NONE)
4119 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4122 while ((event = mono_class_get_events (klass, &iter))) {
4123 if (strcmp (event->name, event_name))
4126 method = event->add;
4128 method = event->remove;
4130 method = event->raise;
4132 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4133 if (!(bflags & BFLAGS_Public))
4136 if (!(bflags & BFLAGS_NonPublic))
4138 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4142 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4143 if (!(bflags & BFLAGS_Static))
4145 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4148 if (!(bflags & BFLAGS_Instance))
4152 if (!(bflags & BFLAGS_NonPublic))
4155 g_free (event_name);
4156 return mono_event_get_object (domain, startklass, event);
4159 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4162 g_free (event_name);
4167 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4170 static MonoClass *System_Reflection_EventInfo;
4171 MonoClass *startklass, *klass;
4178 MonoPtrArray tmp_array;
4180 MONO_ARCH_SAVE_REGS;
4182 mono_ptr_array_init (tmp_array, 4);
4184 if (!System_Reflection_EventInfo)
4185 System_Reflection_EventInfo = mono_class_from_name (
4186 mono_defaults.corlib, "System.Reflection", "EventInfo");
4188 domain = mono_object_domain (type);
4189 if (type->type->byref)
4190 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4191 klass = startklass = mono_class_from_mono_type (type->type);
4194 if (klass->exception_type != MONO_EXCEPTION_NONE)
4195 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4198 while ((event = mono_class_get_events (klass, &iter))) {
4200 method = event->add;
4202 method = event->remove;
4204 method = event->raise;
4206 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4207 if (bflags & BFLAGS_Public)
4209 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4210 if (bflags & BFLAGS_NonPublic)
4215 if (bflags & BFLAGS_NonPublic)
4221 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4222 if (bflags & BFLAGS_Static)
4223 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4226 if (bflags & BFLAGS_Instance)
4231 if (bflags & BFLAGS_Instance)
4235 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4237 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4240 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4242 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4243 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4245 mono_ptr_array_destroy (tmp_array);
4250 static MonoReflectionType *
4251 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4259 MONO_ARCH_SAVE_REGS;
4262 mono_raise_exception (mono_get_exception_argument_null ("name"));
4264 domain = ((MonoObject *)type)->vtable->domain;
4265 if (type->type->byref)
4267 klass = mono_class_from_mono_type (type->type);
4268 str = mono_string_to_utf8 (name);
4271 if (klass->exception_type != MONO_EXCEPTION_NONE)
4272 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4275 * If a nested type is generic, return its generic type definition.
4276 * Note that this means that the return value is essentially a
4277 * nested type of the generic type definition of @klass.
4279 * A note in MSDN claims that a generic type definition can have
4280 * nested types that aren't generic. In any case, the container of that
4281 * nested type would be the generic type definition.
4283 if (klass->generic_class)
4284 klass = klass->generic_class->container_class;
4287 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4289 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4290 if (bflags & BFLAGS_Public)
4293 if (bflags & BFLAGS_NonPublic)
4298 if (strcmp (nested->name, str) == 0){
4300 return mono_type_get_object (domain, &nested->byval_arg);
4303 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4310 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4319 MonoPtrArray tmp_array;
4321 MONO_ARCH_SAVE_REGS;
4323 domain = ((MonoObject *)type)->vtable->domain;
4324 if (type->type->byref)
4325 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4326 klass = mono_class_from_mono_type (type->type);
4327 if (klass->exception_type != MONO_EXCEPTION_NONE)
4328 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4331 * If a nested type is generic, return its generic type definition.
4332 * Note that this means that the return value is essentially the set
4333 * of nested types of the generic type definition of @klass.
4335 * A note in MSDN claims that a generic type definition can have
4336 * nested types that aren't generic. In any case, the container of that
4337 * nested type would be the generic type definition.
4339 if (klass->generic_class)
4340 klass = klass->generic_class->container_class;
4342 mono_ptr_array_init (tmp_array, 1);
4344 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4346 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4347 if (bflags & BFLAGS_Public)
4350 if (bflags & BFLAGS_NonPublic)
4355 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4356 mono_ptr_array_append (tmp_array, member);
4359 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4361 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4362 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4364 mono_ptr_array_destroy (tmp_array);
4369 static MonoReflectionType*
4370 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4373 MonoType *type = NULL;
4374 MonoTypeNameParse info;
4375 gboolean type_resolve;
4377 MONO_ARCH_SAVE_REGS;
4379 /* On MS.NET, this does not fire a TypeResolve event */
4380 type_resolve = TRUE;
4381 str = mono_string_to_utf8 (name);
4382 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4383 if (!mono_reflection_parse_type (str, &info)) {
4385 mono_reflection_free_type_info (&info);
4386 if (throwOnError) /* uhm: this is a parse error, though... */
4387 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4388 /*g_print ("failed parse\n");*/
4392 if (info.assembly.name) {
4394 mono_reflection_free_type_info (&info);
4396 /* 1.0 and 2.0 throw different exceptions */
4397 if (mono_defaults.generic_ilist_class)
4398 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4400 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4405 if (module != NULL) {
4407 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4412 if (assembly->assembly->dynamic) {
4413 /* Enumerate all modules */
4414 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4418 if (abuilder->modules) {
4419 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4420 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4421 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4427 if (!type && abuilder->loaded_modules) {
4428 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4429 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4430 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4437 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4439 mono_reflection_free_type_info (&info);
4441 MonoException *e = NULL;
4444 e = mono_get_exception_type_load (name, NULL);
4446 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4447 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4449 mono_loader_clear_error ();
4452 mono_raise_exception (e);
4457 if (type->type == MONO_TYPE_CLASS) {
4458 MonoClass *klass = mono_type_get_class (type);
4460 if (mono_is_security_manager_active () && !klass->exception_type)
4461 /* Some security problems are detected during generic vtable construction */
4462 mono_class_setup_vtable (klass);
4463 /* need to report exceptions ? */
4464 if (throwOnError && klass->exception_type) {
4465 /* report SecurityException (or others) that occured when loading the assembly */
4466 MonoException *exc = mono_class_get_exception_for_failure (klass);
4467 mono_loader_clear_error ();
4468 mono_raise_exception (exc);
4469 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4474 /* g_print ("got it\n"); */
4475 return mono_type_get_object (mono_object_domain (assembly), type);
4479 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4482 gchar *shadow_ini_file;
4485 /* Check for shadow-copied assembly */
4486 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4487 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4489 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4490 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4496 g_free (shadow_ini_file);
4497 if (content != NULL) {
4500 *filename = content;
4508 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4510 MonoDomain *domain = mono_object_domain (assembly);
4511 MonoAssembly *mass = assembly->assembly;
4512 MonoString *res = NULL;
4517 MONO_ARCH_SAVE_REGS;
4519 if (g_path_is_absolute (mass->image->name)) {
4520 absolute = g_strdup (mass->image->name);
4521 dirname = g_path_get_dirname (absolute);
4523 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4524 dirname = g_strdup (mass->basedir);
4527 replace_shadow_path (domain, dirname, &absolute);
4532 for (i = strlen (absolute) - 1; i >= 0; i--)
4533 if (absolute [i] == '\\')
4538 uri = g_filename_to_uri (absolute, NULL, NULL);
4540 const char *prepend = "file://";
4542 if (*absolute == '/' && *(absolute + 1) == '/') {
4545 prepend = "file:///";
4548 uri = g_strconcat (prepend, absolute, NULL);
4552 res = mono_string_new (domain, uri);
4560 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4562 MonoAssembly *mass = assembly->assembly;
4564 MONO_ARCH_SAVE_REGS;
4566 return mass->in_gac;
4569 static MonoReflectionAssembly*
4570 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4574 MonoImageOpenStatus status;
4576 MONO_ARCH_SAVE_REGS;
4578 name = mono_string_to_utf8 (mname);
4579 res = mono_assembly_load_with_partial_name (name, &status);
4585 return mono_assembly_get_object (mono_domain_get (), res);
4589 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4591 MonoDomain *domain = mono_object_domain (assembly);
4594 MONO_ARCH_SAVE_REGS;
4596 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4602 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4604 MONO_ARCH_SAVE_REGS;
4606 return assembly->assembly->ref_only;
4610 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4612 MonoDomain *domain = mono_object_domain (assembly);
4614 MONO_ARCH_SAVE_REGS;
4616 return mono_string_new (domain, assembly->assembly->image->version);
4619 static MonoReflectionMethod*
4620 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4622 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4624 MONO_ARCH_SAVE_REGS;
4628 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4631 static MonoReflectionModule*
4632 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4634 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4638 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4640 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4641 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4645 MONO_ARCH_SAVE_REGS;
4647 for (i = 0; i < table->rows; ++i) {
4648 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4649 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4655 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4657 static MonoClass *System_Version = NULL;
4658 static MonoMethod *create_version = NULL;
4662 if (!System_Version) {
4663 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4664 g_assert (System_Version);
4667 if (!create_version) {
4668 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4669 create_version = mono_method_desc_search_in_class (desc, System_Version);
4670 g_assert (create_version);
4671 mono_method_desc_free (desc);
4677 args [3] = &revision;
4678 result = mono_object_new (domain, System_Version);
4679 mono_runtime_invoke (create_version, result, args, NULL);
4685 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4687 static MonoClass *System_Reflection_AssemblyName;
4689 MonoDomain *domain = mono_object_domain (assembly);
4691 static MonoMethod *create_culture = NULL;
4692 MonoImage *image = assembly->assembly->image;
4695 MONO_ARCH_SAVE_REGS;
4697 if (!System_Reflection_AssemblyName)
4698 System_Reflection_AssemblyName = mono_class_from_name (
4699 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4701 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4704 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4706 if (count > 0 && !create_culture) {
4707 MonoMethodDesc *desc = mono_method_desc_new (
4708 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4709 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4710 g_assert (create_culture);
4711 mono_method_desc_free (desc);
4714 for (i = 0; i < count; i++) {
4715 MonoReflectionAssemblyName *aname;
4716 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4718 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4720 aname = (MonoReflectionAssemblyName *) mono_object_new (
4721 domain, System_Reflection_AssemblyName);
4723 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4725 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4726 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4727 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4728 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4729 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4730 aname->versioncompat = 1; /* SameMachine (default) */
4731 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4732 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4734 if (create_culture) {
4736 MonoBoolean assembly_ref = 1;
4737 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4738 args [1] = &assembly_ref;
4739 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4742 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4743 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4744 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4746 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4747 /* public key token isn't copied - the class library will
4748 automatically generate it from the public key if required */
4749 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4750 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4752 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4753 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4756 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4759 /* note: this function doesn't return the codebase on purpose (i.e. it can
4760 be used under partial trust as path information isn't present). */
4762 mono_array_setref (result, i, aname);
4773 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4775 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4777 mono_array_setref (info->res, info->idx, name);
4782 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4784 MonoImage *img = assembly->assembly->image;
4789 MONO_ARCH_SAVE_REGS;
4791 mono_image_lock (img);
4792 mono_image_init_name_cache (img);
4795 len = g_hash_table_size (img->name_cache);
4796 mono_image_unlock (img);
4798 /*we can't create objects holding the image lock */
4799 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4801 mono_image_lock (img);
4802 /*len might have changed, create a new array*/
4803 if (len != g_hash_table_size (img->name_cache))
4808 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4809 mono_image_unlock (img);
4814 /* move this in some file in mono/util/ */
4816 g_concat_dir_and_file (const char *dir, const char *file)
4818 g_return_val_if_fail (dir != NULL, NULL);
4819 g_return_val_if_fail (file != NULL, NULL);
4822 * If the directory name doesn't have a / on the end, we need
4823 * to add one so we get a proper path to the file
4825 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4826 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4828 return g_strconcat (dir, file, NULL);
4832 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4834 char *n = mono_string_to_utf8 (name);
4835 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4837 guint32 cols [MONO_MANIFEST_SIZE];
4838 guint32 impl, file_idx;
4842 MONO_ARCH_SAVE_REGS;
4844 for (i = 0; i < table->rows; ++i) {
4845 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4846 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4847 if (strcmp (val, n) == 0)
4851 if (i == table->rows)
4854 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4857 * this code should only be called after obtaining the
4858 * ResourceInfo and handling the other cases.
4860 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4861 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4863 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4868 module = assembly->assembly->image;
4870 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4872 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4876 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4878 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4880 guint32 cols [MONO_MANIFEST_SIZE];
4881 guint32 file_cols [MONO_FILE_SIZE];
4885 MONO_ARCH_SAVE_REGS;
4887 n = mono_string_to_utf8 (name);
4888 for (i = 0; i < table->rows; ++i) {
4889 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4890 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4891 if (strcmp (val, n) == 0)
4895 if (i == table->rows)
4898 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4899 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4902 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4903 case MONO_IMPLEMENTATION_FILE:
4904 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4905 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4906 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4907 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4908 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4909 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4912 info->location = RESOURCE_LOCATION_EMBEDDED;
4915 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4916 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4917 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4918 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4919 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4920 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4922 mono_raise_exception (ex);
4924 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4926 /* Obtain info recursively */
4927 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4928 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4931 case MONO_IMPLEMENTATION_EXP_TYPE:
4932 g_assert_not_reached ();
4941 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4943 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4944 MonoArray *result = NULL;
4949 MONO_ARCH_SAVE_REGS;
4951 /* check hash if needed */
4953 n = mono_string_to_utf8 (name);
4954 for (i = 0; i < table->rows; ++i) {
4955 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4956 if (strcmp (val, n) == 0) {
4959 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4960 fn = mono_string_new (mono_object_domain (assembly), n);
4962 return (MonoObject*)fn;
4970 for (i = 0; i < table->rows; ++i) {
4971 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4975 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4978 for (i = 0; i < table->rows; ++i) {
4979 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4980 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4981 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4982 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4987 return (MonoObject*)result;
4991 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4993 MonoDomain *domain = mono_domain_get();
4996 int i, j, file_count = 0;
4997 MonoImage **modules;
4998 guint32 module_count, real_module_count;
4999 MonoTableInfo *table;
5000 guint32 cols [MONO_FILE_SIZE];
5001 MonoImage *image = assembly->assembly->image;
5003 g_assert (image != NULL);
5004 g_assert (!assembly->assembly->dynamic);
5006 table = &image->tables [MONO_TABLE_FILE];
5007 file_count = table->rows;
5009 modules = image->modules;
5010 module_count = image->module_count;
5012 real_module_count = 0;
5013 for (i = 0; i < module_count; ++i)
5015 real_module_count ++;
5017 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
5018 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
5020 mono_array_setref (res, 0, mono_module_get_object (domain, image));
5022 for (i = 0; i < module_count; ++i)
5024 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
5028 for (i = 0; i < file_count; ++i, ++j) {
5029 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
5030 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
5031 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
5033 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
5035 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
5036 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
5038 mono_array_setref (res, j, mono_module_get_object (domain, m));
5045 static MonoReflectionMethod*
5046 ves_icall_GetCurrentMethod (void)
5048 MonoMethod *m = mono_method_get_last_managed ();
5050 MONO_ARCH_SAVE_REGS;
5052 return mono_method_get_object (mono_domain_get (), m, NULL);
5057 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
5060 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
5061 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
5062 //method is inflated, we should inflate it on the other class
5063 MonoGenericContext ctx;
5064 ctx.method_inst = inflated->context.method_inst;
5065 ctx.class_inst = inflated->context.class_inst;
5066 if (klass->generic_class)
5067 ctx.class_inst = klass->generic_class->context.class_inst;
5068 else if (klass->generic_container)
5069 ctx.class_inst = klass->generic_container->context.class_inst;
5070 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
5073 mono_class_setup_methods (method->klass);
5074 for (i = 0; i < method->klass->method.count; ++i) {
5075 if (method->klass->methods [i] == method) {
5080 mono_class_setup_methods (klass);
5081 g_assert (offset >= 0 && offset < klass->method.count);
5082 return klass->methods [offset];
5085 static MonoReflectionMethod*
5086 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5090 klass = mono_class_from_mono_type (type);
5091 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5093 if (method->klass != klass)
5094 method = mono_method_get_equivalent_method (method, klass);
5096 klass = method->klass;
5097 return mono_method_get_object (mono_domain_get (), method, klass);
5100 static MonoReflectionMethod*
5101 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
5103 return mono_method_get_object (mono_domain_get (), method, NULL);
5106 static MonoReflectionMethodBody*
5107 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5109 return mono_method_body_get_object (mono_domain_get (), method);
5112 static MonoReflectionAssembly*
5113 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5115 MonoMethod *dest = NULL;
5117 MONO_ARCH_SAVE_REGS;
5119 mono_stack_walk_no_il (get_executing, &dest);
5120 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5124 static MonoReflectionAssembly*
5125 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5127 MonoDomain* domain = mono_domain_get ();
5129 MONO_ARCH_SAVE_REGS;
5131 if (!domain->entry_assembly)
5134 return mono_assembly_get_object (domain, domain->entry_assembly);
5137 static MonoReflectionAssembly*
5138 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5143 MONO_ARCH_SAVE_REGS;
5146 mono_stack_walk_no_il (get_executing, &dest);
5148 mono_stack_walk_no_il (get_caller, &dest);
5151 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5155 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5156 gboolean assembly_qualified)
5158 MonoDomain *domain = mono_object_domain (object);
5159 MonoTypeNameFormat format;
5163 MONO_ARCH_SAVE_REGS;
5165 format = assembly_qualified ?
5166 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5167 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5169 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5171 name = mono_type_get_name_full (object->type, format);
5175 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5180 res = mono_string_new (domain, name);
5187 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5189 static MonoMethod *create_culture = NULL;
5192 const char *pkey_ptr;
5194 MonoBoolean assembly_ref = 0;
5196 MONO_ARCH_SAVE_REGS;
5198 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5199 aname->major = name->major;
5200 aname->minor = name->minor;
5201 aname->build = name->build;
5202 aname->flags = name->flags;
5203 aname->revision = name->revision;
5204 aname->hashalg = name->hash_alg;
5205 aname->versioncompat = 1; /* SameMachine (default) */
5207 if (by_default_version)
5208 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5211 if (absolute != NULL && *absolute != '\0') {
5212 const gchar *prepend = "file://";
5215 codebase = g_strdup (absolute);
5220 for (i = strlen (codebase) - 1; i >= 0; i--)
5221 if (codebase [i] == '\\')
5224 if (*codebase == '/' && *(codebase + 1) == '/') {
5227 prepend = "file:///";
5231 result = g_strconcat (prepend, codebase, NULL);
5237 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5241 if (!create_culture) {
5242 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5243 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5244 g_assert (create_culture);
5245 mono_method_desc_free (desc);
5248 if (name->culture) {
5249 args [0] = mono_string_new (domain, name->culture);
5250 args [1] = &assembly_ref;
5251 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5254 if (name->public_key) {
5255 pkey_ptr = (char*)name->public_key;
5256 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5258 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5259 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5260 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5261 } else if (default_publickey) {
5262 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5263 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5266 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5267 if (name->public_key_token [0]) {
5271 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5272 p = mono_array_addr (aname->keyToken, char, 0);
5274 for (i = 0, j = 0; i < 8; i++) {
5275 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5276 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5279 } else if (default_token) {
5280 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5285 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5287 MonoDomain *domain = mono_object_domain (assembly);
5288 MonoAssembly *mass = assembly->assembly;
5292 name = g_strdup_printf (
5293 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5295 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5296 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5297 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5298 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5300 res = mono_string_new (domain, name);
5307 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5310 MonoAssembly *mass = assembly->assembly;
5312 MONO_ARCH_SAVE_REGS;
5314 if (g_path_is_absolute (mass->image->name)) {
5315 fill_reflection_assembly_name (mono_object_domain (assembly),
5316 aname, &mass->aname, mass->image->name, TRUE,
5317 TRUE, mono_framework_version () >= 2);
5320 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5322 fill_reflection_assembly_name (mono_object_domain (assembly),
5323 aname, &mass->aname, absolute, TRUE, TRUE,
5324 mono_framework_version () >= 2);
5330 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5333 MonoImageOpenStatus status = MONO_IMAGE_OK;
5336 MonoAssemblyName name;
5339 MONO_ARCH_SAVE_REGS;
5341 filename = mono_string_to_utf8 (fname);
5343 dirname = g_path_get_dirname (filename);
5344 replace_shadow_path (mono_domain_get (), dirname, &filename);
5347 image = mono_image_open (filename, &status);
5353 if (status == MONO_IMAGE_IMAGE_INVALID)
5354 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5356 exc = mono_get_exception_file_not_found2 (NULL, fname);
5357 mono_raise_exception (exc);
5360 res = mono_assembly_fill_assembly_name (image, &name);
5362 mono_image_close (image);
5364 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5367 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5368 TRUE, mono_framework_version () == 1,
5369 mono_framework_version () >= 2);
5372 mono_image_close (image);
5376 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5377 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5379 MonoBoolean result = FALSE;
5380 MonoDeclSecurityEntry entry;
5382 /* SecurityAction.RequestMinimum */
5383 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5384 *minimum = entry.blob;
5385 *minLength = entry.size;
5388 /* SecurityAction.RequestOptional */
5389 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5390 *optional = entry.blob;
5391 *optLength = entry.size;
5394 /* SecurityAction.RequestRefuse */
5395 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5396 *refused = entry.blob;
5397 *refLength = entry.size;
5405 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5409 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5411 guint32 attrs, visibility;
5413 /* we start the count from 1 because we skip the special type <Module> */
5416 for (i = 1; i < tdef->rows; ++i) {
5417 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5418 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5419 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5423 count = tdef->rows - 1;
5425 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5426 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5428 for (i = 1; i < tdef->rows; ++i) {
5429 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5430 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5431 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5432 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5434 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5436 MonoLoaderError *error;
5439 error = mono_loader_get_last_error ();
5440 g_assert (error != NULL);
5442 ex = mono_loader_error_prepare_exception (error);
5443 mono_array_setref (*exceptions, count, ex);
5445 if (mono_loader_get_last_error ())
5446 mono_loader_clear_error ();
5455 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5457 MonoArray *res = NULL;
5458 MonoArray *exceptions = NULL;
5459 MonoImage *image = NULL;
5460 MonoTableInfo *table = NULL;
5463 int i, len, ex_count;
5465 MONO_ARCH_SAVE_REGS;
5467 domain = mono_object_domain (assembly);
5469 g_assert (!assembly->assembly->dynamic);
5470 image = assembly->assembly->image;
5471 table = &image->tables [MONO_TABLE_FILE];
5472 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5474 /* Append data from all modules in the assembly */
5475 for (i = 0; i < table->rows; ++i) {
5476 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5477 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5480 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5481 /* Append the new types to the end of the array */
5482 if (mono_array_length (res2) > 0) {
5484 MonoArray *res3, *ex3;
5486 len1 = mono_array_length (res);
5487 len2 = mono_array_length (res2);
5489 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5490 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5491 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5494 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5495 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5496 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5503 /* the ReflectionTypeLoadException must have all the types (Types property),
5504 * NULL replacing types which throws an exception. The LoaderException must
5505 * contain all exceptions for NULL items.
5508 len = mono_array_length (res);
5511 for (i = 0; i < len; i++) {
5512 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5516 klass = mono_type_get_class (t->type);
5517 if ((klass != NULL) && klass->exception_type) {
5518 /* keep the class in the list */
5519 list = g_list_append (list, klass);
5520 /* and replace Type with NULL */
5521 mono_array_setref (res, i, NULL);
5528 if (list || ex_count) {
5530 MonoException *exc = NULL;
5531 MonoArray *exl = NULL;
5532 int j, length = g_list_length (list) + ex_count;
5534 mono_loader_clear_error ();
5536 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5537 /* Types for which mono_class_get () succeeded */
5538 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5539 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5540 mono_array_setref (exl, i, exc);
5542 /* Types for which it don't */
5543 for (j = 0; j < mono_array_length (exceptions); ++j) {
5544 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5546 g_assert (i < length);
5547 mono_array_setref (exl, i, exc);
5554 exc = mono_get_exception_reflection_type_load (res, exl);
5555 mono_loader_clear_error ();
5556 mono_raise_exception (exc);
5563 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5565 MonoAssemblyName aname;
5566 MonoDomain *domain = mono_object_domain (name);
5568 gboolean is_version_defined;
5569 gboolean is_token_defined;
5571 aname.public_key = NULL;
5572 val = mono_string_to_utf8 (assname);
5573 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5574 g_free ((guint8*) aname.public_key);
5579 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5580 FALSE, is_token_defined);
5582 mono_assembly_name_free (&aname);
5583 g_free ((guint8*) aname.public_key);
5589 static MonoReflectionType*
5590 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5592 MonoDomain *domain = mono_object_domain (module);
5595 MONO_ARCH_SAVE_REGS;
5597 g_assert (module->image);
5599 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5600 /* These images do not have a global type */
5603 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5604 return mono_type_get_object (domain, &klass->byval_arg);
5608 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5610 /*if (module->image)
5611 mono_image_close (module->image);*/
5615 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5617 MonoDomain *domain = mono_object_domain (module);
5619 MONO_ARCH_SAVE_REGS;
5621 g_assert (module->image);
5622 return mono_string_new (domain, module->image->guid);
5626 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5628 #ifdef PLATFORM_WIN32
5629 if (module->image && module->image->is_module_handle)
5630 return module->image->raw_data;
5633 return (gpointer) (-1);
5637 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5639 if (image->dynamic) {
5640 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5641 *pe_kind = dyn->pe_kind;
5642 *machine = dyn->machine;
5645 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5646 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5651 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5653 return (image->md_version_major << 16) | (image->md_version_minor);
5657 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5659 MonoArray *exceptions;
5662 MONO_ARCH_SAVE_REGS;
5665 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5667 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5668 for (i = 0; i < mono_array_length (exceptions); ++i) {
5669 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5671 mono_raise_exception (ex);
5678 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5680 guint32 cols [MONO_MEMBERREF_SIZE];
5682 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5683 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5684 mono_metadata_decode_blob_size (sig, &sig);
5685 return (*sig != 0x6);
5689 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5692 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5693 mono_array_addr (type_args, MonoType*, 0));
5695 context->class_inst = NULL;
5697 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5698 mono_array_addr (method_args, MonoType*, 0));
5700 context->method_inst = NULL;
5704 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5707 int table = mono_metadata_token_table (token);
5708 int index = mono_metadata_token_index (token);
5709 MonoGenericContext context;
5711 *error = ResolveTokenError_Other;
5713 /* Validate token */
5714 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5715 (table != MONO_TABLE_TYPESPEC)) {
5716 *error = ResolveTokenError_BadTable;
5720 if (image->dynamic) {
5721 if (type_args || method_args)
5722 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5723 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5726 return &klass->byval_arg;
5729 if ((index <= 0) || (index > image->tables [table].rows)) {
5730 *error = ResolveTokenError_OutOfRange;
5734 init_generic_context_from_args (&context, type_args, method_args);
5735 klass = mono_class_get_full (image, token, &context);
5737 if (mono_loader_get_last_error ())
5738 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5741 return &klass->byval_arg;
5747 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5749 int table = mono_metadata_token_table (token);
5750 int index = mono_metadata_token_index (token);
5751 MonoGenericContext context;
5754 *error = ResolveTokenError_Other;
5756 /* Validate token */
5757 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5758 (table != MONO_TABLE_MEMBERREF)) {
5759 *error = ResolveTokenError_BadTable;
5763 if (image->dynamic) {
5764 if (type_args || method_args)
5765 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5766 /* FIXME: validate memberref token type */
5767 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5770 if ((index <= 0) || (index > image->tables [table].rows)) {
5771 *error = ResolveTokenError_OutOfRange;
5774 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5775 *error = ResolveTokenError_BadTable;
5779 init_generic_context_from_args (&context, type_args, method_args);
5780 method = mono_get_method_full (image, token, NULL, &context);
5782 if (mono_loader_get_last_error ())
5783 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5789 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5791 int index = mono_metadata_token_index (token);
5793 *error = ResolveTokenError_Other;
5795 /* Validate token */
5796 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5797 *error = ResolveTokenError_BadTable;
5802 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5804 if ((index <= 0) || (index >= image->heap_us.size)) {
5805 *error = ResolveTokenError_OutOfRange;
5809 /* FIXME: What to do if the index points into the middle of a string ? */
5811 return mono_ldstr (mono_domain_get (), image, index);
5814 static MonoClassField*
5815 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5818 int table = mono_metadata_token_table (token);
5819 int index = mono_metadata_token_index (token);
5820 MonoGenericContext context;
5821 MonoClassField *field;
5823 *error = ResolveTokenError_Other;
5825 /* Validate token */
5826 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5827 *error = ResolveTokenError_BadTable;
5831 if (image->dynamic) {
5832 if (type_args || method_args)
5833 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5834 /* FIXME: validate memberref token type */
5835 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5838 if ((index <= 0) || (index > image->tables [table].rows)) {
5839 *error = ResolveTokenError_OutOfRange;
5842 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5843 *error = ResolveTokenError_BadTable;
5847 init_generic_context_from_args (&context, type_args, method_args);
5848 field = mono_field_from_token (image, token, &klass, &context);
5850 if (mono_loader_get_last_error ())
5851 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5858 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5860 int table = mono_metadata_token_table (token);
5862 *error = ResolveTokenError_Other;
5865 case MONO_TABLE_TYPEDEF:
5866 case MONO_TABLE_TYPEREF:
5867 case MONO_TABLE_TYPESPEC: {
5868 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5870 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5874 case MONO_TABLE_METHOD:
5875 case MONO_TABLE_METHODSPEC: {
5876 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5878 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5882 case MONO_TABLE_FIELD: {
5883 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5885 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5889 case MONO_TABLE_MEMBERREF:
5890 if (mono_metadata_memberref_is_method (image, token)) {
5891 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5893 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5898 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5900 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5907 *error = ResolveTokenError_BadTable;
5914 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5916 int table = mono_metadata_token_table (token);
5917 int idx = mono_metadata_token_index (token);
5918 MonoTableInfo *tables = image->tables;
5923 *error = ResolveTokenError_OutOfRange;
5925 /* FIXME: Support other tables ? */
5926 if (table != MONO_TABLE_STANDALONESIG)
5932 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5935 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5937 ptr = mono_metadata_blob_heap (image, sig);
5938 len = mono_metadata_decode_blob_size (ptr, &ptr);
5940 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5941 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5945 static MonoReflectionType*
5946 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5949 int isbyref = 0, rank;
5950 char *str = mono_string_to_utf8 (smodifiers);
5953 MONO_ARCH_SAVE_REGS;
5955 klass = mono_class_from_mono_type (tb->type.type);
5957 /* logic taken from mono_reflection_parse_type(): keep in sync */
5961 if (isbyref) { /* only one level allowed by the spec */
5968 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5971 klass = mono_ptr_class_get (&klass->byval_arg);
5972 mono_class_init (klass);
5983 else if (*p != '*') { /* '*' means unknown lower bound */
5994 klass = mono_array_class_get (klass, rank);
5995 mono_class_init (klass);
6002 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
6006 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
6011 MONO_ARCH_SAVE_REGS;
6014 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
6019 static MonoReflectionType *
6020 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
6022 MonoClass *klass, *aklass;
6024 MONO_ARCH_SAVE_REGS;
6026 klass = mono_class_from_mono_type (type->type);
6027 if (rank == 0) //single dimentional array
6028 aklass = mono_array_class_get (klass, 1);
6030 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
6032 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
6035 static MonoReflectionType *
6036 ves_icall_Type_make_byref_type (MonoReflectionType *type)
6040 MONO_ARCH_SAVE_REGS;
6042 klass = mono_class_from_mono_type (type->type);
6044 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
6047 static MonoReflectionType *
6048 ves_icall_Type_MakePointerType (MonoReflectionType *type)
6052 MONO_ARCH_SAVE_REGS;
6054 pklass = mono_ptr_class_get (type->type);
6056 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
6060 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
6061 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
6063 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
6064 MonoObject *delegate;
6066 MonoMethod *method = info->method;
6068 MONO_ARCH_SAVE_REGS;
6070 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
6072 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
6073 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6077 delegate = mono_object_new (mono_object_domain (type), delegate_class);
6079 if (method->dynamic) {
6080 /* Creating a trampoline would leak memory */
6081 func = mono_compile_method (method);
6083 func = mono_create_ftnptr (mono_domain_get (),
6084 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6087 mono_delegate_ctor_with_method (delegate, target, func, method);
6093 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
6095 /* Reset the invoke impl to the default one */
6096 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
6100 * Magic number to convert a time which is relative to
6101 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
6103 #define EPOCH_ADJUST ((guint64)62135596800LL)
6106 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
6108 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
6110 #ifdef PLATFORM_WIN32
6111 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
6113 convert_to_absolute_date(SYSTEMTIME *date)
6115 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
6116 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6117 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6118 /* from the calendar FAQ */
6119 int a = (14 - date->wMonth) / 12;
6120 int y = date->wYear - a;
6121 int m = date->wMonth + 12 * a - 2;
6122 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
6124 /* d is now the day of the week for the first of the month (0 == Sunday) */
6126 int day_of_week = date->wDayOfWeek;
6128 /* set day_in_month to the first day in the month which falls on day_of_week */
6129 int day_in_month = 1 + (day_of_week - d);
6130 if (day_in_month <= 0)
6133 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6134 date->wDay = day_in_month + (date->wDay - 1) * 7;
6135 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6140 #ifndef PLATFORM_WIN32
6142 * Return's the offset from GMT of a local time.
6144 * tm is a local time
6145 * t is the same local time as seconds.
6148 gmt_offset(struct tm *tm, time_t t)
6150 #if defined (HAVE_TM_GMTOFF)
6151 return tm->tm_gmtoff;
6156 g.tm_isdst = tm->tm_isdst;
6158 return (int)difftime(t, t2);
6163 * This is heavily based on zdump.c from glibc 2.2.
6165 * * data[0]: start of daylight saving time (in DateTime ticks).
6166 * * data[1]: end of daylight saving time (in DateTime ticks).
6167 * * data[2]: utcoffset (in TimeSpan ticks).
6168 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6169 * * name[0]: name of this timezone when not daylight saving.
6170 * * name[1]: name of this timezone when daylight saving.
6172 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6173 * the class library allows years between 1 and 9999.
6175 * Returns true on success and zero on failure.
6178 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6180 #ifndef PLATFORM_WIN32
6181 MonoDomain *domain = mono_domain_get ();
6182 struct tm start, tt;
6186 int is_daylight = 0, day;
6189 MONO_ARCH_SAVE_REGS;
6191 MONO_CHECK_ARG_NULL (data);
6192 MONO_CHECK_ARG_NULL (names);
6194 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
6195 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6198 * no info is better than crashing: we'll need our own tz data
6199 * to make this work properly, anyway. The range is probably
6200 * reduced to 1970 .. 2037 because that is what mktime is
6201 * guaranteed to support (we get into an infinite loop
6205 memset (&start, 0, sizeof (start));
6208 start.tm_year = year-1900;
6210 t = mktime (&start);
6212 if ((year < 1970) || (year > 2037) || (t == -1)) {
6214 tt = *localtime (&t);
6215 strftime (tzone, sizeof (tzone), "%Z", &tt);
6216 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6217 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6221 gmtoff = gmt_offset (&start, t);
6223 /* For each day of the year, calculate the tm_gmtoff. */
6224 for (day = 0; day < 365; day++) {
6227 tt = *localtime (&t);
6229 /* Daylight saving starts or ends here. */
6230 if (gmt_offset (&tt, t) != gmtoff) {
6234 /* Try to find the exact hour when daylight saving starts/ends. */
6238 tt1 = *localtime (&t1);
6239 } while (gmt_offset (&tt1, t1) != gmtoff);
6241 /* Try to find the exact minute when daylight saving starts/ends. */
6244 tt1 = *localtime (&t1);
6245 } while (gmt_offset (&tt1, t1) == gmtoff);
6247 strftime (tzone, sizeof (tzone), "%Z", &tt);
6249 /* Write data, if we're already in daylight saving, we're done. */
6251 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6252 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6255 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6256 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6260 /* This is only set once when we enter daylight saving. */
6261 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6262 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6264 gmtoff = gmt_offset (&tt, t);
6269 strftime (tzone, sizeof (tzone), "%Z", &tt);
6270 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6271 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6272 mono_array_set ((*data), gint64, 0, 0);
6273 mono_array_set ((*data), gint64, 1, 0);
6274 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6275 mono_array_set ((*data), gint64, 3, 0);
6280 MonoDomain *domain = mono_domain_get ();
6281 TIME_ZONE_INFORMATION tz_info;
6286 tz_id = GetTimeZoneInformation (&tz_info);
6287 if (tz_id == TIME_ZONE_ID_INVALID)
6290 MONO_CHECK_ARG_NULL (data);
6291 MONO_CHECK_ARG_NULL (names);
6293 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6294 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6296 for (i = 0; i < 32; ++i)
6297 if (!tz_info.DaylightName [i])
6299 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6300 for (i = 0; i < 32; ++i)
6301 if (!tz_info.StandardName [i])
6303 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6305 if ((year <= 1601) || (year > 30827)) {
6307 * According to MSDN, the MS time functions can't handle dates outside
6313 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6314 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6315 tz_info.StandardDate.wYear = year;
6316 convert_to_absolute_date(&tz_info.StandardDate);
6317 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6322 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6323 tz_info.DaylightDate.wYear = year;
6324 convert_to_absolute_date(&tz_info.DaylightDate);
6325 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6330 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6332 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6333 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6340 ves_icall_System_Object_obj_address (MonoObject *this)
6342 MONO_ARCH_SAVE_REGS;
6349 static inline gint32
6350 mono_array_get_byte_length (MonoArray *array)
6356 klass = array->obj.vtable->klass;
6358 if (array->bounds == NULL)
6359 length = array->max_length;
6362 for (i = 0; i < klass->rank; ++ i)
6363 length *= array->bounds [i].length;
6366 switch (klass->element_class->byval_arg.type) {
6369 case MONO_TYPE_BOOLEAN:
6373 case MONO_TYPE_CHAR:
6381 return length * sizeof (gpointer);
6392 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6394 MONO_ARCH_SAVE_REGS;
6396 return mono_array_get_byte_length (array);
6400 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6402 MONO_ARCH_SAVE_REGS;
6404 return mono_array_get (array, gint8, idx);
6408 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6410 MONO_ARCH_SAVE_REGS;
6412 mono_array_set (array, gint8, idx, value);
6416 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6418 guint8 *src_buf, *dest_buf;
6420 MONO_ARCH_SAVE_REGS;
6422 /* watch out for integer overflow */
6423 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6426 src_buf = (guint8 *)src->vector + src_offset;
6427 dest_buf = (guint8 *)dest->vector + dest_offset;
6430 memcpy (dest_buf, src_buf, count);
6432 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6438 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6440 MonoDomain *domain = mono_object_domain (this);
6442 MonoRealProxy *rp = ((MonoRealProxy *)this);
6443 MonoTransparentProxy *tp;
6447 MONO_ARCH_SAVE_REGS;
6449 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6450 tp = (MonoTransparentProxy*) res;
6452 MONO_OBJECT_SETREF (tp, rp, rp);
6453 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6454 klass = mono_class_from_mono_type (type);
6456 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6457 tp->remote_class = mono_remote_class (domain, class_name, klass);
6459 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6463 static MonoReflectionType *
6464 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6466 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6469 /* System.Environment */
6472 ves_icall_System_Environment_get_UserName (void)
6474 MONO_ARCH_SAVE_REGS;
6476 /* using glib is more portable */
6477 return mono_string_new (mono_domain_get (), g_get_user_name ());
6482 ves_icall_System_Environment_get_MachineName (void)
6484 #if defined (PLATFORM_WIN32)
6489 len = MAX_COMPUTERNAME_LENGTH + 1;
6490 buf = g_new (gunichar2, len);
6493 if (GetComputerName (buf, (PDWORD) &len))
6494 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6498 #elif !defined(DISABLE_SOCKETS)
6502 if (gethostname (buf, sizeof (buf)) == 0)
6503 result = mono_string_new (mono_domain_get (), buf);
6509 return mono_string_new (mono_domain_get (), "mono");
6514 ves_icall_System_Environment_get_Platform (void)
6516 #if defined (PLATFORM_WIN32)
6519 #elif defined(__MACH__)
6521 if (mono_framework_version () < 2)
6525 // For compatibility with our client code, this will be 4 for a while.
6526 // We will eventually move to 6 to match .NET, but it requires all client
6527 // code to be updated and the documentation everywhere to be updated
6533 if (mono_framework_version () < 2)
6540 ves_icall_System_Environment_get_NewLine (void)
6542 MONO_ARCH_SAVE_REGS;
6544 #if defined (PLATFORM_WIN32)
6545 return mono_string_new (mono_domain_get (), "\r\n");
6547 return mono_string_new (mono_domain_get (), "\n");
6552 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6557 MONO_ARCH_SAVE_REGS;
6562 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6563 value = g_getenv (utf8_name);
6570 return mono_string_new (mono_domain_get (), value);
6574 * There is no standard way to get at environ.
6577 #ifndef __MINGW32_VERSION
6579 /* Apple defines this in crt_externs.h but doesn't provide that header for
6580 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6581 * in fact exist on all implementations (so far)
6583 gchar ***_NSGetEnviron(void);
6584 #define environ (*_NSGetEnviron())
6593 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6595 #ifdef PLATFORM_WIN32
6604 env_strings = GetEnvironmentStrings();
6607 env_string = env_strings;
6608 while (*env_string != '\0') {
6609 /* weird case that MS seems to skip */
6610 if (*env_string != '=')
6612 while (*env_string != '\0')
6618 domain = mono_domain_get ();
6619 names = mono_array_new (domain, mono_defaults.string_class, n);
6623 env_string = env_strings;
6624 while (*env_string != '\0') {
6625 /* weird case that MS seems to skip */
6626 if (*env_string != '=') {
6627 equal_str = wcschr(env_string, '=');
6628 g_assert(equal_str);
6629 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6630 mono_array_setref (names, n, str);
6633 while (*env_string != '\0')
6638 FreeEnvironmentStrings (env_strings);
6650 MONO_ARCH_SAVE_REGS;
6653 for (e = environ; *e != 0; ++ e)
6656 domain = mono_domain_get ();
6657 names = mono_array_new (domain, mono_defaults.string_class, n);
6660 for (e = environ; *e != 0; ++ e) {
6661 parts = g_strsplit (*e, "=", 2);
6663 str = mono_string_new (domain, *parts);
6664 mono_array_setref (names, n, str);
6677 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6679 #if !GLIB_CHECK_VERSION(2,4,0)
6680 #define g_setenv(a,b,c) setenv(a,b,c)
6681 #define g_unsetenv(a) unsetenv(a)
6685 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6687 #ifdef PLATFORM_WIN32
6688 gunichar2 *utf16_name, *utf16_value;
6690 gchar *utf8_name, *utf8_value;
6693 MONO_ARCH_SAVE_REGS;
6695 #ifdef PLATFORM_WIN32
6696 utf16_name = mono_string_to_utf16 (name);
6697 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6698 SetEnvironmentVariable (utf16_name, NULL);
6699 g_free (utf16_name);
6703 utf16_value = mono_string_to_utf16 (value);
6705 SetEnvironmentVariable (utf16_name, utf16_value);
6707 g_free (utf16_name);
6708 g_free (utf16_value);
6710 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6712 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6713 g_unsetenv (utf8_name);
6718 utf8_value = mono_string_to_utf8 (value);
6719 g_setenv (utf8_name, utf8_value, TRUE);
6722 g_free (utf8_value);
6727 ves_icall_System_Environment_Exit (int result)
6729 MONO_ARCH_SAVE_REGS;
6731 mono_threads_set_shutting_down ();
6733 mono_runtime_set_shutting_down ();
6735 /* Suspend all managed threads since the runtime is going away */
6736 mono_thread_suspend_all_other_threads ();
6738 mono_runtime_quit ();
6740 /* we may need to do some cleanup here... */
6745 ves_icall_System_Environment_GetGacPath (void)
6747 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6751 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6753 #if defined (PLATFORM_WIN32)
6754 #ifndef CSIDL_FLAG_CREATE
6755 #define CSIDL_FLAG_CREATE 0x8000
6758 WCHAR path [MAX_PATH];
6759 /* Create directory if no existing */
6760 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6764 return mono_string_new_utf16 (mono_domain_get (), path, len);
6767 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6769 return mono_string_new (mono_domain_get (), "");
6773 ves_icall_System_Environment_GetLogicalDrives (void)
6775 gunichar2 buf [128], *ptr, *dname;
6777 guint initial_size = 127, size = 128;
6780 MonoString *drivestr;
6781 MonoDomain *domain = mono_domain_get ();
6784 MONO_ARCH_SAVE_REGS;
6789 while (size > initial_size) {
6790 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6791 if (size > initial_size) {
6794 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6795 initial_size = size;
6809 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6814 while (*u16) { u16++; len ++; }
6815 drivestr = mono_string_new_utf16 (domain, dname, len);
6816 mono_array_setref (result, ndrives++, drivestr);
6827 ves_icall_System_Environment_InternalGetHome (void)
6829 MONO_ARCH_SAVE_REGS;
6831 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6834 static const char *encodings [] = {
6836 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6837 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6838 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6840 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6841 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6842 "x_unicode_2_0_utf_7",
6844 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6845 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6847 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6850 "unicodefffe", "utf_16be",
6857 * Returns the internal codepage, if the value of "int_code_page" is
6858 * 1 at entry, and we can not compute a suitable code page number,
6859 * returns the code page as a string
6862 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6867 char *codepage = NULL;
6869 int want_name = *int_code_page;
6872 *int_code_page = -1;
6873 MONO_ARCH_SAVE_REGS;
6875 g_get_charset (&cset);
6876 c = codepage = strdup (cset);
6877 for (c = codepage; *c; c++){
6878 if (isascii (*c) && isalpha (*c))
6883 /* g_print ("charset: %s\n", cset); */
6885 /* handle some common aliases */
6888 for (i = 0; p != 0; ){
6889 if ((gssize) p < 7){
6891 p = encodings [++i];
6894 if (strcmp (p, codepage) == 0){
6895 *int_code_page = code;
6898 p = encodings [++i];
6901 if (strstr (codepage, "utf_8") != NULL)
6902 *int_code_page |= 0x10000000;
6905 if (want_name && *int_code_page == -1)
6906 return mono_string_new (mono_domain_get (), cset);
6912 ves_icall_System_Environment_get_HasShutdownStarted (void)
6914 if (mono_runtime_is_shutting_down ())
6917 if (mono_domain_is_unloading (mono_domain_get ()))
6924 ves_icall_System_Environment_BroadcastSettingChange (void)
6926 #ifdef PLATFORM_WIN32
6927 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6932 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6933 MonoReflectionMethod *method,
6934 MonoArray *out_args)
6936 MONO_ARCH_SAVE_REGS;
6938 mono_message_init (mono_object_domain (this), this, method, out_args);
6942 ves_icall_IsTransparentProxy (MonoObject *proxy)
6944 MONO_ARCH_SAVE_REGS;
6949 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6955 static MonoReflectionMethod *
6956 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6957 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6961 MonoMethod **vtable;
6962 MonoMethod *res = NULL;
6964 MONO_CHECK_ARG_NULL (rtype);
6965 MONO_CHECK_ARG_NULL (rmethod);
6967 method = rmethod->method;
6968 klass = mono_class_from_mono_type (rtype->type);
6970 if (MONO_CLASS_IS_INTERFACE (klass))
6973 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6976 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6977 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6983 mono_class_setup_vtable (klass);
6984 vtable = klass->vtable;
6986 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6987 int offs = mono_class_interface_offset (klass, method->klass);
6989 res = vtable [offs + method->slot];
6991 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6994 if (method->slot != -1)
6995 res = vtable [method->slot];
7001 return mono_method_get_object (mono_domain_get (), res, NULL);
7005 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
7010 MONO_ARCH_SAVE_REGS;
7012 klass = mono_class_from_mono_type (type->type);
7013 vtable = mono_class_vtable (mono_domain_get (), klass);
7015 if (enable) vtable->remote = 1;
7016 else vtable->remote = 0;
7020 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
7025 MONO_ARCH_SAVE_REGS;
7027 domain = mono_object_domain (type);
7028 klass = mono_class_from_mono_type (type->type);
7030 if (klass->rank >= 1) {
7031 g_assert (klass->rank == 1);
7032 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
7034 /* Bypass remoting object creation check */
7035 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
7040 ves_icall_System_IO_get_temp_path (void)
7042 MONO_ARCH_SAVE_REGS;
7044 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
7047 #ifndef PLATFORM_NO_DRIVEINFO
7049 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
7050 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
7054 ULARGE_INTEGER wapi_free_bytes_avail;
7055 ULARGE_INTEGER wapi_total_number_of_bytes;
7056 ULARGE_INTEGER wapi_total_number_of_free_bytes;
7058 MONO_ARCH_SAVE_REGS;
7060 *error = ERROR_SUCCESS;
7061 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
7062 &wapi_total_number_of_free_bytes);
7065 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
7066 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
7067 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
7069 *free_bytes_avail = 0;
7070 *total_number_of_bytes = 0;
7071 *total_number_of_free_bytes = 0;
7072 *error = GetLastError ();
7079 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7081 MONO_ARCH_SAVE_REGS;
7083 return GetDriveType (mono_string_chars (root_path_name));
7088 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7090 MONO_ARCH_SAVE_REGS;
7092 return mono_compile_method (method);
7096 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7101 MONO_ARCH_SAVE_REGS;
7103 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7105 #if defined (PLATFORM_WIN32)
7106 /* Avoid mixing '/' and '\\' */
7109 for (i = strlen (path) - 1; i >= 0; i--)
7110 if (path [i] == '/')
7114 mcpath = mono_string_new (mono_domain_get (), path);
7121 get_bundled_machine_config (void)
7123 const gchar *machine_config;
7125 MONO_ARCH_SAVE_REGS;
7127 machine_config = mono_get_machine_config ();
7129 if (!machine_config)
7132 return mono_string_new (mono_domain_get (), machine_config);
7136 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7141 MONO_ARCH_SAVE_REGS;
7143 path = g_path_get_dirname (mono_get_config_dir ());
7145 #if defined (PLATFORM_WIN32)
7146 /* Avoid mixing '/' and '\\' */
7149 for (i = strlen (path) - 1; i >= 0; i--)
7150 if (path [i] == '/')
7154 ipath = mono_string_new (mono_domain_get (), path);
7161 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7163 MonoPEResourceDataEntry *entry;
7166 MONO_ARCH_SAVE_REGS;
7168 if (!assembly || !result || !size)
7173 image = assembly->assembly->image;
7174 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7178 *result = mono_image_rva_map (image, entry->rde_data_offset);
7183 *size = entry->rde_size;
7189 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7191 return mono_debug_using_mono_debugger ();
7195 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7197 #if defined (PLATFORM_WIN32)
7198 OutputDebugString (mono_string_chars (message));
7200 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7204 /* Only used for value types */
7206 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7211 MONO_ARCH_SAVE_REGS;
7213 domain = mono_object_domain (type);
7214 klass = mono_class_from_mono_type (type->type);
7216 if (mono_class_is_nullable (klass))
7217 /* No arguments -> null */
7220 return mono_object_new (domain, klass);
7223 static MonoReflectionMethod *
7224 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7226 MonoClass *klass, *parent;
7227 MonoMethod *method = m->method;
7228 MonoMethod *result = NULL;
7230 MONO_ARCH_SAVE_REGS;
7232 if (method->klass == NULL)
7235 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7236 MONO_CLASS_IS_INTERFACE (method->klass) ||
7237 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7240 klass = method->klass;
7241 if (klass->generic_class)
7242 klass = klass->generic_class->container_class;
7244 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7245 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7246 mono_class_setup_vtable (parent);
7247 if (parent->vtable_size <= method->slot)
7252 if (klass == method->klass)
7255 result = klass->vtable [method->slot];
7256 if (result == NULL) {
7257 /* It is an abstract method */
7258 gpointer iter = NULL;
7259 while ((result = mono_class_get_methods (klass, &iter)))
7260 if (result->slot == method->slot)
7267 return mono_method_get_object (mono_domain_get (), result, NULL);
7271 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7273 MonoMethod *method = m->method;
7275 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7280 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7282 MONO_ARCH_SAVE_REGS;
7284 iter->sig = *(MonoMethodSignature**)argsp;
7286 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7287 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7290 /* FIXME: it's not documented what start is exactly... */
7294 iter->args = argsp + sizeof (gpointer);
7295 #ifndef MONO_ARCH_REGPARMS
7297 guint32 i, arg_size;
7299 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7300 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7301 iter->args = (char*)iter->args + arg_size;
7306 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7308 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7312 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7314 guint32 i, arg_size;
7317 MONO_ARCH_SAVE_REGS;
7319 i = iter->sig->sentinelpos + iter->next_arg;
7321 g_assert (i < iter->sig->param_count);
7323 res.type = iter->sig->params [i];
7324 res.klass = mono_class_from_mono_type (res.type);
7325 res.value = iter->args;
7326 arg_size = mono_type_stack_size (res.type, &align);
7327 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7328 if (arg_size <= sizeof (gpointer)) {
7330 int padding = arg_size - mono_type_size (res.type, &dummy);
7331 res.value = (guint8*)res.value + padding;
7334 iter->args = (char*)iter->args + arg_size;
7337 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7343 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7345 guint32 i, arg_size;
7348 MONO_ARCH_SAVE_REGS;
7350 i = iter->sig->sentinelpos + iter->next_arg;
7352 g_assert (i < iter->sig->param_count);
7354 while (i < iter->sig->param_count) {
7355 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7357 res.type = iter->sig->params [i];
7358 res.klass = mono_class_from_mono_type (res.type);
7359 /* FIXME: endianess issue... */
7360 res.value = iter->args;
7361 arg_size = mono_type_stack_size (res.type, &align);
7362 iter->args = (char*)iter->args + arg_size;
7364 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7367 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7376 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7379 MONO_ARCH_SAVE_REGS;
7381 i = iter->sig->sentinelpos + iter->next_arg;
7383 g_assert (i < iter->sig->param_count);
7385 return iter->sig->params [i];
7389 mono_TypedReference_ToObject (MonoTypedRef tref)
7391 MONO_ARCH_SAVE_REGS;
7393 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7394 MonoObject** objp = tref.value;
7398 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7402 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7404 MONO_ARCH_SAVE_REGS;
7406 if (MONO_TYPE_IS_REFERENCE (type)) {
7407 MonoObject** objp = value;
7411 return mono_value_box (mono_domain_get (), klass, value);
7415 prelink_method (MonoMethod *method)
7417 const char *exc_class, *exc_arg;
7418 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7420 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7422 mono_raise_exception(
7423 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7425 /* create the wrapper, too? */
7429 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7431 MONO_ARCH_SAVE_REGS;
7432 prelink_method (method->method);
7436 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7438 MonoClass *klass = mono_class_from_mono_type (type->type);
7440 gpointer iter = NULL;
7441 MONO_ARCH_SAVE_REGS;
7443 while ((m = mono_class_get_methods (klass, &iter)))
7447 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7449 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7450 gint32 const **exponents,
7451 gunichar2 const **digitLowerTable,
7452 gunichar2 const **digitUpperTable,
7453 gint64 const **tenPowersList,
7454 gint32 const **decHexDigits)
7456 *mantissas = Formatter_MantissaBitsTable;
7457 *exponents = Formatter_TensExponentTable;
7458 *digitLowerTable = Formatter_DigitLowerTable;
7459 *digitUpperTable = Formatter_DigitUpperTable;
7460 *tenPowersList = Formatter_TenPowersList;
7461 *decHexDigits = Formatter_DecHexDigits;
7464 /* These parameters are "readonly" in corlib/System/Char.cs */
7466 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7467 guint8 const **numeric_data,
7468 gdouble const **numeric_data_values,
7469 guint16 const **to_lower_data_low,
7470 guint16 const **to_lower_data_high,
7471 guint16 const **to_upper_data_low,
7472 guint16 const **to_upper_data_high)
7474 *category_data = CategoryData;
7475 *numeric_data = NumericData;
7476 *numeric_data_values = NumericDataValues;
7477 *to_lower_data_low = ToLowerDataLow;
7478 *to_lower_data_high = ToLowerDataHigh;
7479 *to_upper_data_low = ToUpperDataLow;
7480 *to_upper_data_high = ToUpperDataHigh;
7484 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7486 return method->method->token;
7490 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7491 * and avoid useless allocations.
7494 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7498 for (i = 0; i < type->num_mods; ++i) {
7499 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7504 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7506 for (i = 0; i < type->num_mods; ++i) {
7507 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7508 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7509 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7517 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7519 MonoType *type = param->ClassImpl->type;
7520 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7521 MonoImage *image = method->method->klass->image;
7522 int pos = param->PositionImpl;
7523 MonoMethodSignature *sig = mono_method_signature (method->method);
7527 type = sig->params [pos];
7529 return type_array_from_modifiers (image, type, optional);
7533 get_property_type (MonoProperty *prop)
7535 MonoMethodSignature *sig;
7537 sig = mono_method_signature (prop->get);
7539 } else if (prop->set) {
7540 sig = mono_method_signature (prop->set);
7541 return sig->params [sig->param_count - 1];
7547 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7549 MonoType *type = get_property_type (property->property);
7550 MonoImage *image = property->klass->image;
7554 return type_array_from_modifiers (image, type, optional);
7558 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7560 MonoCustomAttrInfo *cinfo;
7563 cinfo = mono_reflection_get_custom_attrs_info (obj);
7566 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7568 mono_custom_attrs_free (cinfo);
7573 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7575 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7577 if (mono_loader_get_last_error ()) {
7578 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7579 g_assert_not_reached ();
7588 ves_icall_Mono_Runtime_GetDisplayName (void)
7590 static const char display_name_str [] = "Mono " VERSION;
7591 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7592 return display_name;
7596 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7598 MonoString *message;
7602 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7603 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7606 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7608 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7616 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7617 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7618 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7619 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7620 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7621 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7622 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7623 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7627 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7632 gunichar2 last, prev_last, prev2_last;
7640 last = prev_last = 0, prev2_last = 0;
7641 for (i = 0; i < ilength; i++) {
7643 if (c >= sizeof (dbase64)) {
7644 exc = mono_exception_from_name_msg (mono_get_corlib (),
7645 "System", "FormatException",
7646 "Invalid character found.");
7647 mono_raise_exception (exc);
7648 } else if (isspace (c)) {
7651 prev2_last = prev_last;
7657 olength = ilength - ignored;
7659 if (allowWhitespaceOnly && olength == 0) {
7660 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7663 if ((olength & 3) != 0 || olength <= 0) {
7664 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7665 "FormatException", "Invalid length.");
7666 mono_raise_exception (exc);
7669 if (prev2_last == '=') {
7670 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7671 mono_raise_exception (exc);
7674 olength = (olength * 3) / 4;
7678 if (prev_last == '=')
7681 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7682 res_ptr = mono_array_addr (result, guchar, 0);
7683 for (i = 0; i < ilength; ) {
7686 for (k = 0; k < 4 && i < ilength;) {
7692 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7693 exc = mono_exception_from_name_msg (mono_get_corlib (),
7694 "System", "FormatException",
7695 "Invalid character found.");
7696 mono_raise_exception (exc);
7701 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7703 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7705 *res_ptr++ = (b [2] << 6) | b [3];
7707 while (i < ilength && isspace (start [i]))
7715 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7717 MONO_ARCH_SAVE_REGS;
7719 return base64_to_byte_array (mono_string_chars (str),
7720 mono_string_length (str), allowWhitespaceOnly);
7724 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7726 MONO_ARCH_SAVE_REGS;
7728 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7732 #define ICALL_TYPE(id,name,first)
7733 #define ICALL(id,name,func) Icall_ ## id,
7736 #include "metadata/icall-def.h"
7742 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7743 #define ICALL(id,name,func)
7745 #include "metadata/icall-def.h"
7751 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7752 #define ICALL(id,name,func)
7754 guint16 first_icall;
7757 static const IcallTypeDesc
7758 icall_type_descs [] = {
7759 #include "metadata/icall-def.h"
7763 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7766 #define ICALL_TYPE(id,name,first)
7769 #ifdef HAVE_ARRAY_ELEM_INIT
7770 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7771 #define MSGSTRFIELD1(line) str##line
7773 static const struct msgstrtn_t {
7774 #define ICALL(id,name,func)
7776 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7777 #include "metadata/icall-def.h"
7779 } icall_type_names_str = {
7780 #define ICALL_TYPE(id,name,first) (name),
7781 #include "metadata/icall-def.h"
7784 static const guint16 icall_type_names_idx [] = {
7785 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7786 #include "metadata/icall-def.h"
7789 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7791 static const struct msgstr_t {
7793 #define ICALL_TYPE(id,name,first)
7794 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7795 #include "metadata/icall-def.h"
7797 } icall_names_str = {
7798 #define ICALL(id,name,func) (name),
7799 #include "metadata/icall-def.h"
7802 static const guint16 icall_names_idx [] = {
7803 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7804 #include "metadata/icall-def.h"
7807 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7813 #define ICALL_TYPE(id,name,first) name,
7814 #define ICALL(id,name,func)
7815 static const char* const
7816 icall_type_names [] = {
7817 #include "metadata/icall-def.h"
7821 #define icall_type_name_get(id) (icall_type_names [(id)])
7825 #define ICALL_TYPE(id,name,first)
7826 #define ICALL(id,name,func) name,
7827 static const char* const
7829 #include "metadata/icall-def.h"
7832 #define icall_name_get(id) icall_names [(id)]
7834 #endif /* !HAVE_ARRAY_ELEM_INIT */
7838 #define ICALL_TYPE(id,name,first)
7839 #define ICALL(id,name,func) func,
7840 static const gconstpointer
7841 icall_functions [] = {
7842 #include "metadata/icall-def.h"
7846 static GHashTable *icall_hash = NULL;
7847 static GHashTable *jit_icall_hash_name = NULL;
7848 static GHashTable *jit_icall_hash_addr = NULL;
7851 mono_icall_init (void)
7855 /* check that tables are sorted: disable in release */
7858 const char *prev_class = NULL;
7859 const char *prev_method;
7861 for (i = 0; i < Icall_type_num; ++i) {
7862 const IcallTypeDesc *desc;
7865 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7866 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7867 prev_class = icall_type_name_get (i);
7868 desc = &icall_type_descs [i];
7869 num_icalls = icall_desc_num_icalls (desc);
7870 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7871 for (j = 0; j < num_icalls; ++j) {
7872 const char *methodn = icall_name_get (desc->first_icall + j);
7873 if (prev_method && strcmp (prev_method, methodn) >= 0)
7874 g_print ("method %s should come before method %s\n", methodn, prev_method);
7875 prev_method = methodn;
7880 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7884 mono_icall_cleanup (void)
7886 g_hash_table_destroy (icall_hash);
7887 g_hash_table_destroy (jit_icall_hash_name);
7888 g_hash_table_destroy (jit_icall_hash_addr);
7892 mono_add_internal_call (const char *name, gconstpointer method)
7894 mono_loader_lock ();
7896 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7898 mono_loader_unlock ();
7901 #ifdef HAVE_ARRAY_ELEM_INIT
7903 compare_method_imap (const void *key, const void *elem)
7905 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7906 return strcmp (key, method_name);
7910 find_method_icall (const IcallTypeDesc *imap, const char *name)
7912 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7915 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7919 compare_class_imap (const void *key, const void *elem)
7921 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7922 return strcmp (key, class_name);
7925 static const IcallTypeDesc*
7926 find_class_icalls (const char *name)
7928 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7931 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7936 compare_method_imap (const void *key, const void *elem)
7938 const char** method_name = (const char**)elem;
7939 return strcmp (key, *method_name);
7943 find_method_icall (const IcallTypeDesc *imap, const char *name)
7945 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7948 return (gpointer)icall_functions [(nameslot - icall_names)];
7952 compare_class_imap (const void *key, const void *elem)
7954 const char** class_name = (const char**)elem;
7955 return strcmp (key, *class_name);
7958 static const IcallTypeDesc*
7959 find_class_icalls (const char *name)
7961 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7964 return &icall_type_descs [nameslot - icall_type_names];
7970 * we should probably export this as an helper (handle nested types).
7971 * Returns the number of chars written in buf.
7974 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7976 int nspacelen, cnamelen;
7977 nspacelen = strlen (klass->name_space);
7978 cnamelen = strlen (klass->name);
7979 if (nspacelen + cnamelen + 2 > bufsize)
7982 memcpy (buf, klass->name_space, nspacelen);
7983 buf [nspacelen ++] = '.';
7985 memcpy (buf + nspacelen, klass->name, cnamelen);
7986 buf [nspacelen + cnamelen] = 0;
7987 return nspacelen + cnamelen;
7991 mono_lookup_internal_call (MonoMethod *method)
7996 int typelen = 0, mlen, siglen;
7998 const IcallTypeDesc *imap;
8000 g_assert (method != NULL);
8002 if (method->is_inflated)
8003 method = ((MonoMethodInflated *) method)->declaring;
8005 if (method->klass->nested_in) {
8006 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8010 mname [pos++] = '/';
8013 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8019 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8024 imap = find_class_icalls (mname);
8026 mname [typelen] = ':';
8027 mname [typelen + 1] = ':';
8029 mlen = strlen (method->name);
8030 memcpy (mname + typelen + 2, method->name, mlen);
8031 sigstart = mname + typelen + 2 + mlen;
8034 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8035 siglen = strlen (tmpsig);
8036 if (typelen + mlen + siglen + 6 > sizeof (mname))
8039 memcpy (sigstart + 1, tmpsig, siglen);
8040 sigstart [siglen + 1] = ')';
8041 sigstart [siglen + 2] = 0;
8044 mono_loader_lock ();
8046 res = g_hash_table_lookup (icall_hash, mname);
8048 mono_loader_unlock ();
8051 /* try without signature */
8053 res = g_hash_table_lookup (icall_hash, mname);
8055 mono_loader_unlock ();
8059 /* it wasn't found in the static call tables */
8061 mono_loader_unlock ();
8064 res = find_method_icall (imap, sigstart - mlen);
8066 mono_loader_unlock ();
8069 /* try _with_ signature */
8071 res = find_method_icall (imap, sigstart - mlen);
8073 mono_loader_unlock ();
8077 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8078 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8079 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8080 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8081 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");
8082 g_print ("If you see other errors or faults after this message they are probably related\n");
8083 g_print ("and you need to fix your mono install first.\n");
8085 mono_loader_unlock ();
8091 type_from_typename (char *typename)
8093 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8095 if (!strcmp (typename, "int"))
8096 klass = mono_defaults.int_class;
8097 else if (!strcmp (typename, "ptr"))
8098 klass = mono_defaults.int_class;
8099 else if (!strcmp (typename, "void"))
8100 klass = mono_defaults.void_class;
8101 else if (!strcmp (typename, "int32"))
8102 klass = mono_defaults.int32_class;
8103 else if (!strcmp (typename, "uint32"))
8104 klass = mono_defaults.uint32_class;
8105 else if (!strcmp (typename, "int8"))
8106 klass = mono_defaults.sbyte_class;
8107 else if (!strcmp (typename, "uint8"))
8108 klass = mono_defaults.byte_class;
8109 else if (!strcmp (typename, "int16"))
8110 klass = mono_defaults.int16_class;
8111 else if (!strcmp (typename, "uint16"))
8112 klass = mono_defaults.uint16_class;
8113 else if (!strcmp (typename, "long"))
8114 klass = mono_defaults.int64_class;
8115 else if (!strcmp (typename, "ulong"))
8116 klass = mono_defaults.uint64_class;
8117 else if (!strcmp (typename, "float"))
8118 klass = mono_defaults.single_class;
8119 else if (!strcmp (typename, "double"))
8120 klass = mono_defaults.double_class;
8121 else if (!strcmp (typename, "object"))
8122 klass = mono_defaults.object_class;
8123 else if (!strcmp (typename, "obj"))
8124 klass = mono_defaults.object_class;
8125 else if (!strcmp (typename, "string"))
8126 klass = mono_defaults.string_class;
8127 else if (!strcmp (typename, "bool"))
8128 klass = mono_defaults.boolean_class;
8129 else if (!strcmp (typename, "boolean"))
8130 klass = mono_defaults.boolean_class;
8132 g_error ("%s", typename);
8133 g_assert_not_reached ();
8135 return &klass->byval_arg;
8138 MonoMethodSignature*
8139 mono_create_icall_signature (const char *sigstr)
8144 MonoMethodSignature *res;
8146 mono_loader_lock ();
8147 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8149 mono_loader_unlock ();
8153 parts = g_strsplit (sigstr, " ", 256);
8162 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8165 #ifdef PLATFORM_WIN32
8167 * Under windows, the default pinvoke calling convention is STDCALL but
8170 res->call_convention = MONO_CALL_C;
8173 res->ret = type_from_typename (parts [0]);
8174 for (i = 1; i < len; ++i) {
8175 res->params [i - 1] = type_from_typename (parts [i]);
8180 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8182 mono_loader_unlock ();
8188 mono_find_jit_icall_by_name (const char *name)
8190 MonoJitICallInfo *info;
8191 g_assert (jit_icall_hash_name);
8193 mono_loader_lock ();
8194 info = g_hash_table_lookup (jit_icall_hash_name, name);
8195 mono_loader_unlock ();
8200 mono_find_jit_icall_by_addr (gconstpointer addr)
8202 MonoJitICallInfo *info;
8203 g_assert (jit_icall_hash_addr);
8205 mono_loader_lock ();
8206 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8207 mono_loader_unlock ();
8213 * mono_get_jit_icall_info:
8215 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8216 * caller should access it while holding the loader lock.
8219 mono_get_jit_icall_info (void)
8221 return jit_icall_hash_name;
8225 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8227 mono_loader_lock ();
8228 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8229 mono_loader_unlock ();
8233 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8235 MonoJitICallInfo *info;
8240 mono_loader_lock ();
8242 if (!jit_icall_hash_name) {
8243 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8244 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8247 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8248 g_warning ("jit icall already defined \"%s\"\n", name);
8249 g_assert_not_reached ();
8252 info = g_new0 (MonoJitICallInfo, 1);
8259 info->wrapper = func;
8261 info->wrapper = NULL;
8264 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8265 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8267 mono_loader_unlock ();