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 (ARRAY).data = __tmp; \
114 (ARRAY).capacity *= 2;\
116 ((ARRAY).data [(ARRAY).size++] = VALUE); \
119 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
120 ((ARRAY).data [(IDX)] = VALUE); \
123 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
125 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
128 static inline MonoBoolean
129 is_generic_parameter (MonoType *type)
131 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
135 * We expect a pointer to a char, not a string
138 mono_double_ParseImpl (char *ptr, double *result)
140 gchar *endptr = NULL;
147 *result = strtod (ptr, &endptr);
151 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
152 EnterCriticalSection (&mono_strtod_mutex);
153 *result = mono_strtod (ptr, &endptr);
154 LeaveCriticalSection (&mono_strtod_mutex);
156 *result = mono_strtod (ptr, &endptr);
161 if (!*ptr || (endptr && *endptr))
168 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
177 ao = (MonoArray *)this;
178 ac = (MonoClass *)ao->obj.vtable->klass;
180 esize = mono_array_element_size (ac);
181 ea = (gpointer*)((char*)ao->vector + (pos * esize));
183 if (ac->element_class->valuetype)
184 return mono_value_box (this->vtable->domain, ac->element_class, ea);
190 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
198 MONO_CHECK_ARG_NULL (idxs);
200 io = (MonoArray *)idxs;
201 ic = (MonoClass *)io->obj.vtable->klass;
203 ao = (MonoArray *)this;
204 ac = (MonoClass *)ao->obj.vtable->klass;
206 g_assert (ic->rank == 1);
207 if (io->bounds != NULL || io->max_length != ac->rank)
208 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
210 ind = (gint32 *)io->vector;
212 if (ao->bounds == NULL) {
213 if (*ind < 0 || *ind >= ao->max_length)
214 mono_raise_exception (mono_get_exception_index_out_of_range ());
216 return ves_icall_System_Array_GetValueImpl (this, *ind);
219 for (i = 0; i < ac->rank; i++)
220 if ((ind [i] < ao->bounds [i].lower_bound) ||
221 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
222 mono_raise_exception (mono_get_exception_index_out_of_range ());
224 pos = ind [0] - ao->bounds [0].lower_bound;
225 for (i = 1; i < ac->rank; i++)
226 pos = pos*ao->bounds [i].length + ind [i] -
227 ao->bounds [i].lower_bound;
229 return ves_icall_System_Array_GetValueImpl (this, pos);
233 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
235 MonoClass *ac, *vc, *ec;
247 vc = value->vtable->klass;
251 ac = this->obj.vtable->klass;
252 ec = ac->element_class;
254 esize = mono_array_element_size (ac);
255 ea = (gpointer*)((char*)this->vector + (pos * esize));
256 va = (gpointer*)((char*)value + sizeof (MonoObject));
259 memset (ea, 0, esize);
263 #define NO_WIDENING_CONVERSION G_STMT_START{\
264 mono_raise_exception (mono_get_exception_argument ( \
265 "value", "not a widening conversion")); \
268 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
269 if (esize < vsize + (extra)) \
270 mono_raise_exception (mono_get_exception_argument ( \
271 "value", "not a widening conversion")); \
274 #define INVALID_CAST G_STMT_START{\
275 mono_raise_exception (mono_get_exception_invalid_cast ()); \
278 /* Check element (destination) type. */
279 switch (ec->byval_arg.type) {
280 case MONO_TYPE_STRING:
281 switch (vc->byval_arg.type) {
282 case MONO_TYPE_STRING:
288 case MONO_TYPE_BOOLEAN:
289 switch (vc->byval_arg.type) {
290 case MONO_TYPE_BOOLEAN:
303 NO_WIDENING_CONVERSION;
310 if (!ec->valuetype) {
311 if (!mono_object_isinst (value, ec))
313 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
317 if (mono_object_isinst (value, ec)) {
318 if (ec->has_references)
319 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
321 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
328 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
330 et = ec->byval_arg.type;
331 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
332 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
334 vt = vc->byval_arg.type;
335 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
336 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
338 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
344 case MONO_TYPE_CHAR: \
345 CHECK_WIDENING_CONVERSION(0); \
346 *(etype *) ea = (etype) u64; \
348 /* You can't assign a signed value to an unsigned array. */ \
353 /* You can't assign a floating point number to an integer array. */ \
356 NO_WIDENING_CONVERSION; \
360 #define ASSIGN_SIGNED(etype) G_STMT_START{\
366 CHECK_WIDENING_CONVERSION(0); \
367 *(etype *) ea = (etype) i64; \
369 /* You can assign an unsigned value to a signed array if the array's */ \
370 /* element size is larger than the value size. */ \
375 case MONO_TYPE_CHAR: \
376 CHECK_WIDENING_CONVERSION(1); \
377 *(etype *) ea = (etype) u64; \
379 /* You can't assign a floating point number to an integer array. */ \
382 NO_WIDENING_CONVERSION; \
386 #define ASSIGN_REAL(etype) G_STMT_START{\
390 CHECK_WIDENING_CONVERSION(0); \
391 *(etype *) ea = (etype) r64; \
393 /* All integer values fit into a floating point array, so we don't */ \
394 /* need to CHECK_WIDENING_CONVERSION here. */ \
399 *(etype *) ea = (etype) i64; \
405 case MONO_TYPE_CHAR: \
406 *(etype *) ea = (etype) u64; \
413 u64 = *(guint8 *) va;
416 u64 = *(guint16 *) va;
419 u64 = *(guint32 *) va;
422 u64 = *(guint64 *) va;
428 i64 = *(gint16 *) va;
431 i64 = *(gint32 *) va;
434 i64 = *(gint64 *) va;
437 r64 = *(gfloat *) va;
440 r64 = *(gdouble *) va;
443 u64 = *(guint16 *) va;
445 case MONO_TYPE_BOOLEAN:
446 /* Boolean is only compatible with itself. */
459 NO_WIDENING_CONVERSION;
466 /* If we can't do a direct copy, let's try a widening conversion. */
469 ASSIGN_UNSIGNED (guint16);
471 ASSIGN_UNSIGNED (guint8);
473 ASSIGN_UNSIGNED (guint16);
475 ASSIGN_UNSIGNED (guint32);
477 ASSIGN_UNSIGNED (guint64);
479 ASSIGN_SIGNED (gint8);
481 ASSIGN_SIGNED (gint16);
483 ASSIGN_SIGNED (gint32);
485 ASSIGN_SIGNED (gint64);
487 ASSIGN_REAL (gfloat);
489 ASSIGN_REAL (gdouble);
493 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
497 #undef NO_WIDENING_CONVERSION
498 #undef CHECK_WIDENING_CONVERSION
499 #undef ASSIGN_UNSIGNED
505 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
513 MONO_CHECK_ARG_NULL (idxs);
515 ic = idxs->obj.vtable->klass;
516 ac = this->obj.vtable->klass;
518 g_assert (ic->rank == 1);
519 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
520 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
522 ind = (gint32 *)idxs->vector;
524 if (this->bounds == NULL) {
525 if (*ind < 0 || *ind >= this->max_length)
526 mono_raise_exception (mono_get_exception_index_out_of_range ());
528 ves_icall_System_Array_SetValueImpl (this, value, *ind);
532 for (i = 0; i < ac->rank; i++)
533 if ((ind [i] < this->bounds [i].lower_bound) ||
534 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
535 mono_raise_exception (mono_get_exception_index_out_of_range ());
537 pos = ind [0] - this->bounds [0].lower_bound;
538 for (i = 1; i < ac->rank; i++)
539 pos = pos * this->bounds [i].length + ind [i] -
540 this->bounds [i].lower_bound;
542 ves_icall_System_Array_SetValueImpl (this, value, pos);
546 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
550 mono_array_size_t *sizes, i;
551 gboolean bounded = FALSE;
555 MONO_CHECK_ARG_NULL (type);
556 MONO_CHECK_ARG_NULL (lengths);
558 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
560 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
562 for (i = 0; i < mono_array_length (lengths); i++)
563 if (mono_array_get (lengths, gint32, i) < 0)
564 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
566 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
567 /* vectors are not the same as one dimensional arrays with no-zero bounds */
572 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
574 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
575 for (i = 0; i < aklass->rank; ++i) {
576 sizes [i] = mono_array_get (lengths, guint32, i);
578 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
580 sizes [i + aklass->rank] = 0;
583 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
589 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
593 mono_array_size_t *sizes, i;
594 gboolean bounded = FALSE;
598 MONO_CHECK_ARG_NULL (type);
599 MONO_CHECK_ARG_NULL (lengths);
601 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
603 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
605 for (i = 0; i < mono_array_length (lengths); i++)
606 if ((mono_array_get (lengths, gint64, i) < 0) ||
607 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
608 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
610 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
611 /* vectors are not the same as one dimensional arrays with no-zero bounds */
616 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
618 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
619 for (i = 0; i < aklass->rank; ++i) {
620 sizes [i] = mono_array_get (lengths, guint64, i);
622 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
624 sizes [i + aklass->rank] = 0;
627 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
633 ves_icall_System_Array_GetRank (MonoObject *this)
637 return this->vtable->klass->rank;
641 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
643 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
644 mono_array_size_t length;
648 if ((dimension < 0) || (dimension >= rank))
649 mono_raise_exception (mono_get_exception_index_out_of_range ());
651 if (this->bounds == NULL)
652 length = this->max_length;
654 length = this->bounds [dimension].length;
656 #ifdef MONO_BIG_ARRAYS
657 if (length > G_MAXINT32)
658 mono_raise_exception (mono_get_exception_overflow ());
664 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
666 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
670 if ((dimension < 0) || (dimension >= rank))
671 mono_raise_exception (mono_get_exception_index_out_of_range ());
673 if (this->bounds == NULL)
674 return this->max_length;
676 return this->bounds [dimension].length;
680 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
682 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
686 if ((dimension < 0) || (dimension >= rank))
687 mono_raise_exception (mono_get_exception_index_out_of_range ());
689 if (this->bounds == NULL)
692 return this->bounds [dimension].lower_bound;
696 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
698 int sz = mono_array_element_size (mono_object_class (arr));
699 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
703 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
708 MonoClass *src_class;
709 MonoClass *dest_class;
714 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
717 if (source->bounds || dest->bounds)
720 if ((dest_idx + length > mono_array_length (dest)) ||
721 (source_idx + length > mono_array_length (source)))
724 src_class = source->obj.vtable->klass->element_class;
725 dest_class = dest->obj.vtable->klass->element_class;
728 * Handle common cases.
731 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
732 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
733 int has_refs = dest_class->has_references;
734 for (i = source_idx; i < source_idx + length; ++i) {
735 MonoObject *elem = mono_array_get (source, MonoObject*, i);
736 if (elem && !mono_object_isinst (elem, dest_class))
740 element_size = mono_array_element_size (dest->obj.vtable->klass);
741 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
742 for (i = 0; i < length; ++i) {
743 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
744 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
748 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
750 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
755 /* Check if we're copying a char[] <==> (u)short[] */
756 if (src_class != dest_class) {
757 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
760 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
762 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
763 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
764 for (i = source_idx; i < source_idx + length; ++i) {
765 MonoObject *elem = mono_array_get (source, MonoObject*, i);
766 if (elem && !mono_object_isinst (elem, dest_class))
773 if (dest_class->valuetype) {
774 element_size = mono_array_element_size (source->obj.vtable->klass);
775 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
776 if (dest_class->has_references) {
777 mono_value_copy_array (dest, dest_idx, source_addr, length);
779 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
780 memmove (dest_addr, source_addr, element_size * length);
783 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
790 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
799 ao = (MonoArray *)this;
800 ac = (MonoClass *)ao->obj.vtable->klass;
802 esize = mono_array_element_size (ac);
803 ea = (gpointer*)((char*)ao->vector + (pos * esize));
805 memcpy (value, ea, esize);
809 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
818 ao = (MonoArray *)this;
819 ac = (MonoClass *)ao->obj.vtable->klass;
821 esize = mono_array_element_size (ac);
822 ea = (gpointer*)((char*)ao->vector + (pos * esize));
824 memcpy (ea, value, esize);
828 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
830 MonoClass *klass = array->obj.vtable->klass;
831 guint32 size = mono_array_element_size (klass);
832 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
834 const char *field_data;
836 if (MONO_TYPE_IS_REFERENCE (type) ||
837 (type->type == MONO_TYPE_VALUETYPE &&
838 (!mono_type_get_class (type) ||
839 mono_type_get_class (type)->has_references))) {
840 MonoException *exc = mono_get_exception_argument("array",
841 "Cannot initialize array containing references");
842 mono_raise_exception (exc);
845 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
846 MonoException *exc = mono_get_exception_argument("field_handle",
847 "Field doesn't have an RVA");
848 mono_raise_exception (exc);
851 size *= array->max_length;
852 field_data = mono_field_get_data (field_handle);
854 if (size > mono_type_size (field_handle->type, &align)) {
855 MonoException *exc = mono_get_exception_argument("field_handle",
856 "Field not large enough to fill array");
857 mono_raise_exception (exc);
860 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
862 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
863 guint ## n *src = (guint ## n *) field_data; \
864 guint ## n *end = (guint ## n *)((char*)src + size); \
866 for (; src < end; data++, src++) { \
867 *data = read ## n (src); \
871 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
873 switch (type->type) {
890 memcpy (mono_array_addr (array, char, 0), field_data, size);
894 memcpy (mono_array_addr (array, char, 0), field_data, size);
896 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
899 double *data = (double*)mono_array_addr (array, double, 0);
901 for (i = 0; i < size; i++, data++) {
911 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
915 return offsetof (MonoString, chars);
919 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
923 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
926 return mono_object_clone (obj);
930 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
936 MONO_CHECK_ARG_NULL (handle);
938 klass = mono_class_from_mono_type (handle);
939 MONO_CHECK_ARG (handle, klass);
941 /* This will call the type constructor */
942 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), klass));
946 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
950 mono_image_check_for_module_cctor (image);
951 if (image->has_module_cctor) {
952 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
953 mono_runtime_class_init (mono_class_vtable (mono_domain_get (), module_klass));
958 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
962 return mono_object_clone (this);
966 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
969 MonoObject **values = NULL;
973 MonoClassField* field;
978 klass = mono_object_class (this);
980 if (mono_class_num_fields (klass) == 0)
981 return mono_object_hash (this);
984 * Compute the starting value of the hashcode for fields of primitive
985 * types, and return the remaining fields in an array to the managed side.
986 * This way, we can avoid costly reflection operations in managed code.
989 while ((field = mono_class_get_fields (klass, &iter))) {
990 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
992 if (mono_field_is_deleted (field))
994 /* FIXME: Add more types */
995 switch (field->type->type) {
997 result ^= *(gint32*)((guint8*)this + field->offset);
999 case MONO_TYPE_STRING: {
1001 s = *(MonoString**)((guint8*)this + field->offset);
1003 result ^= mono_string_hash (s);
1008 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1009 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1010 values [count++] = o;
1016 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
1017 for (i = 0; i < count; ++i)
1018 mono_array_setref (*fields, i, values [i]);
1026 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1029 MonoObject **values = NULL;
1031 MonoClassField* field;
1035 MONO_ARCH_SAVE_REGS;
1037 MONO_CHECK_ARG_NULL (that);
1039 if (this->vtable != that->vtable)
1042 klass = mono_object_class (this);
1044 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1045 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1048 * Do the comparison for fields of primitive type and return a result if
1049 * possible. Otherwise, return the remaining fields in an array to the
1050 * managed side. This way, we can avoid costly reflection operations in
1055 while ((field = mono_class_get_fields (klass, &iter))) {
1056 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1058 if (mono_field_is_deleted (field))
1060 /* FIXME: Add more types */
1061 switch (field->type->type) {
1064 case MONO_TYPE_BOOLEAN:
1065 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1070 case MONO_TYPE_CHAR:
1071 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1076 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1081 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1085 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1089 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1094 case MONO_TYPE_STRING: {
1095 MonoString *s1, *s2;
1096 guint32 s1len, s2len;
1097 s1 = *(MonoString**)((guint8*)this + field->offset);
1098 s2 = *(MonoString**)((guint8*)that + field->offset);
1101 if ((s1 == NULL) || (s2 == NULL))
1103 s1len = mono_string_length (s1);
1104 s2len = mono_string_length (s2);
1108 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1114 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1115 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1116 values [count++] = o;
1117 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1118 values [count++] = o;
1121 if (klass->enumtype)
1122 /* enums only have one non-static field */
1128 *fields = mono_array_new (mono_domain_get (), mono_defaults.object_class, count);
1129 for (i = 0; i < count; ++i)
1130 mono_array_setref (*fields, i, values [i]);
1137 static MonoReflectionType *
1138 ves_icall_System_Object_GetType (MonoObject *obj)
1140 MONO_ARCH_SAVE_REGS;
1142 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1143 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1145 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1149 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1151 MONO_ARCH_SAVE_REGS;
1153 mtype->type = &obj->vtable->klass->byval_arg;
1154 g_assert (mtype->type->type);
1158 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1160 MONO_ARCH_SAVE_REGS;
1162 MONO_CHECK_ARG_NULL (obj);
1164 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1168 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1169 MonoReflectionMethod *method,
1170 MonoArray *opt_param_types)
1172 MONO_ARCH_SAVE_REGS;
1174 MONO_CHECK_ARG_NULL (method);
1176 return mono_image_create_method_token (
1177 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1181 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1183 MONO_ARCH_SAVE_REGS;
1185 mono_image_create_pefile (mb, file);
1189 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1191 MONO_ARCH_SAVE_REGS;
1193 mono_image_build_metadata (mb);
1197 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1199 MONO_ARCH_SAVE_REGS;
1201 mono_image_register_token (mb->dynamic_image, token, obj);
1205 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1207 MonoMethod **dest = data;
1209 /* skip unmanaged frames */
1225 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1227 MonoMethod **dest = data;
1229 /* skip unmanaged frames */
1234 if (!strcmp (m->klass->name_space, "System.Reflection"))
1243 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1245 MonoMethod **dest = data;
1247 /* skip unmanaged frames */
1251 if (m->wrapper_type != MONO_WRAPPER_NONE)
1254 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1268 static MonoReflectionType *
1269 type_from_name (const char *str, MonoBoolean ignoreCase)
1271 MonoType *type = NULL;
1272 MonoAssembly *assembly = NULL;
1273 MonoTypeNameParse info;
1274 char *temp_str = g_strdup (str);
1275 gboolean type_resolve = FALSE;
1277 MONO_ARCH_SAVE_REGS;
1279 /* mono_reflection_parse_type() mangles the string */
1280 if (!mono_reflection_parse_type (temp_str, &info)) {
1281 mono_reflection_free_type_info (&info);
1286 if (info.assembly.name) {
1287 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1289 MonoMethod *m = mono_method_get_last_managed ();
1290 MonoMethod *dest = m;
1292 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1297 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1298 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1299 * to crash. This only seems to happen in some strange remoting
1300 * scenarios and I was unable to figure out what's happening there.
1301 * Dec 10, 2005 - Martin.
1305 assembly = dest->klass->image->assembly;
1307 g_warning (G_STRLOC);
1312 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1314 if (!info.assembly.name && !type) /* try mscorlib */
1315 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1317 mono_reflection_free_type_info (&info);
1323 return mono_type_get_object (mono_domain_get (), type);
1327 MonoReflectionType *
1328 mono_type_get (const char *str)
1330 char *copy = g_strdup (str);
1331 MonoReflectionType *type = type_from_name (copy, FALSE);
1338 static MonoReflectionType*
1339 ves_icall_type_from_name (MonoString *name,
1340 MonoBoolean throwOnError,
1341 MonoBoolean ignoreCase)
1343 char *str = mono_string_to_utf8 (name);
1344 MonoReflectionType *type;
1346 type = type_from_name (str, ignoreCase);
1349 MonoException *e = NULL;
1352 e = mono_get_exception_type_load (name, NULL);
1354 mono_loader_clear_error ();
1356 mono_raise_exception (e);
1363 static MonoReflectionType*
1364 ves_icall_type_from_handle (MonoType *handle)
1366 MonoDomain *domain = mono_domain_get ();
1367 MonoClass *klass = mono_class_from_mono_type (handle);
1369 MONO_ARCH_SAVE_REGS;
1371 mono_class_init (klass);
1372 return mono_type_get_object (domain, handle);
1376 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1378 MONO_ARCH_SAVE_REGS;
1380 if (c && type->type && c->type)
1381 return mono_metadata_type_equal (type->type, c->type);
1383 return (type == c) ? TRUE : FALSE;
1386 /* System.TypeCode */
1405 TYPECODE_STRING = 18
1409 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1411 int t = type->type->type;
1413 MONO_ARCH_SAVE_REGS;
1415 if (type->type->byref)
1416 return TYPECODE_OBJECT;
1420 case MONO_TYPE_VOID:
1421 return TYPECODE_OBJECT;
1422 case MONO_TYPE_BOOLEAN:
1423 return TYPECODE_BOOLEAN;
1425 return TYPECODE_BYTE;
1427 return TYPECODE_SBYTE;
1429 return TYPECODE_UINT16;
1431 return TYPECODE_INT16;
1432 case MONO_TYPE_CHAR:
1433 return TYPECODE_CHAR;
1437 return TYPECODE_OBJECT;
1439 return TYPECODE_UINT32;
1441 return TYPECODE_INT32;
1443 return TYPECODE_UINT64;
1445 return TYPECODE_INT64;
1447 return TYPECODE_SINGLE;
1449 return TYPECODE_DOUBLE;
1450 case MONO_TYPE_VALUETYPE:
1451 if (type->type->data.klass->enumtype) {
1452 t = mono_class_enum_basetype (type->type->data.klass)->type;
1455 MonoClass *k = type->type->data.klass;
1456 if (strcmp (k->name_space, "System") == 0) {
1457 if (strcmp (k->name, "Decimal") == 0)
1458 return TYPECODE_DECIMAL;
1459 else if (strcmp (k->name, "DateTime") == 0)
1460 return TYPECODE_DATETIME;
1463 return TYPECODE_OBJECT;
1464 case MONO_TYPE_STRING:
1465 return TYPECODE_STRING;
1466 case MONO_TYPE_SZARRAY:
1467 case MONO_TYPE_ARRAY:
1468 case MONO_TYPE_OBJECT:
1470 case MONO_TYPE_MVAR:
1471 case MONO_TYPE_TYPEDBYREF:
1472 return TYPECODE_OBJECT;
1473 case MONO_TYPE_CLASS:
1475 MonoClass *k = type->type->data.klass;
1476 if (strcmp (k->name_space, "System") == 0) {
1477 if (strcmp (k->name, "DBNull") == 0)
1478 return TYPECODE_DBNULL;
1481 return TYPECODE_OBJECT;
1482 case MONO_TYPE_GENERICINST:
1483 return TYPECODE_OBJECT;
1485 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1491 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1497 MONO_ARCH_SAVE_REGS;
1499 g_assert (type != NULL);
1501 domain = ((MonoObject *)type)->vtable->domain;
1503 if (!c) /* FIXME: dont know what do do here */
1506 klass = mono_class_from_mono_type (type->type);
1507 klassc = mono_class_from_mono_type (c->type);
1509 if (type->type->byref)
1510 return klassc == mono_defaults.object_class;
1512 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1516 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1522 MONO_ARCH_SAVE_REGS;
1524 g_assert (type != NULL);
1526 domain = ((MonoObject *)type)->vtable->domain;
1528 klass = mono_class_from_mono_type (type->type);
1529 klassc = mono_class_from_mono_type (c->type);
1531 if (type->type->byref && !c->type->byref)
1534 return mono_class_is_assignable_from (klass, klassc);
1538 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1540 MonoClass *klass = mono_class_from_mono_type (type->type);
1541 return mono_object_isinst (obj, klass) != NULL;
1545 ves_icall_get_attributes (MonoReflectionType *type)
1547 MonoClass *klass = mono_class_from_mono_type (type->type);
1549 MONO_ARCH_SAVE_REGS;
1551 return klass->flags;
1554 static MonoReflectionMarshal*
1555 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1557 MonoClass *klass = field->field->parent;
1558 MonoMarshalType *info;
1561 if (klass->generic_container ||
1562 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1565 info = mono_marshal_load_type_info (klass);
1567 for (i = 0; i < info->num_fields; ++i) {
1568 if (info->fields [i].field == field->field) {
1569 if (!info->fields [i].mspec)
1572 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1579 static MonoReflectionField*
1580 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoClass *klass)
1585 klass = handle->parent;
1587 /* FIXME: check that handle is a field of klass or of a parent: return null
1588 * and throw the exception in managed code.
1590 return mono_field_get_object (mono_domain_get (), klass, handle);
1593 static MonoReflectionField*
1594 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1596 MONO_ARCH_SAVE_REGS;
1600 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1604 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1606 MonoType *type = field->field->type;
1608 return type_array_from_modifiers (field->field->parent->image, type, optional);
1612 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1614 MonoDomain *domain = mono_domain_get ();
1615 MonoMethodSignature* sig;
1616 MONO_ARCH_SAVE_REGS;
1618 sig = mono_method_signature (method);
1620 g_assert (mono_loader_get_last_error ());
1621 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1624 info->parent = mono_type_get_object (domain, &method->klass->byval_arg);
1625 info->ret = mono_type_get_object (domain, sig->ret);
1626 info->attrs = method->flags;
1627 info->implattrs = method->iflags;
1628 if (sig->call_convention == MONO_CALL_DEFAULT)
1629 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1631 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1636 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1640 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1642 MonoDomain *domain = mono_domain_get ();
1644 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1647 static MonoReflectionMarshal*
1648 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1650 MonoDomain *domain = mono_domain_get ();
1651 MonoReflectionMarshal* res = NULL;
1652 MonoMarshalSpec **mspecs;
1655 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1656 mono_method_get_marshal_info (method, mspecs);
1659 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1661 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1663 mono_metadata_free_marshal_spec (mspecs [i]);
1670 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1672 return field->field->offset - sizeof (MonoObject);
1675 static MonoReflectionType*
1676 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1679 MONO_ARCH_SAVE_REGS;
1681 parent = declaring? field->field->parent: field->klass;
1683 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1687 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1690 MonoClassField *cf = field->field;
1694 MonoDomain *domain = mono_object_domain (field);
1696 gboolean is_static = FALSE;
1697 gboolean is_ref = FALSE;
1699 MONO_ARCH_SAVE_REGS;
1701 if (field->klass->image->assembly->ref_only)
1702 mono_raise_exception (mono_get_exception_invalid_operation (
1703 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1705 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1706 mono_security_core_clr_ensure_reflection_access_field (cf);
1708 mono_class_init (field->klass);
1710 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1713 if (obj && !is_static) {
1714 /* Check that the field belongs to the object */
1715 gboolean found = FALSE;
1718 for (k = obj->vtable->klass; k; k = k->parent) {
1719 if (k == cf->parent) {
1726 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);
1727 MonoException *ex = mono_get_exception_argument (NULL, msg);
1729 mono_raise_exception (ex);
1733 t = mono_type_get_underlying_type (cf->type);
1735 case MONO_TYPE_STRING:
1736 case MONO_TYPE_OBJECT:
1737 case MONO_TYPE_CLASS:
1738 case MONO_TYPE_ARRAY:
1739 case MONO_TYPE_SZARRAY:
1744 case MONO_TYPE_BOOLEAN:
1747 case MONO_TYPE_CHAR:
1756 case MONO_TYPE_VALUETYPE:
1759 case MONO_TYPE_GENERICINST:
1760 if (mono_type_generic_inst_is_valuetype (t)) {
1767 g_error ("type 0x%x not handled in "
1768 "ves_icall_Monofield_GetValue", t->type);
1774 vtable = mono_class_vtable (domain, cf->parent);
1775 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1776 mono_runtime_class_init (vtable);
1781 mono_field_static_get_value (vtable, cf, &o);
1783 mono_field_get_value (obj, cf, &o);
1788 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1789 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1792 /* Convert the Nullable structure into a boxed vtype */
1794 buf = (guint8*)vtable->data + cf->offset;
1796 buf = (guint8*)obj + cf->offset;
1798 return mono_nullable_box (buf, nklass);
1801 /* boxed value type */
1802 klass = mono_class_from_mono_type (cf->type);
1803 o = mono_object_new (domain, klass);
1804 v = ((gchar *) o) + sizeof (MonoObject);
1806 mono_field_static_get_value (vtable, cf, v);
1808 mono_field_get_value (obj, cf, v);
1815 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1817 MonoClassField *cf = field->field;
1820 MONO_ARCH_SAVE_REGS;
1822 if (field->klass->image->assembly->ref_only)
1823 mono_raise_exception (mono_get_exception_invalid_operation (
1824 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1826 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1827 mono_security_core_clr_ensure_reflection_access_field (cf);
1829 v = (gchar *) value;
1830 if (!cf->type->byref) {
1831 switch (cf->type->type) {
1834 case MONO_TYPE_BOOLEAN:
1837 case MONO_TYPE_CHAR:
1846 case MONO_TYPE_VALUETYPE:
1848 v += sizeof (MonoObject);
1850 case MONO_TYPE_STRING:
1851 case MONO_TYPE_OBJECT:
1852 case MONO_TYPE_CLASS:
1853 case MONO_TYPE_ARRAY:
1854 case MONO_TYPE_SZARRAY:
1857 case MONO_TYPE_GENERICINST: {
1858 MonoGenericClass *gclass = cf->type->data.generic_class;
1859 g_assert (!gclass->context.class_inst->is_open);
1861 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1862 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1863 MonoObject *nullable;
1866 * Convert the boxed vtype into a Nullable structure.
1867 * This is complicated by the fact that Nullables have
1868 * a variable structure.
1870 nullable = mono_object_new (mono_domain_get (), nklass);
1872 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1874 v = mono_object_unbox (nullable);
1877 if (gclass->container_class->valuetype && (v != NULL))
1878 v += sizeof (MonoObject);
1882 g_error ("type 0x%x not handled in "
1883 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1888 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1889 MonoVTable *vtable = mono_class_vtable (mono_object_domain (field), cf->parent);
1890 if (!vtable->initialized)
1891 mono_runtime_class_init (vtable);
1892 mono_field_static_set_value (vtable, cf, v);
1894 mono_field_set_value (obj, cf, v);
1899 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1901 MonoObject *o = NULL;
1902 MonoClassField *field = this->field;
1904 MonoDomain *domain = mono_object_domain (this);
1906 MonoTypeEnum def_type;
1907 const char *def_value;
1909 MONO_ARCH_SAVE_REGS;
1911 mono_class_init (field->parent);
1913 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1914 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1916 if (field->parent->image->dynamic) {
1918 g_assert_not_reached ();
1921 def_value = mono_class_get_field_default_value (field, &def_type);
1926 case MONO_TYPE_BOOLEAN:
1929 case MONO_TYPE_CHAR:
1937 case MONO_TYPE_R8: {
1940 /* boxed value type */
1941 t = g_new0 (MonoType, 1);
1943 klass = mono_class_from_mono_type (t);
1945 o = mono_object_new (domain, klass);
1946 v = ((gchar *) o) + sizeof (MonoObject);
1947 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1950 case MONO_TYPE_STRING:
1951 case MONO_TYPE_CLASS:
1952 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1955 g_assert_not_reached ();
1961 static MonoReflectionType*
1962 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1964 MonoMethod *method = rmethod->method.method;
1966 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1969 /* From MonoProperty.cs */
1971 PInfo_Attributes = 1,
1972 PInfo_GetMethod = 1 << 1,
1973 PInfo_SetMethod = 1 << 2,
1974 PInfo_ReflectedType = 1 << 3,
1975 PInfo_DeclaringType = 1 << 4,
1980 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1982 MonoDomain *domain = mono_object_domain (property);
1984 MONO_ARCH_SAVE_REGS;
1986 if ((req_info & PInfo_ReflectedType) != 0)
1987 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1988 else if ((req_info & PInfo_DeclaringType) != 0)
1989 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1991 if ((req_info & PInfo_Name) != 0)
1992 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1994 if ((req_info & PInfo_Attributes) != 0)
1995 info->attrs = property->property->attrs;
1997 if ((req_info & PInfo_GetMethod) != 0)
1998 MONO_STRUCT_SETREF (info, get, property->property->get ?
1999 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2001 if ((req_info & PInfo_SetMethod) != 0)
2002 MONO_STRUCT_SETREF (info, set, property->property->set ?
2003 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2005 * There may be other methods defined for properties, though, it seems they are not exposed
2006 * in the reflection API
2011 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2013 MonoDomain *domain = mono_object_domain (event);
2015 MONO_ARCH_SAVE_REGS;
2017 info->reflected_type = mono_type_get_object (domain, &event->klass->byval_arg);
2018 info->declaring_type = mono_type_get_object (domain, &event->event->parent->byval_arg);
2020 info->name = mono_string_new (domain, event->event->name);
2021 info->attrs = event->event->attrs;
2022 info->add_method = event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL;
2023 info->remove_method = event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL;
2024 info->raise_method = event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL;
2026 if (event->event->other) {
2028 while (event->event->other [n])
2030 info->other_methods = mono_array_new (domain, mono_defaults.method_info_class, n);
2032 for (i = 0; i < n; i++)
2033 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2038 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2040 MonoDomain *domain = mono_object_domain (type);
2042 GPtrArray *ifaces = NULL;
2044 MonoClass *class = mono_class_from_mono_type (type->type);
2047 MonoGenericContext *context = NULL;
2049 MONO_ARCH_SAVE_REGS;
2051 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2052 context = mono_class_get_context (class);
2053 class = class->generic_class->container_class;
2056 mono_class_setup_vtable (class);
2058 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2060 for (parent = class; parent; parent = parent->parent) {
2061 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2063 for (i = 0; i < tmp_ifaces->len; ++i) {
2064 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2066 if (mono_bitset_test (slots, ic->interface_id))
2069 mono_bitset_set (slots, ic->interface_id);
2071 ifaces = g_ptr_array_new ();
2072 g_ptr_array_add (ifaces, ic);
2074 g_ptr_array_free (tmp_ifaces, TRUE);
2077 mono_bitset_free (slots);
2080 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2082 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2083 for (i = 0; i < ifaces->len; ++i) {
2084 MonoClass *ic = g_ptr_array_index (ifaces, i);
2085 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2086 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2087 inflated = ret = mono_class_inflate_generic_type (ret, context);
2089 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2091 mono_metadata_free_type (inflated);
2093 g_ptr_array_free (ifaces, TRUE);
2099 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2101 MonoClass *class = mono_class_from_mono_type (type->type);
2102 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2103 MonoReflectionMethod *member;
2106 int i = 0, len, ioffset;
2109 MONO_ARCH_SAVE_REGS;
2111 mono_class_setup_vtable (class);
2113 /* type doesn't implement iface: the exception is thrown in managed code */
2114 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2117 len = mono_class_num_methods (iclass);
2118 ioffset = mono_class_interface_offset (class, iclass);
2119 domain = mono_object_domain (type);
2120 *targets = mono_array_new (domain, mono_defaults.method_info_class, len);
2121 *methods = mono_array_new (domain, mono_defaults.method_info_class, len);
2124 while ((method = mono_class_get_methods (iclass, &iter))) {
2125 member = mono_method_get_object (domain, method, iclass);
2126 mono_array_setref (*methods, i, member);
2127 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2128 mono_array_setref (*targets, i, member);
2135 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2137 MonoClass *klass = mono_class_from_mono_type (type->type);
2139 if (klass->image->dynamic) {
2140 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2141 *packing = tb->packing_size;
2142 *size = tb->class_size;
2144 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2148 static MonoReflectionType*
2149 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2153 MONO_ARCH_SAVE_REGS;
2155 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2156 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2158 class = mono_class_from_mono_type (type->type);
2160 // GetElementType should only return a type for:
2161 // Array Pointer PassedByRef
2162 if (type->type->byref)
2163 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2164 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2165 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2166 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2167 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2172 static MonoReflectionType*
2173 ves_icall_get_type_parent (MonoReflectionType *type)
2175 MonoClass *class = mono_class_from_mono_type (type->type);
2177 MONO_ARCH_SAVE_REGS;
2179 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2183 ves_icall_type_ispointer (MonoReflectionType *type)
2185 MONO_ARCH_SAVE_REGS;
2187 return type->type->type == MONO_TYPE_PTR;
2191 ves_icall_type_isprimitive (MonoReflectionType *type)
2193 MONO_ARCH_SAVE_REGS;
2195 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)));
2199 ves_icall_type_isbyref (MonoReflectionType *type)
2201 MONO_ARCH_SAVE_REGS;
2203 return type->type->byref;
2207 ves_icall_type_iscomobject (MonoReflectionType *type)
2209 MonoClass *klass = mono_class_from_mono_type (type->type);
2210 MONO_ARCH_SAVE_REGS;
2212 return (klass && klass->is_com_object);
2215 static MonoReflectionModule*
2216 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2218 MonoClass *class = mono_class_from_mono_type (type->type);
2220 MONO_ARCH_SAVE_REGS;
2222 return mono_module_get_object (mono_object_domain (type), class->image);
2225 static MonoReflectionAssembly*
2226 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2228 MonoDomain *domain = mono_domain_get ();
2229 MonoClass *class = mono_class_from_mono_type (type->type);
2231 MONO_ARCH_SAVE_REGS;
2233 return mono_assembly_get_object (domain, class->image->assembly);
2236 static MonoReflectionType*
2237 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2239 MonoDomain *domain = mono_domain_get ();
2242 MONO_ARCH_SAVE_REGS;
2244 if (type->type->byref)
2246 if (type->type->type == MONO_TYPE_VAR)
2247 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2248 else if (type->type->type == MONO_TYPE_MVAR)
2249 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2251 class = mono_class_from_mono_type (type->type)->nested_in;
2253 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2256 static MonoReflectionType*
2257 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2259 MonoDomain *domain = mono_domain_get ();
2260 MonoClass *class = mono_class_from_mono_type (type->type);
2262 MONO_ARCH_SAVE_REGS;
2264 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2265 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2266 else if (class->element_class)
2267 return mono_type_get_object (domain, &class->element_class->byval_arg);
2273 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2275 MonoDomain *domain = mono_domain_get ();
2276 MonoClass *class = mono_class_from_mono_type (type->type);
2278 MONO_ARCH_SAVE_REGS;
2280 if (type->type->byref) {
2281 char *n = g_strdup_printf ("%s&", class->name);
2282 MonoString *res = mono_string_new (domain, n);
2288 return mono_string_new (domain, class->name);
2293 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2295 MonoDomain *domain = mono_domain_get ();
2296 MonoClass *class = mono_class_from_mono_type (type->type);
2298 MONO_ARCH_SAVE_REGS;
2300 while (class->nested_in)
2301 class = class->nested_in;
2303 if (class->name_space [0] == '\0')
2306 return mono_string_new (domain, class->name_space);
2310 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2312 MonoClass *class = mono_class_from_mono_type (type->type);
2314 MONO_ARCH_SAVE_REGS;
2320 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2323 MonoClass *klass, *pklass;
2324 MonoDomain *domain = mono_object_domain (type);
2325 MonoVTable *array_vtable = mono_class_vtable (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1));
2327 MONO_ARCH_SAVE_REGS;
2329 klass = mono_class_from_mono_type (type->type);
2331 if (klass->generic_container) {
2332 MonoGenericContainer *container = klass->generic_container;
2333 res = mono_array_new_specific (array_vtable, container->type_argc);
2334 for (i = 0; i < container->type_argc; ++i) {
2335 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2336 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2338 } else if (klass->generic_class) {
2339 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2340 res = mono_array_new_specific (array_vtable, inst->type_argc);
2341 for (i = 0; i < inst->type_argc; ++i)
2342 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2344 res = mono_array_new_specific (array_vtable, 0);
2350 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2353 MONO_ARCH_SAVE_REGS;
2355 if (!IS_MONOTYPE (type))
2358 if (type->type->byref)
2361 klass = mono_class_from_mono_type (type->type);
2363 return klass->generic_container != NULL;
2366 static MonoReflectionType*
2367 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2370 MONO_ARCH_SAVE_REGS;
2372 if (type->type->byref)
2375 klass = mono_class_from_mono_type (type->type);
2376 if (klass->generic_container) {
2377 return type; /* check this one */
2379 if (klass->generic_class) {
2380 MonoClass *generic_class = klass->generic_class->container_class;
2382 if (generic_class->wastypebuilder && generic_class->reflection_info)
2383 return generic_class->reflection_info;
2385 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2390 static MonoReflectionType*
2391 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2393 MonoType *geninst, **types;
2396 MONO_ARCH_SAVE_REGS;
2398 count = mono_array_length (type_array);
2399 types = g_new0 (MonoType *, count);
2401 for (i = 0; i < count; i++) {
2402 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2403 types [i] = t->type;
2406 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2411 return mono_type_get_object (mono_object_domain (type), geninst);
2415 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2418 MONO_ARCH_SAVE_REGS;
2420 if (type->type->byref)
2423 klass = mono_class_from_mono_type (type->type);
2424 return klass->generic_class != NULL;
2428 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2431 MONO_ARCH_SAVE_REGS;
2433 if (!IS_MONOTYPE (type))
2436 if (type->type->byref)
2439 klass = mono_class_from_mono_type (type->type);
2440 return klass->generic_class != NULL || klass->generic_container != NULL;
2444 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2446 MONO_ARCH_SAVE_REGS;
2448 if (!IS_MONOTYPE (type))
2451 if (is_generic_parameter (type->type))
2452 return mono_type_get_generic_param_num (type->type);
2456 static GenericParameterAttributes
2457 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2459 MONO_ARCH_SAVE_REGS;
2461 g_assert (IS_MONOTYPE (type));
2462 g_assert (is_generic_parameter (type->type));
2463 return mono_generic_param_info (type->type->data.generic_param)->flags;
2467 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2469 MonoGenericParamInfo *param_info;
2475 MONO_ARCH_SAVE_REGS;
2477 g_assert (IS_MONOTYPE (type));
2479 domain = mono_object_domain (type);
2480 param_info = mono_generic_param_info (type->type->data.generic_param);
2481 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2484 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2485 for (i = 0; i < count; i++)
2486 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2493 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2495 MONO_ARCH_SAVE_REGS;
2496 return is_generic_parameter (type->type);
2500 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2502 MONO_ARCH_SAVE_REGS;
2503 return is_generic_parameter (tb->type.type);
2507 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2508 MonoReflectionType *t)
2510 enumtype->type = t->type;
2513 static MonoReflectionType*
2514 ves_icall_MonoGenericClass_GetParentType (MonoReflectionGenericClass *type)
2516 MonoDynamicGenericClass *gclass;
2517 MonoReflectionType *parent = NULL, *res;
2523 MONO_ARCH_SAVE_REGS;
2525 g_assert (type->type.type->data.generic_class->is_dynamic);
2526 gclass = (MonoDynamicGenericClass *) type->type.type->data.generic_class;
2528 domain = mono_object_domain (type);
2529 klass = mono_class_from_mono_type (type->generic_type->type.type);
2531 if (!klass->generic_class && !klass->generic_container)
2534 parent = monotype_cast (type->generic_type->parent);
2536 if (!parent || (parent->type->type != MONO_TYPE_GENERICINST))
2539 inflated = mono_class_inflate_generic_type (
2540 parent->type, mono_generic_class_get_context ((MonoGenericClass *) gclass));
2542 res = mono_type_get_object (domain, inflated);
2543 mono_metadata_free_type (inflated);
2548 ves_icall_MonoGenericClass_GetInterfaces (MonoReflectionGenericClass *type)
2550 static MonoClass *System_Reflection_MonoGenericClass;
2551 MonoGenericClass *gclass;
2552 MonoReflectionTypeBuilder *tb = NULL;
2553 MonoClass *klass = NULL;
2558 MONO_ARCH_SAVE_REGS;
2560 if (!System_Reflection_MonoGenericClass) {
2561 System_Reflection_MonoGenericClass = mono_class_from_name (
2562 mono_defaults.corlib, "System.Reflection", "MonoGenericClass");
2563 g_assert (System_Reflection_MonoGenericClass);
2566 domain = mono_object_domain (type);
2568 gclass = type->type.type->data.generic_class;
2569 g_assert (gclass->is_dynamic);
2571 tb = type->generic_type;
2572 icount = tb->interfaces ? mono_array_length (tb->interfaces) : 0;
2574 res = mono_array_new (domain, System_Reflection_MonoGenericClass, icount);
2576 for (i = 0; i < icount; i++) {
2577 MonoReflectionType *iface;
2581 iface = mono_array_get (tb->interfaces, MonoReflectionType *, i);
2584 it = &klass->interfaces [i]->byval_arg;
2586 it = mono_class_inflate_generic_type (it, mono_generic_class_get_context (gclass));
2588 iface = mono_type_get_object (domain, it);
2589 mono_array_setref (res, i, iface);
2590 mono_metadata_free_type (it);
2596 static MonoReflectionMethod*
2597 ves_icall_MonoGenericClass_GetCorrespondingInflatedMethod (MonoReflectionGenericClass *type,
2598 MonoReflectionMethod* generic)
2600 MonoGenericClass *gclass;
2601 MonoDynamicGenericClass *dgclass;
2605 MONO_ARCH_SAVE_REGS;
2607 gclass = type->type.type->data.generic_class;
2608 g_assert (gclass->is_dynamic);
2610 dgclass = (MonoDynamicGenericClass *) gclass;
2612 domain = mono_object_domain (type);
2614 for (i = 0; i < dgclass->count_methods; i++)
2615 if (generic->method->token == dgclass->methods [i]->token)
2616 return mono_method_get_object (domain, dgclass->methods [i], NULL);
2621 static MonoReflectionMethod*
2622 ves_icall_MonoGenericClass_GetCorrespondingInflatedConstructor (MonoReflectionGenericClass *type,
2623 MonoReflectionMethod* generic)
2625 MonoGenericClass *gclass;
2626 MonoDynamicGenericClass *dgclass;
2630 MONO_ARCH_SAVE_REGS;
2632 gclass = type->type.type->data.generic_class;
2633 g_assert (gclass->is_dynamic);
2635 dgclass = (MonoDynamicGenericClass *) gclass;
2637 domain = mono_object_domain (type);
2639 for (i = 0; i < dgclass->count_ctors; i++)
2640 if (generic->method->token == dgclass->ctors [i]->token)
2641 return mono_method_get_object (domain, dgclass->ctors [i], NULL);
2647 static MonoReflectionField*
2648 ves_icall_MonoGenericClass_GetCorrespondingInflatedField (MonoReflectionGenericClass *type,
2649 MonoString* generic_name)
2651 MonoGenericClass *gclass;
2652 MonoDynamicGenericClass *dgclass;
2654 MonoClass *refclass;
2655 char *utf8_name = mono_string_to_utf8 (generic_name);
2658 MONO_ARCH_SAVE_REGS;
2660 gclass = type->type.type->data.generic_class;
2661 g_assert (gclass->is_dynamic);
2663 dgclass = (MonoDynamicGenericClass *) gclass;
2665 refclass = mono_class_from_mono_type (type->type.type);
2667 domain = mono_object_domain (type);
2669 for (i = 0; i < dgclass->count_fields; i++)
2670 if (strcmp (utf8_name, mono_field_get_name (&dgclass->fields [i])) == 0) {
2672 return mono_field_get_object (domain, refclass, &dgclass->fields [i]);
2681 static MonoReflectionMethod*
2682 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2683 MonoReflectionMethod* generic)
2690 MONO_ARCH_SAVE_REGS;
2692 domain = ((MonoObject *)type)->vtable->domain;
2694 klass = mono_class_from_mono_type (type->type);
2697 while ((method = mono_class_get_methods (klass, &iter))) {
2698 if (method->token == generic->method->token)
2699 return mono_method_get_object (domain, method, klass);
2706 ves_icall_MonoGenericClass_GetMethods (MonoReflectionGenericClass *type,
2707 MonoReflectionType *reflected_type)
2709 MonoGenericClass *gclass;
2710 MonoDynamicGenericClass *dgclass;
2712 MonoClass *refclass;
2716 MONO_ARCH_SAVE_REGS;
2718 gclass = type->type.type->data.generic_class;
2719 g_assert (gclass->is_dynamic);
2720 dgclass = (MonoDynamicGenericClass *) gclass;
2722 refclass = mono_class_from_mono_type (reflected_type->type);
2724 domain = mono_object_domain (type);
2725 res = mono_array_new (domain, mono_defaults.method_info_class, dgclass->count_methods);
2727 for (i = 0; i < dgclass->count_methods; i++)
2728 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->methods [i], refclass));
2734 ves_icall_MonoGenericClass_GetConstructors (MonoReflectionGenericClass *type,
2735 MonoReflectionType *reflected_type)
2737 static MonoClass *System_Reflection_ConstructorInfo;
2738 MonoGenericClass *gclass;
2739 MonoDynamicGenericClass *dgclass;
2741 MonoClass *refclass;
2745 MONO_ARCH_SAVE_REGS;
2747 if (!System_Reflection_ConstructorInfo)
2748 System_Reflection_ConstructorInfo = mono_class_from_name (
2749 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
2751 gclass = type->type.type->data.generic_class;
2752 g_assert (gclass->is_dynamic);
2753 dgclass = (MonoDynamicGenericClass *) gclass;
2755 refclass = mono_class_from_mono_type (reflected_type->type);
2757 domain = mono_object_domain (type);
2758 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, dgclass->count_ctors);
2760 for (i = 0; i < dgclass->count_ctors; i++)
2761 mono_array_setref (res, i, mono_method_get_object (domain, dgclass->ctors [i], refclass));
2767 ves_icall_MonoGenericClass_GetFields (MonoReflectionGenericClass *type,
2768 MonoReflectionType *reflected_type)
2770 MonoGenericClass *gclass;
2771 MonoDynamicGenericClass *dgclass;
2773 MonoClass *refclass;
2777 MONO_ARCH_SAVE_REGS;
2779 gclass = type->type.type->data.generic_class;
2780 g_assert (gclass->is_dynamic);
2781 dgclass = (MonoDynamicGenericClass *) gclass;
2783 refclass = mono_class_from_mono_type (reflected_type->type);
2785 domain = mono_object_domain (type);
2786 res = mono_array_new (domain, mono_defaults.field_info_class, dgclass->count_fields);
2788 for (i = 0; i < dgclass->count_fields; i++)
2789 mono_array_setref (res, i, mono_field_get_object (domain, refclass, &dgclass->fields [i]));
2795 ves_icall_MonoGenericClass_GetProperties (MonoReflectionGenericClass *type,
2796 MonoReflectionType *reflected_type)
2798 static MonoClass *System_Reflection_PropertyInfo;
2799 MonoGenericClass *gclass;
2800 MonoDynamicGenericClass *dgclass;
2802 MonoClass *refclass;
2806 MONO_ARCH_SAVE_REGS;
2808 if (!System_Reflection_PropertyInfo)
2809 System_Reflection_PropertyInfo = mono_class_from_name (
2810 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
2812 gclass = type->type.type->data.generic_class;
2813 g_assert (gclass->is_dynamic);
2814 dgclass = (MonoDynamicGenericClass *) gclass;
2816 refclass = mono_class_from_mono_type (reflected_type->type);
2818 domain = mono_object_domain (type);
2819 res = mono_array_new (domain, System_Reflection_PropertyInfo, dgclass->count_properties);
2821 for (i = 0; i < dgclass->count_properties; i++)
2822 mono_array_setref (res, i, mono_property_get_object (domain, refclass, &dgclass->properties [i]));
2828 ves_icall_MonoGenericClass_GetEvents (MonoReflectionGenericClass *type,
2829 MonoReflectionType *reflected_type)
2831 static MonoClass *System_Reflection_EventInfo;
2832 MonoGenericClass *gclass;
2833 MonoDynamicGenericClass *dgclass;
2835 MonoClass *refclass;
2839 MONO_ARCH_SAVE_REGS;
2841 if (!System_Reflection_EventInfo)
2842 System_Reflection_EventInfo = mono_class_from_name (
2843 mono_defaults.corlib, "System.Reflection", "EventInfo");
2845 gclass = type->type.type->data.generic_class;
2846 g_assert (gclass->is_dynamic);
2847 dgclass = (MonoDynamicGenericClass *) gclass;
2849 refclass = mono_class_from_mono_type (reflected_type->type);
2851 domain = mono_object_domain (type);
2852 res = mono_array_new (domain, System_Reflection_EventInfo, dgclass->count_events);
2854 for (i = 0; i < dgclass->count_events; i++)
2855 mono_array_setref (res, i, mono_event_get_object (domain, refclass, &dgclass->events [i]));
2860 static MonoReflectionType*
2861 ves_icall_MonoGenericClass_InflateType (MonoReflectionGenericClass *type,
2862 MonoReflectionType *target)
2866 MonoReflectionType *res;
2868 MONO_ARCH_SAVE_REGS;
2870 gklass = mono_class_from_mono_type (type->type.type);
2871 res_type = mono_class_inflate_generic_type (target->type, mono_class_get_context (gklass));
2872 res = mono_type_get_object (mono_object_domain (type), res_type);
2873 mono_metadata_free_type (res_type);
2877 static MonoReflectionMethod *
2878 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *type)
2883 MONO_ARCH_SAVE_REGS;
2885 if (type->type->byref || type->type->type != MONO_TYPE_MVAR)
2888 method = mono_type_get_generic_param_owner (type->type)->owner.method;
2890 klass = mono_class_from_mono_type (type->type);
2891 return mono_method_get_object (mono_object_domain (type), method, klass);
2894 static MonoReflectionDllImportAttribute*
2895 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2897 static MonoClass *DllImportAttributeClass = NULL;
2898 MonoDomain *domain = mono_domain_get ();
2899 MonoReflectionDllImportAttribute *attr;
2900 MonoImage *image = method->klass->image;
2901 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2902 MonoTableInfo *tables = image->tables;
2903 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2904 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2905 guint32 im_cols [MONO_IMPLMAP_SIZE];
2906 guint32 scope_token;
2907 const char *import = NULL;
2908 const char *scope = NULL;
2911 if (!method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL)
2914 if (!DllImportAttributeClass) {
2915 DllImportAttributeClass =
2916 mono_class_from_name (mono_defaults.corlib,
2917 "System.Runtime.InteropServices", "DllImportAttribute");
2918 g_assert (DllImportAttributeClass);
2921 if (method->klass->image->dynamic) {
2922 MonoReflectionMethodAux *method_aux =
2923 g_hash_table_lookup (
2924 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2926 import = method_aux->dllentry;
2927 scope = method_aux->dll;
2931 if (piinfo->implmap_idx) {
2932 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2934 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2935 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2936 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2937 scope = mono_metadata_string_heap (image, scope_token);
2940 flags = piinfo->piflags;
2942 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2944 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2945 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2946 attr->call_conv = (flags & 0x700) >> 8;
2947 attr->charset = ((flags & 0x6) >> 1) + 1;
2948 if (attr->charset == 1)
2950 attr->exact_spelling = (flags & 0x1) != 0;
2951 attr->set_last_error = (flags & 0x40) != 0;
2952 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2953 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2954 attr->preserve_sig = FALSE;
2959 static MonoReflectionMethod *
2960 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2962 MonoMethodInflated *imethod;
2965 MONO_ARCH_SAVE_REGS;
2967 if (method->method->is_generic)
2970 if (!method->method->is_inflated)
2973 imethod = (MonoMethodInflated *) method->method;
2975 result = imethod->declaring;
2976 /* Not a generic method. */
2977 if (!result->is_generic)
2980 if (method->method->klass->image->dynamic) {
2981 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2982 MonoReflectionMethod *res;
2985 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2986 * the dynamic case as well ?
2988 mono_loader_lock ();
2989 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2990 mono_loader_unlock ();
2996 if (imethod->context.class_inst) {
2997 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2998 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
3001 return mono_method_get_object (mono_object_domain (method), result, NULL);
3005 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
3007 MONO_ARCH_SAVE_REGS;
3009 return mono_method_signature (method->method)->generic_param_count != 0;
3013 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
3015 MONO_ARCH_SAVE_REGS;
3017 return method->method->is_generic;
3021 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
3026 MONO_ARCH_SAVE_REGS;
3028 domain = mono_object_domain (method);
3030 if (method->method->is_inflated) {
3031 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
3034 count = inst->type_argc;
3035 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3037 for (i = 0; i < count; i++)
3038 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
3044 count = mono_method_signature (method->method)->generic_param_count;
3045 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
3047 for (i = 0; i < count; i++) {
3048 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
3049 MonoGenericParam *param = mono_generic_container_get_param (container, i);
3050 MonoClass *pklass = mono_class_from_generic_parameter (
3051 param, method->method->klass->image, TRUE);
3052 mono_array_setref (res, i,
3053 mono_type_get_object (domain, &pklass->byval_arg));
3060 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
3063 * Invoke from reflection is supposed to always be a virtual call (the API
3064 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
3065 * greater flexibility.
3067 MonoMethod *m = method->method;
3071 MONO_ARCH_SAVE_REGS;
3075 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
3076 mono_security_core_clr_ensure_reflection_access_method (m);
3078 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
3080 if (!mono_object_isinst (this, m->klass)) {
3081 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type.");
3084 m = mono_object_get_virtual_method (this, m);
3085 /* must pass the pointer to the value for valuetype methods */
3086 if (m->klass->valuetype)
3087 obj = mono_object_unbox (this);
3088 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
3089 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target.");
3094 pcount = params? mono_array_length (params): 0;
3095 if (pcount != mono_method_signature (m)->param_count) {
3096 *exc = mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException");
3100 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
3101 *exc = mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class.");
3105 if (m->klass->image->assembly->ref_only) {
3106 *exc = mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api.");
3110 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
3112 mono_array_size_t *lengths;
3113 mono_array_size_t *lower_bounds;
3114 pcount = mono_array_length (params);
3115 lengths = alloca (sizeof (mono_array_size_t) * pcount);
3116 for (i = 0; i < pcount; ++i)
3117 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
3119 if (m->klass->rank == pcount) {
3120 /* Only lengths provided. */
3121 lower_bounds = NULL;
3123 g_assert (pcount == (m->klass->rank * 2));
3124 /* lower bounds are first. */
3125 lower_bounds = lengths;
3126 lengths += m->klass->rank;
3129 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
3131 return mono_runtime_invoke_array (m, obj, params, NULL);
3135 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
3137 MonoDomain *domain = mono_object_domain (method);
3138 MonoMethod *m = method->method;
3139 MonoMethodSignature *sig = mono_method_signature (m);
3140 MonoArray *out_args;
3142 int i, j, outarg_count = 0;
3144 MONO_ARCH_SAVE_REGS;
3146 if (m->klass == mono_defaults.object_class) {
3148 if (!strcmp (m->name, "FieldGetter")) {
3149 MonoClass *k = this->vtable->klass;
3153 /* If this is a proxy, then it must be a CBO */
3154 if (k == mono_defaults.transparent_proxy_class) {
3155 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3156 this = tp->rp->unwrapped_server;
3158 k = this->vtable->klass;
3161 name = mono_array_get (params, MonoString *, 1);
3162 str = mono_string_to_utf8 (name);
3165 MonoClassField* field = mono_class_get_field_from_name (k, str);
3167 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3168 if (field_klass->valuetype)
3169 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
3171 result = *((gpointer *)((char *)this + field->offset));
3173 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
3174 *outArgs = out_args;
3175 mono_array_setref (out_args, 0, result);
3183 g_assert_not_reached ();
3185 } else if (!strcmp (m->name, "FieldSetter")) {
3186 MonoClass *k = this->vtable->klass;
3192 /* If this is a proxy, then it must be a CBO */
3193 if (k == mono_defaults.transparent_proxy_class) {
3194 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
3195 this = tp->rp->unwrapped_server;
3197 k = this->vtable->klass;
3200 name = mono_array_get (params, MonoString *, 1);
3201 str = mono_string_to_utf8 (name);
3204 MonoClassField* field = mono_class_get_field_from_name (k, str);
3206 MonoClass *field_klass = mono_class_from_mono_type (field->type);
3207 MonoObject *val = mono_array_get (params, gpointer, 2);
3209 if (field_klass->valuetype) {
3210 size = mono_type_size (field->type, &align);
3212 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
3214 memcpy ((char *)this + field->offset,
3215 ((char *)val) + sizeof (MonoObject), size);
3217 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
3220 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
3221 *outArgs = out_args;
3231 g_assert_not_reached ();
3236 for (i = 0; i < mono_array_length (params); i++) {
3237 if (sig->params [i]->byref)
3241 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
3243 /* handle constructors only for objects already allocated */
3244 if (!strcmp (method->method->name, ".ctor"))
3247 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
3248 g_assert (!method->method->klass->valuetype);
3249 result = mono_runtime_invoke_array (method->method, this, params, NULL);
3251 for (i = 0, j = 0; i < mono_array_length (params); i++) {
3252 if (sig->params [i]->byref) {
3254 arg = mono_array_get (params, gpointer, i);
3255 mono_array_setref (out_args, j, arg);
3260 *outArgs = out_args;
3266 read_enum_value (char *mem, int type)
3270 return *(guint8*)mem;
3272 return *(gint8*)mem;
3274 return *(guint16*)mem;
3276 return *(gint16*)mem;
3278 return *(guint32*)mem;
3280 return *(gint32*)mem;
3282 return *(guint64*)mem;
3284 return *(gint64*)mem;
3286 g_assert_not_reached ();
3292 write_enum_value (char *mem, int type, guint64 value)
3296 case MONO_TYPE_I1: {
3297 guint8 *p = (guint8*)mem;
3302 case MONO_TYPE_I2: {
3303 guint16 *p = (void*)mem;
3308 case MONO_TYPE_I4: {
3309 guint32 *p = (void*)mem;
3314 case MONO_TYPE_I8: {
3315 guint64 *p = (void*)mem;
3320 g_assert_not_reached ();
3326 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3329 MonoClass *enumc, *objc;
3333 MONO_ARCH_SAVE_REGS;
3335 MONO_CHECK_ARG_NULL (enumType);
3336 MONO_CHECK_ARG_NULL (value);
3338 domain = mono_object_domain (enumType);
3339 enumc = mono_class_from_mono_type (enumType->type);
3340 objc = value->vtable->klass;
3342 if (!enumc->enumtype)
3343 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3344 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3345 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."));
3347 res = mono_object_new (domain, enumc);
3348 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3349 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3355 ves_icall_System_Enum_get_value (MonoObject *this)
3363 MONO_ARCH_SAVE_REGS;
3368 g_assert (this->vtable->klass->enumtype);
3370 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3371 res = mono_object_new (mono_object_domain (this), enumc);
3372 dst = (char *)res + sizeof (MonoObject);
3373 src = (char *)this + sizeof (MonoObject);
3374 size = mono_class_value_size (enumc, NULL);
3376 memcpy (dst, src, size);
3381 static MonoReflectionType *
3382 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3384 MONO_ARCH_SAVE_REGS;
3386 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3390 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3392 gpointer tdata = (char *)this + sizeof (MonoObject);
3393 gpointer odata = (char *)other + sizeof (MonoObject);
3394 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3395 g_assert (basetype);
3397 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3398 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3399 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3402 return me > other ? 1 : -1; \
3405 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3406 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3407 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3410 return me - other; \
3413 switch (basetype->type) {
3415 COMPARE_ENUM_VALUES (guint8);
3417 COMPARE_ENUM_VALUES (gint8);
3418 case MONO_TYPE_CHAR:
3420 COMPARE_ENUM_VALUES_RANGE (guint16);
3422 COMPARE_ENUM_VALUES (gint16);
3424 COMPARE_ENUM_VALUES (guint32);
3426 COMPARE_ENUM_VALUES (gint32);
3428 COMPARE_ENUM_VALUES (guint64);
3430 COMPARE_ENUM_VALUES (gint64);
3432 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3434 #undef COMPARE_ENUM_VALUES_RANGE
3435 #undef COMPARE_ENUM_VALUES
3440 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3442 gpointer data = (char *)this + sizeof (MonoObject);
3443 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3444 g_assert (basetype);
3446 switch (basetype->type) {
3448 return *((gint8*)data);
3450 return *((guint8*)data);
3451 case MONO_TYPE_CHAR:
3453 return *((guint16*)data);
3456 return *((gint16*)data);
3458 return *((guint32*)data);
3460 return *((gint32*)data);
3462 case MONO_TYPE_I8: {
3463 gint64 value = *((gint64*)data);
3464 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3467 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3473 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3475 MonoDomain *domain = mono_object_domain (type);
3476 MonoClass *enumc = mono_class_from_mono_type (type->type);
3477 guint j = 0, nvalues, crow;
3479 MonoClassField *field;
3481 MONO_ARCH_SAVE_REGS;
3483 info->utype = mono_type_get_object (domain, mono_class_enum_basetype (enumc));
3484 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3485 info->names = mono_array_new (domain, mono_defaults.string_class, nvalues);
3486 info->values = mono_array_new (domain, enumc, nvalues);
3490 while ((field = mono_class_get_fields (enumc, &iter))) {
3493 MonoTypeEnum def_type;
3495 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3497 if (mono_field_is_deleted (field))
3499 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3501 p = mono_class_get_field_default_value (field, &def_type);
3502 len = mono_metadata_decode_blob_size (p, &p);
3503 switch (mono_class_enum_basetype (enumc)->type) {
3506 mono_array_set (info->values, gchar, j, *p);
3508 case MONO_TYPE_CHAR:
3511 mono_array_set (info->values, gint16, j, read16 (p));
3515 mono_array_set (info->values, gint32, j, read32 (p));
3519 mono_array_set (info->values, gint64, j, read64 (p));
3522 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3529 BFLAGS_IgnoreCase = 1,
3530 BFLAGS_DeclaredOnly = 2,
3531 BFLAGS_Instance = 4,
3533 BFLAGS_Public = 0x10,
3534 BFLAGS_NonPublic = 0x20,
3535 BFLAGS_FlattenHierarchy = 0x40,
3536 BFLAGS_InvokeMethod = 0x100,
3537 BFLAGS_CreateInstance = 0x200,
3538 BFLAGS_GetField = 0x400,
3539 BFLAGS_SetField = 0x800,
3540 BFLAGS_GetProperty = 0x1000,
3541 BFLAGS_SetProperty = 0x2000,
3542 BFLAGS_ExactBinding = 0x10000,
3543 BFLAGS_SuppressChangeType = 0x20000,
3544 BFLAGS_OptionalParamBinding = 0x40000
3547 static MonoReflectionField *
3548 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3551 MonoClass *startklass, *klass;
3553 MonoClassField *field;
3556 int (*compare_func) (const char *s1, const char *s2) = NULL;
3557 domain = ((MonoObject *)type)->vtable->domain;
3558 klass = startklass = mono_class_from_mono_type (type->type);
3560 MONO_ARCH_SAVE_REGS;
3563 mono_raise_exception (mono_get_exception_argument_null ("name"));
3564 if (type->type->byref)
3567 compare_func = (bflags & BFLAGS_IgnoreCase) ? g_strcasecmp : strcmp;
3570 if (klass->exception_type != MONO_EXCEPTION_NONE)
3571 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3574 while ((field = mono_class_get_fields (klass, &iter))) {
3577 if (field->type == NULL)
3579 if (mono_field_is_deleted (field))
3581 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3582 if (bflags & BFLAGS_Public)
3584 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3585 if (bflags & BFLAGS_NonPublic) {
3592 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3593 if (bflags & BFLAGS_Static)
3594 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3597 if (bflags & BFLAGS_Instance)
3604 utf8_name = mono_string_to_utf8 (name);
3606 if (compare_func (mono_field_get_name (field), utf8_name)) {
3612 return mono_field_get_object (domain, klass, field);
3614 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3621 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3624 MonoClass *startklass, *klass, *refklass;
3629 MonoClassField *field;
3630 MonoPtrArray tmp_array;
3632 MONO_ARCH_SAVE_REGS;
3634 domain = ((MonoObject *)type)->vtable->domain;
3635 if (type->type->byref)
3636 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3637 klass = startklass = mono_class_from_mono_type (type->type);
3638 refklass = mono_class_from_mono_type (reftype->type);
3640 mono_ptr_array_init (tmp_array, 2);
3643 if (klass->exception_type != MONO_EXCEPTION_NONE)
3644 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3647 while ((field = mono_class_get_fields (klass, &iter))) {
3649 if (mono_field_is_deleted (field))
3651 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3652 if (bflags & BFLAGS_Public)
3654 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3655 if (bflags & BFLAGS_NonPublic) {
3662 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3663 if (bflags & BFLAGS_Static)
3664 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3667 if (bflags & BFLAGS_Instance)
3673 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3674 mono_ptr_array_append (tmp_array, member);
3676 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3679 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3681 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3682 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3684 mono_ptr_array_destroy (tmp_array);
3690 method_nonpublic (MonoMethod* method, gboolean start_klass)
3692 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3693 case METHOD_ATTRIBUTE_ASSEM:
3694 return (start_klass || mono_defaults.generic_ilist_class);
3695 case METHOD_ATTRIBUTE_PRIVATE:
3697 case METHOD_ATTRIBUTE_PUBLIC:
3705 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3707 static MonoClass *MethodInfo_array;
3709 MonoClass *startklass, *klass, *refklass;
3714 int i, len, match, nslots;
3715 guint32 method_slots_default [8];
3716 guint32 *method_slots;
3717 gchar *mname = NULL;
3718 int (*compare_func) (const char *s1, const char *s2) = NULL;
3719 MonoVTable *array_vtable;
3720 MonoPtrArray tmp_array;
3722 MONO_ARCH_SAVE_REGS;
3724 mono_ptr_array_init (tmp_array, 4);
3726 if (!MethodInfo_array) {
3727 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3728 mono_memory_barrier ();
3729 MethodInfo_array = klass;
3732 domain = ((MonoObject *)type)->vtable->domain;
3733 array_vtable = mono_class_vtable (domain, MethodInfo_array);
3734 if (type->type->byref)
3735 return mono_array_new_specific (array_vtable, 0);
3736 klass = startklass = mono_class_from_mono_type (type->type);
3737 refklass = mono_class_from_mono_type (reftype->type);
3740 mname = mono_string_to_utf8 (name);
3741 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3744 /* An optimization for calls made from Delegate:CreateDelegate () */
3745 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3746 method = mono_get_delegate_invoke (klass);
3748 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3750 res = mono_array_new_specific (array_vtable, 1);
3751 mono_array_setref (res, 0, member);
3756 mono_class_setup_vtable (klass);
3758 if (is_generic_parameter (type->type))
3759 nslots = klass->parent->vtable_size;
3761 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3762 if (nslots >= sizeof (method_slots_default) * 8) {
3763 method_slots = g_new0 (guint32, nslots / 32 + 1);
3765 method_slots = method_slots_default;
3766 memset (method_slots, 0, sizeof (method_slots_default));
3769 mono_class_setup_vtable (klass);
3770 if (klass->exception_type != MONO_EXCEPTION_NONE)
3771 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3774 while ((method = mono_class_get_methods (klass, &iter))) {
3776 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3778 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3779 if (bflags & BFLAGS_Public)
3781 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3787 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3788 if (bflags & BFLAGS_Static)
3789 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3792 if (bflags & BFLAGS_Instance)
3800 if (compare_func (mname, method->name))
3805 if (method->slot != -1) {
3806 g_assert (method->slot < nslots);
3807 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3809 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3812 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3814 mono_ptr_array_append (tmp_array, member);
3816 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3820 if (method_slots != method_slots_default)
3821 g_free (method_slots);
3823 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3825 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3826 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3828 mono_ptr_array_destroy (tmp_array);
3833 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3836 static MonoClass *System_Reflection_ConstructorInfo;
3837 MonoClass *startklass, *klass, *refklass;
3842 gpointer iter = NULL;
3843 MonoPtrArray tmp_array;
3845 MONO_ARCH_SAVE_REGS;
3847 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3849 domain = ((MonoObject *)type)->vtable->domain;
3850 if (type->type->byref)
3851 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3852 klass = startklass = mono_class_from_mono_type (type->type);
3853 refklass = mono_class_from_mono_type (reftype->type);
3855 if (klass->exception_type != MONO_EXCEPTION_NONE)
3856 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3858 if (!System_Reflection_ConstructorInfo)
3859 System_Reflection_ConstructorInfo = mono_class_from_name (
3860 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3863 while ((method = mono_class_get_methods (klass, &iter))) {
3865 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3867 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3868 if (bflags & BFLAGS_Public)
3871 if (bflags & BFLAGS_NonPublic)
3877 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3878 if (bflags & BFLAGS_Static)
3879 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3882 if (bflags & BFLAGS_Instance)
3888 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3890 mono_ptr_array_append (tmp_array, member);
3893 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3895 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3896 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3898 mono_ptr_array_destroy (tmp_array);
3904 property_hash (gconstpointer data)
3906 MonoProperty *prop = (MonoProperty*)data;
3908 return g_str_hash (prop->name);
3912 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3914 // Properties are hide-by-name-and-signature
3915 if (!g_str_equal (prop1->name, prop2->name))
3918 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3920 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3926 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3931 return method_nonpublic (accessor, start_klass);
3935 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3938 static MonoClass *System_Reflection_PropertyInfo;
3939 MonoClass *startklass, *klass;
3945 gchar *propname = NULL;
3946 int (*compare_func) (const char *s1, const char *s2) = NULL;
3948 GHashTable *properties;
3949 MonoPtrArray tmp_array;
3951 MONO_ARCH_SAVE_REGS;
3953 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3955 if (!System_Reflection_PropertyInfo)
3956 System_Reflection_PropertyInfo = mono_class_from_name (
3957 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3959 domain = ((MonoObject *)type)->vtable->domain;
3960 if (type->type->byref)
3961 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3962 klass = startklass = mono_class_from_mono_type (type->type);
3964 propname = mono_string_to_utf8 (name);
3965 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3968 mono_class_setup_vtable (klass);
3970 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3972 mono_class_setup_vtable (klass);
3973 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3974 g_hash_table_destroy (properties);
3977 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3981 while ((prop = mono_class_get_properties (klass, &iter))) {
3987 flags = method->flags;
3990 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3991 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3992 if (bflags & BFLAGS_Public)
3994 } else if (bflags & BFLAGS_NonPublic) {
3995 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3996 property_accessor_nonpublic(prop->set, startklass == klass)) {
4003 if (flags & METHOD_ATTRIBUTE_STATIC) {
4004 if (bflags & BFLAGS_Static)
4005 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4008 if (bflags & BFLAGS_Instance)
4017 if (compare_func (propname, prop->name))
4021 if (g_hash_table_lookup (properties, prop))
4024 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4026 g_hash_table_insert (properties, prop, prop);
4028 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4031 g_hash_table_destroy (properties);
4034 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4035 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4036 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4038 mono_ptr_array_destroy (tmp_array);
4043 static MonoReflectionEvent *
4044 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
4047 MonoClass *klass, *startklass;
4053 MONO_ARCH_SAVE_REGS;
4055 event_name = mono_string_to_utf8 (name);
4056 if (type->type->byref)
4058 klass = startklass = mono_class_from_mono_type (type->type);
4059 domain = mono_object_domain (type);
4062 if (klass->exception_type != MONO_EXCEPTION_NONE)
4063 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4066 while ((event = mono_class_get_events (klass, &iter))) {
4067 if (strcmp (event->name, event_name))
4070 method = event->add;
4072 method = event->remove;
4074 method = event->raise;
4076 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4077 if (!(bflags & BFLAGS_Public))
4080 if (!(bflags & BFLAGS_NonPublic))
4082 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4087 if (!(bflags & BFLAGS_NonPublic))
4090 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4091 if (!(bflags & BFLAGS_Static))
4093 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4096 if (!(bflags & BFLAGS_Instance))
4100 g_free (event_name);
4101 return mono_event_get_object (domain, startklass, event);
4104 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4107 g_free (event_name);
4112 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4115 static MonoClass *System_Reflection_EventInfo;
4116 MonoClass *startklass, *klass;
4123 MonoPtrArray tmp_array;
4125 MONO_ARCH_SAVE_REGS;
4127 mono_ptr_array_init (tmp_array, 4);
4129 if (!System_Reflection_EventInfo)
4130 System_Reflection_EventInfo = mono_class_from_name (
4131 mono_defaults.corlib, "System.Reflection", "EventInfo");
4133 domain = mono_object_domain (type);
4134 if (type->type->byref)
4135 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4136 klass = startklass = mono_class_from_mono_type (type->type);
4139 if (klass->exception_type != MONO_EXCEPTION_NONE)
4140 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4143 while ((event = mono_class_get_events (klass, &iter))) {
4145 method = event->add;
4147 method = event->remove;
4149 method = event->raise;
4151 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4152 if (bflags & BFLAGS_Public)
4154 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4155 if (bflags & BFLAGS_NonPublic)
4160 if (bflags & BFLAGS_NonPublic)
4166 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4167 if (bflags & BFLAGS_Static)
4168 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4171 if (bflags & BFLAGS_Instance)
4176 if (bflags & BFLAGS_Instance)
4180 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4182 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4185 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4187 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4188 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4190 mono_ptr_array_destroy (tmp_array);
4195 static MonoReflectionType *
4196 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4204 MONO_ARCH_SAVE_REGS;
4206 domain = ((MonoObject *)type)->vtable->domain;
4207 if (type->type->byref)
4209 klass = mono_class_from_mono_type (type->type);
4210 str = mono_string_to_utf8 (name);
4213 if (klass->exception_type != MONO_EXCEPTION_NONE)
4214 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4217 * If a nested type is generic, return its generic type definition.
4218 * Note that this means that the return value is essentially a
4219 * nested type of the generic type definition of @klass.
4221 * A note in MSDN claims that a generic type definition can have
4222 * nested types that aren't generic. In any case, the container of that
4223 * nested type would be the generic type definition.
4225 if (klass->generic_class)
4226 klass = klass->generic_class->container_class;
4229 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4231 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4232 if (bflags & BFLAGS_Public)
4235 if (bflags & BFLAGS_NonPublic)
4240 if (strcmp (nested->name, str) == 0){
4242 return mono_type_get_object (domain, &nested->byval_arg);
4245 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4252 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4261 MonoPtrArray tmp_array;
4263 MONO_ARCH_SAVE_REGS;
4265 domain = ((MonoObject *)type)->vtable->domain;
4266 if (type->type->byref)
4267 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4268 klass = mono_class_from_mono_type (type->type);
4269 if (klass->exception_type != MONO_EXCEPTION_NONE)
4270 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4273 * If a nested type is generic, return its generic type definition.
4274 * Note that this means that the return value is essentially the set
4275 * of nested types of the generic type definition of @klass.
4277 * A note in MSDN claims that a generic type definition can have
4278 * nested types that aren't generic. In any case, the container of that
4279 * nested type would be the generic type definition.
4281 if (klass->generic_class)
4282 klass = klass->generic_class->container_class;
4284 mono_ptr_array_init (tmp_array, 1);
4286 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4288 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4289 if (bflags & BFLAGS_Public)
4292 if (bflags & BFLAGS_NonPublic)
4297 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4298 mono_ptr_array_append (tmp_array, member);
4301 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4303 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4304 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4306 mono_ptr_array_destroy (tmp_array);
4311 static MonoReflectionType*
4312 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4315 MonoType *type = NULL;
4316 MonoTypeNameParse info;
4317 gboolean type_resolve;
4319 MONO_ARCH_SAVE_REGS;
4321 /* On MS.NET, this does not fire a TypeResolve event */
4322 type_resolve = TRUE;
4323 str = mono_string_to_utf8 (name);
4324 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4325 if (!mono_reflection_parse_type (str, &info)) {
4327 mono_reflection_free_type_info (&info);
4328 if (throwOnError) /* uhm: this is a parse error, though... */
4329 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4330 /*g_print ("failed parse\n");*/
4334 if (info.assembly.name) {
4336 mono_reflection_free_type_info (&info);
4338 /* 1.0 and 2.0 throw different exceptions */
4339 if (mono_defaults.generic_ilist_class)
4340 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4342 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4347 if (module != NULL) {
4349 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4354 if (assembly->assembly->dynamic) {
4355 /* Enumerate all modules */
4356 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4360 if (abuilder->modules) {
4361 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4362 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4363 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4369 if (!type && abuilder->loaded_modules) {
4370 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4371 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4372 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4379 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4381 mono_reflection_free_type_info (&info);
4383 MonoException *e = NULL;
4386 e = mono_get_exception_type_load (name, NULL);
4388 mono_loader_clear_error ();
4391 mono_raise_exception (e);
4396 if (type->type == MONO_TYPE_CLASS) {
4397 MonoClass *klass = mono_type_get_class (type);
4399 if (mono_is_security_manager_active () && !klass->exception_type)
4400 /* Some security problems are detected during generic vtable construction */
4401 mono_class_setup_vtable (klass);
4402 /* need to report exceptions ? */
4403 if (throwOnError && klass->exception_type) {
4404 /* report SecurityException (or others) that occured when loading the assembly */
4405 MonoException *exc = mono_class_get_exception_for_failure (klass);
4406 mono_loader_clear_error ();
4407 mono_raise_exception (exc);
4408 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4413 /* g_print ("got it\n"); */
4414 return mono_type_get_object (mono_object_domain (assembly), type);
4418 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4421 gchar *shadow_ini_file;
4424 /* Check for shadow-copied assembly */
4425 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4426 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4428 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4429 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4435 g_free (shadow_ini_file);
4436 if (content != NULL) {
4439 *filename = content;
4447 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4449 MonoDomain *domain = mono_object_domain (assembly);
4450 MonoAssembly *mass = assembly->assembly;
4451 MonoString *res = NULL;
4456 MONO_ARCH_SAVE_REGS;
4458 if (g_path_is_absolute (mass->image->name)) {
4459 absolute = g_strdup (mass->image->name);
4460 dirname = g_path_get_dirname (absolute);
4462 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4463 dirname = g_strdup (mass->basedir);
4466 replace_shadow_path (domain, dirname, &absolute);
4471 for (i = strlen (absolute) - 1; i >= 0; i--)
4472 if (absolute [i] == '\\')
4477 uri = g_filename_to_uri (absolute, NULL, NULL);
4479 const char *prepend = "file://";
4481 if (*absolute == '/' && *(absolute + 1) == '/') {
4484 prepend = "file:///";
4487 uri = g_strconcat (prepend, absolute, NULL);
4491 res = mono_string_new (domain, uri);
4499 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4501 MonoAssembly *mass = assembly->assembly;
4503 MONO_ARCH_SAVE_REGS;
4505 return mass->in_gac;
4508 static MonoReflectionAssembly*
4509 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4513 MonoImageOpenStatus status;
4515 MONO_ARCH_SAVE_REGS;
4517 name = mono_string_to_utf8 (mname);
4518 res = mono_assembly_load_with_partial_name (name, &status);
4524 return mono_assembly_get_object (mono_domain_get (), res);
4528 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4530 MonoDomain *domain = mono_object_domain (assembly);
4533 MONO_ARCH_SAVE_REGS;
4535 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4541 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4543 MONO_ARCH_SAVE_REGS;
4545 return assembly->assembly->ref_only;
4549 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4551 MonoDomain *domain = mono_object_domain (assembly);
4553 MONO_ARCH_SAVE_REGS;
4555 return mono_string_new (domain, assembly->assembly->image->version);
4558 static MonoReflectionMethod*
4559 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4561 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4563 MONO_ARCH_SAVE_REGS;
4567 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4570 static MonoReflectionModule*
4571 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4573 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4577 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4579 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4580 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4584 MONO_ARCH_SAVE_REGS;
4586 for (i = 0; i < table->rows; ++i) {
4587 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4588 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4594 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4596 static MonoClass *System_Version = NULL;
4597 static MonoMethod *create_version = NULL;
4601 if (!System_Version) {
4602 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4603 g_assert (System_Version);
4606 if (!create_version) {
4607 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4608 create_version = mono_method_desc_search_in_class (desc, System_Version);
4609 g_assert (create_version);
4610 mono_method_desc_free (desc);
4616 args [3] = &revision;
4617 result = mono_object_new (domain, System_Version);
4618 mono_runtime_invoke (create_version, result, args, NULL);
4624 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4626 static MonoClass *System_Reflection_AssemblyName;
4628 MonoDomain *domain = mono_object_domain (assembly);
4630 static MonoMethod *create_culture = NULL;
4631 MonoImage *image = assembly->assembly->image;
4634 MONO_ARCH_SAVE_REGS;
4636 if (!System_Reflection_AssemblyName)
4637 System_Reflection_AssemblyName = mono_class_from_name (
4638 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4640 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4643 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4645 if (count > 0 && !create_culture) {
4646 MonoMethodDesc *desc = mono_method_desc_new (
4647 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4648 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4649 g_assert (create_culture);
4650 mono_method_desc_free (desc);
4653 for (i = 0; i < count; i++) {
4654 MonoReflectionAssemblyName *aname;
4655 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4657 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4659 aname = (MonoReflectionAssemblyName *) mono_object_new (
4660 domain, System_Reflection_AssemblyName);
4662 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4664 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4665 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4666 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4667 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4668 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4669 aname->versioncompat = 1; /* SameMachine (default) */
4670 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4671 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4673 if (create_culture) {
4675 MonoBoolean assembly_ref = 1;
4676 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4677 args [1] = &assembly_ref;
4678 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4681 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4682 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4683 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4685 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4686 /* public key token isn't copied - the class library will
4687 automatically generate it from the public key if required */
4688 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4689 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4691 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4692 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4695 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4698 /* note: this function doesn't return the codebase on purpose (i.e. it can
4699 be used under partial trust as path information isn't present). */
4701 mono_array_setref (result, i, aname);
4712 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4714 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4716 mono_array_setref (info->res, info->idx, name);
4721 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4723 MonoImage *img = assembly->assembly->image;
4727 MONO_ARCH_SAVE_REGS;
4729 if (!img->name_cache)
4730 mono_image_init_name_cache (img);
4732 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4735 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4740 /* move this in some file in mono/util/ */
4742 g_concat_dir_and_file (const char *dir, const char *file)
4744 g_return_val_if_fail (dir != NULL, NULL);
4745 g_return_val_if_fail (file != NULL, NULL);
4748 * If the directory name doesn't have a / on the end, we need
4749 * to add one so we get a proper path to the file
4751 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4752 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4754 return g_strconcat (dir, file, NULL);
4758 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4760 char *n = mono_string_to_utf8 (name);
4761 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4763 guint32 cols [MONO_MANIFEST_SIZE];
4764 guint32 impl, file_idx;
4768 MONO_ARCH_SAVE_REGS;
4770 for (i = 0; i < table->rows; ++i) {
4771 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4772 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4773 if (strcmp (val, n) == 0)
4777 if (i == table->rows)
4780 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4783 * this code should only be called after obtaining the
4784 * ResourceInfo and handling the other cases.
4786 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4787 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4789 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4794 module = assembly->assembly->image;
4796 *ref_module = mono_module_get_object (mono_domain_get (), module);
4798 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4802 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4804 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4806 guint32 cols [MONO_MANIFEST_SIZE];
4807 guint32 file_cols [MONO_FILE_SIZE];
4811 MONO_ARCH_SAVE_REGS;
4813 n = mono_string_to_utf8 (name);
4814 for (i = 0; i < table->rows; ++i) {
4815 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4816 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4817 if (strcmp (val, n) == 0)
4821 if (i == table->rows)
4824 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4825 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4828 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4829 case MONO_IMPLEMENTATION_FILE:
4830 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4831 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4832 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4833 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4834 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4835 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4838 info->location = RESOURCE_LOCATION_EMBEDDED;
4841 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4842 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4843 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4844 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4845 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4846 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4848 mono_raise_exception (ex);
4850 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4852 /* Obtain info recursively */
4853 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4854 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4857 case MONO_IMPLEMENTATION_EXP_TYPE:
4858 g_assert_not_reached ();
4867 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4869 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4870 MonoArray *result = NULL;
4875 MONO_ARCH_SAVE_REGS;
4877 /* check hash if needed */
4879 n = mono_string_to_utf8 (name);
4880 for (i = 0; i < table->rows; ++i) {
4881 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4882 if (strcmp (val, n) == 0) {
4885 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4886 fn = mono_string_new (mono_object_domain (assembly), n);
4888 return (MonoObject*)fn;
4896 for (i = 0; i < table->rows; ++i) {
4897 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4901 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4904 for (i = 0; i < table->rows; ++i) {
4905 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4906 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4907 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4908 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4913 return (MonoObject*)result;
4917 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4919 MonoDomain *domain = mono_domain_get();
4922 int i, j, file_count = 0;
4923 MonoImage **modules;
4924 guint32 module_count, real_module_count;
4925 MonoTableInfo *table;
4926 guint32 cols [MONO_FILE_SIZE];
4927 MonoImage *image = assembly->assembly->image;
4929 g_assert (image != NULL);
4930 g_assert (!assembly->assembly->dynamic);
4932 table = &image->tables [MONO_TABLE_FILE];
4933 file_count = table->rows;
4935 modules = image->modules;
4936 module_count = image->module_count;
4938 real_module_count = 0;
4939 for (i = 0; i < module_count; ++i)
4941 real_module_count ++;
4943 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4944 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4946 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4948 for (i = 0; i < module_count; ++i)
4950 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4954 for (i = 0; i < file_count; ++i, ++j) {
4955 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4956 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4957 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4959 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4961 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4962 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4964 mono_array_setref (res, j, mono_module_get_object (domain, m));
4971 static MonoReflectionMethod*
4972 ves_icall_GetCurrentMethod (void)
4974 MonoMethod *m = mono_method_get_last_managed ();
4976 MONO_ARCH_SAVE_REGS;
4978 return mono_method_get_object (mono_domain_get (), m, NULL);
4983 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4986 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4987 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4988 //method is inflated, we should inflate it on the other class
4989 MonoGenericContext ctx;
4990 ctx.method_inst = inflated->context.method_inst;
4991 ctx.class_inst = inflated->context.class_inst;
4992 if (klass->generic_class)
4993 ctx.class_inst = klass->generic_class->context.class_inst;
4994 else if (klass->generic_container)
4995 ctx.class_inst = klass->generic_container->context.class_inst;
4996 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4999 mono_class_setup_methods (method->klass);
5000 for (i = 0; i < method->klass->method.count; ++i) {
5001 if (method->klass->methods [i] == method) {
5006 mono_class_setup_methods (klass);
5007 g_assert (offset >= 0 && offset < klass->method.count);
5008 return klass->methods [offset];
5011 static MonoReflectionMethod*
5012 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5016 klass = mono_class_from_mono_type (type);
5017 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5019 if (method->klass != klass)
5020 method = mono_method_get_equivalent_method (method, klass);
5022 klass = method->klass;
5023 return mono_method_get_object (mono_domain_get (), method, klass);
5026 static MonoReflectionMethod*
5027 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
5029 return mono_method_get_object (mono_domain_get (), method, NULL);
5032 static MonoReflectionMethodBody*
5033 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5035 return mono_method_body_get_object (mono_domain_get (), method);
5038 static MonoReflectionAssembly*
5039 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5041 MonoMethod *dest = NULL;
5043 MONO_ARCH_SAVE_REGS;
5045 mono_stack_walk_no_il (get_executing, &dest);
5046 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5050 static MonoReflectionAssembly*
5051 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5053 MonoDomain* domain = mono_domain_get ();
5055 MONO_ARCH_SAVE_REGS;
5057 if (!domain->entry_assembly)
5060 return mono_assembly_get_object (domain, domain->entry_assembly);
5063 static MonoReflectionAssembly*
5064 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5069 MONO_ARCH_SAVE_REGS;
5072 mono_stack_walk_no_il (get_executing, &dest);
5074 mono_stack_walk_no_il (get_caller, &dest);
5077 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5081 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5082 gboolean assembly_qualified)
5084 MonoDomain *domain = mono_object_domain (object);
5085 MonoTypeNameFormat format;
5089 MONO_ARCH_SAVE_REGS;
5091 format = assembly_qualified ?
5092 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5093 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5095 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5097 name = mono_type_get_name_full (object->type, format);
5101 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5106 res = mono_string_new (domain, name);
5113 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5115 static MonoMethod *create_culture = NULL;
5118 const char *pkey_ptr;
5120 MonoBoolean assembly_ref = 0;
5122 MONO_ARCH_SAVE_REGS;
5124 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5125 aname->major = name->major;
5126 aname->minor = name->minor;
5127 aname->build = name->build;
5128 aname->flags = name->flags;
5129 aname->revision = name->revision;
5130 aname->hashalg = name->hash_alg;
5131 aname->versioncompat = 1; /* SameMachine (default) */
5133 if (by_default_version)
5134 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5137 if (absolute != NULL && *absolute != '\0') {
5138 const gchar *prepend = "file://";
5141 codebase = g_strdup (absolute);
5146 for (i = strlen (codebase) - 1; i >= 0; i--)
5147 if (codebase [i] == '\\')
5150 if (*codebase == '/' && *(codebase + 1) == '/') {
5153 prepend = "file:///";
5157 result = g_strconcat (prepend, codebase, NULL);
5163 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5167 if (!create_culture) {
5168 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5169 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5170 g_assert (create_culture);
5171 mono_method_desc_free (desc);
5174 if (name->culture) {
5175 args [0] = mono_string_new (domain, name->culture);
5176 args [1] = &assembly_ref;
5177 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5180 if (name->public_key) {
5181 pkey_ptr = (char*)name->public_key;
5182 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5184 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5185 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5186 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5187 } else if (default_publickey) {
5188 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5189 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5192 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5193 if (name->public_key_token [0]) {
5197 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5198 p = mono_array_addr (aname->keyToken, char, 0);
5200 for (i = 0, j = 0; i < 8; i++) {
5201 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5202 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5205 } else if (default_token) {
5206 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5211 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5213 MonoDomain *domain = mono_object_domain (assembly);
5214 MonoAssembly *mass = assembly->assembly;
5218 name = g_strdup_printf (
5219 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5221 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5222 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5223 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5224 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5226 res = mono_string_new (domain, name);
5233 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5236 MonoAssembly *mass = assembly->assembly;
5238 MONO_ARCH_SAVE_REGS;
5240 if (g_path_is_absolute (mass->image->name)) {
5241 fill_reflection_assembly_name (mono_object_domain (assembly),
5242 aname, &mass->aname, mass->image->name, TRUE,
5243 TRUE, mono_framework_version () >= 2);
5246 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5248 fill_reflection_assembly_name (mono_object_domain (assembly),
5249 aname, &mass->aname, absolute, TRUE, TRUE,
5250 mono_framework_version () >= 2);
5256 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5259 MonoImageOpenStatus status = MONO_IMAGE_OK;
5262 MonoAssemblyName name;
5265 MONO_ARCH_SAVE_REGS;
5267 filename = mono_string_to_utf8 (fname);
5269 dirname = g_path_get_dirname (filename);
5270 replace_shadow_path (mono_domain_get (), dirname, &filename);
5273 image = mono_image_open (filename, &status);
5279 if (status == MONO_IMAGE_IMAGE_INVALID)
5280 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5282 exc = mono_get_exception_file_not_found2 (NULL, fname);
5283 mono_raise_exception (exc);
5286 res = mono_assembly_fill_assembly_name (image, &name);
5288 mono_image_close (image);
5290 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5293 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5294 TRUE, mono_framework_version () == 1,
5295 mono_framework_version () >= 2);
5298 mono_image_close (image);
5302 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5303 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5305 MonoBoolean result = FALSE;
5306 MonoDeclSecurityEntry entry;
5308 /* SecurityAction.RequestMinimum */
5309 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5310 *minimum = entry.blob;
5311 *minLength = entry.size;
5314 /* SecurityAction.RequestOptional */
5315 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5316 *optional = entry.blob;
5317 *optLength = entry.size;
5320 /* SecurityAction.RequestRefuse */
5321 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5322 *refused = entry.blob;
5323 *refLength = entry.size;
5331 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5335 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5337 guint32 attrs, visibility;
5339 /* we start the count from 1 because we skip the special type <Module> */
5342 for (i = 1; i < tdef->rows; ++i) {
5343 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5344 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5345 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5349 count = tdef->rows - 1;
5351 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5352 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5354 for (i = 1; i < tdef->rows; ++i) {
5355 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5356 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5357 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5358 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5360 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5362 MonoLoaderError *error;
5365 error = mono_loader_get_last_error ();
5366 g_assert (error != NULL);
5368 ex = mono_loader_error_prepare_exception (error);
5369 mono_array_setref (*exceptions, count, ex);
5371 if (mono_loader_get_last_error ())
5372 mono_loader_clear_error ();
5381 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5383 MonoArray *res = NULL;
5384 MonoArray *exceptions = NULL;
5385 MonoImage *image = NULL;
5386 MonoTableInfo *table = NULL;
5389 int i, len, ex_count;
5391 MONO_ARCH_SAVE_REGS;
5393 domain = mono_object_domain (assembly);
5395 g_assert (!assembly->assembly->dynamic);
5396 image = assembly->assembly->image;
5397 table = &image->tables [MONO_TABLE_FILE];
5398 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5400 /* Append data from all modules in the assembly */
5401 for (i = 0; i < table->rows; ++i) {
5402 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5403 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5406 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5407 /* Append the new types to the end of the array */
5408 if (mono_array_length (res2) > 0) {
5410 MonoArray *res3, *ex3;
5412 len1 = mono_array_length (res);
5413 len2 = mono_array_length (res2);
5415 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5416 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5417 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5420 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5421 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5422 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5429 /* the ReflectionTypeLoadException must have all the types (Types property),
5430 * NULL replacing types which throws an exception. The LoaderException must
5431 * contain all exceptions for NULL items.
5434 len = mono_array_length (res);
5437 for (i = 0; i < len; i++) {
5438 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5442 klass = mono_type_get_class (t->type);
5443 if ((klass != NULL) && klass->exception_type) {
5444 /* keep the class in the list */
5445 list = g_list_append (list, klass);
5446 /* and replace Type with NULL */
5447 mono_array_setref (res, i, NULL);
5454 if (list || ex_count) {
5456 MonoException *exc = NULL;
5457 MonoArray *exl = NULL;
5458 int j, length = g_list_length (list) + ex_count;
5460 mono_loader_clear_error ();
5462 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5463 /* Types for which mono_class_get () succeeded */
5464 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5465 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5466 mono_array_setref (exl, i, exc);
5468 /* Types for which it don't */
5469 for (j = 0; j < mono_array_length (exceptions); ++j) {
5470 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5472 g_assert (i < length);
5473 mono_array_setref (exl, i, exc);
5480 exc = mono_get_exception_reflection_type_load (res, exl);
5481 mono_loader_clear_error ();
5482 mono_raise_exception (exc);
5489 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5491 MonoAssemblyName aname;
5492 MonoDomain *domain = mono_object_domain (name);
5494 gboolean is_version_defined;
5495 gboolean is_token_defined;
5497 aname.public_key = NULL;
5498 val = mono_string_to_utf8 (assname);
5499 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5500 g_free ((guint8*) aname.public_key);
5505 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5506 FALSE, is_token_defined);
5508 mono_assembly_name_free (&aname);
5509 g_free ((guint8*) aname.public_key);
5515 static MonoReflectionType*
5516 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5518 MonoDomain *domain = mono_object_domain (module);
5521 MONO_ARCH_SAVE_REGS;
5523 g_assert (module->image);
5525 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5526 /* These images do not have a global type */
5529 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5530 return mono_type_get_object (domain, &klass->byval_arg);
5534 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5536 /*if (module->image)
5537 mono_image_close (module->image);*/
5541 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5543 MonoDomain *domain = mono_object_domain (module);
5545 MONO_ARCH_SAVE_REGS;
5547 g_assert (module->image);
5548 return mono_string_new (domain, module->image->guid);
5552 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5554 #ifdef PLATFORM_WIN32
5555 if (module->image && module->image->is_module_handle)
5556 return module->image->raw_data;
5559 return (gpointer) (-1);
5563 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5565 if (image->dynamic) {
5566 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5567 *pe_kind = dyn->pe_kind;
5568 *machine = dyn->machine;
5571 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5572 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5577 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5579 return (image->md_version_major << 16) | (image->md_version_minor);
5583 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5585 MonoArray *exceptions;
5588 MONO_ARCH_SAVE_REGS;
5591 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5593 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5594 for (i = 0; i < mono_array_length (exceptions); ++i) {
5595 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5597 mono_raise_exception (ex);
5604 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5606 guint32 cols [MONO_MEMBERREF_SIZE];
5608 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5609 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5610 mono_metadata_decode_blob_size (sig, &sig);
5611 return (*sig != 0x6);
5615 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5618 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5619 mono_array_addr (type_args, MonoType*, 0));
5621 context->class_inst = NULL;
5623 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5624 mono_array_addr (method_args, MonoType*, 0));
5626 context->method_inst = NULL;
5630 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5633 int table = mono_metadata_token_table (token);
5634 int index = mono_metadata_token_index (token);
5635 MonoGenericContext context;
5637 *error = ResolveTokenError_Other;
5639 /* Validate token */
5640 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5641 (table != MONO_TABLE_TYPESPEC)) {
5642 *error = ResolveTokenError_BadTable;
5646 if (image->dynamic) {
5647 if (type_args || method_args)
5648 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5649 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5652 return &klass->byval_arg;
5655 if ((index <= 0) || (index > image->tables [table].rows)) {
5656 *error = ResolveTokenError_OutOfRange;
5660 init_generic_context_from_args (&context, type_args, method_args);
5661 klass = mono_class_get_full (image, token, &context);
5663 if (mono_loader_get_last_error ())
5664 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5667 return &klass->byval_arg;
5673 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5675 int table = mono_metadata_token_table (token);
5676 int index = mono_metadata_token_index (token);
5677 MonoGenericContext context;
5680 *error = ResolveTokenError_Other;
5682 /* Validate token */
5683 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5684 (table != MONO_TABLE_MEMBERREF)) {
5685 *error = ResolveTokenError_BadTable;
5689 if (image->dynamic) {
5690 if (type_args || method_args)
5691 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5692 /* FIXME: validate memberref token type */
5693 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5696 if ((index <= 0) || (index > image->tables [table].rows)) {
5697 *error = ResolveTokenError_OutOfRange;
5700 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5701 *error = ResolveTokenError_BadTable;
5705 init_generic_context_from_args (&context, type_args, method_args);
5706 method = mono_get_method_full (image, token, NULL, &context);
5708 if (mono_loader_get_last_error ())
5709 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5715 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5717 int index = mono_metadata_token_index (token);
5719 *error = ResolveTokenError_Other;
5721 /* Validate token */
5722 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5723 *error = ResolveTokenError_BadTable;
5728 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5730 if ((index <= 0) || (index >= image->heap_us.size)) {
5731 *error = ResolveTokenError_OutOfRange;
5735 /* FIXME: What to do if the index points into the middle of a string ? */
5737 return mono_ldstr (mono_domain_get (), image, index);
5740 static MonoClassField*
5741 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5744 int table = mono_metadata_token_table (token);
5745 int index = mono_metadata_token_index (token);
5746 MonoGenericContext context;
5747 MonoClassField *field;
5749 *error = ResolveTokenError_Other;
5751 /* Validate token */
5752 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5753 *error = ResolveTokenError_BadTable;
5757 if (image->dynamic) {
5758 if (type_args || method_args)
5759 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5760 /* FIXME: validate memberref token type */
5761 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5764 if ((index <= 0) || (index > image->tables [table].rows)) {
5765 *error = ResolveTokenError_OutOfRange;
5768 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5769 *error = ResolveTokenError_BadTable;
5773 init_generic_context_from_args (&context, type_args, method_args);
5774 field = mono_field_from_token (image, token, &klass, &context);
5776 if (mono_loader_get_last_error ())
5777 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5784 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5786 int table = mono_metadata_token_table (token);
5788 *error = ResolveTokenError_Other;
5791 case MONO_TABLE_TYPEDEF:
5792 case MONO_TABLE_TYPEREF:
5793 case MONO_TABLE_TYPESPEC: {
5794 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5796 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5800 case MONO_TABLE_METHOD:
5801 case MONO_TABLE_METHODSPEC: {
5802 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5804 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5808 case MONO_TABLE_FIELD: {
5809 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5811 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5815 case MONO_TABLE_MEMBERREF:
5816 if (mono_metadata_memberref_is_method (image, token)) {
5817 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5819 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5824 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5826 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5833 *error = ResolveTokenError_BadTable;
5840 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5842 int table = mono_metadata_token_table (token);
5843 int idx = mono_metadata_token_index (token);
5844 MonoTableInfo *tables = image->tables;
5849 *error = ResolveTokenError_OutOfRange;
5851 /* FIXME: Support other tables ? */
5852 if (table != MONO_TABLE_STANDALONESIG)
5858 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5861 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5863 ptr = mono_metadata_blob_heap (image, sig);
5864 len = mono_metadata_decode_blob_size (ptr, &ptr);
5866 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5867 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5871 static MonoReflectionType*
5872 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5875 int isbyref = 0, rank;
5876 char *str = mono_string_to_utf8 (smodifiers);
5879 MONO_ARCH_SAVE_REGS;
5881 klass = mono_class_from_mono_type (tb->type.type);
5883 /* logic taken from mono_reflection_parse_type(): keep in sync */
5887 if (isbyref) { /* only one level allowed by the spec */
5894 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5897 klass = mono_ptr_class_get (&klass->byval_arg);
5898 mono_class_init (klass);
5909 else if (*p != '*') { /* '*' means unknown lower bound */
5920 klass = mono_array_class_get (klass, rank);
5921 mono_class_init (klass);
5928 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5932 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5937 MONO_ARCH_SAVE_REGS;
5940 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5945 static MonoReflectionType *
5946 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5948 MonoClass *klass, *aklass;
5950 MONO_ARCH_SAVE_REGS;
5952 klass = mono_class_from_mono_type (type->type);
5953 aklass = mono_array_class_get (klass, rank);
5955 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5958 static MonoReflectionType *
5959 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5963 MONO_ARCH_SAVE_REGS;
5965 klass = mono_class_from_mono_type (type->type);
5967 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5970 static MonoReflectionType *
5971 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5975 MONO_ARCH_SAVE_REGS;
5977 pklass = mono_ptr_class_get (type->type);
5979 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5983 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5984 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5986 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5987 MonoObject *delegate;
5989 MonoMethod *method = info->method;
5991 MONO_ARCH_SAVE_REGS;
5993 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5995 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5996 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
6000 delegate = mono_object_new (mono_object_domain (type), delegate_class);
6002 if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
6003 method = mono_marshal_get_static_rgctx_invoke (method);
6004 func = mono_compile_method (method);
6005 } else if (method->dynamic) {
6006 /* Creating a trampoline would leak memory */
6007 func = mono_compile_method (method);
6009 func = mono_create_ftnptr (mono_domain_get (),
6010 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6013 mono_delegate_ctor_with_method (delegate, target, func, method);
6019 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
6021 /* Reset the invoke impl to the default one */
6022 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
6026 * Magic number to convert a time which is relative to
6027 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
6029 #define EPOCH_ADJUST ((guint64)62135596800LL)
6032 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
6034 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
6036 #ifdef PLATFORM_WIN32
6037 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
6039 convert_to_absolute_date(SYSTEMTIME *date)
6041 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
6042 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6043 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6044 /* from the calendar FAQ */
6045 int a = (14 - date->wMonth) / 12;
6046 int y = date->wYear - a;
6047 int m = date->wMonth + 12 * a - 2;
6048 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
6050 /* d is now the day of the week for the first of the month (0 == Sunday) */
6052 int day_of_week = date->wDayOfWeek;
6054 /* set day_in_month to the first day in the month which falls on day_of_week */
6055 int day_in_month = 1 + (day_of_week - d);
6056 if (day_in_month <= 0)
6059 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6060 date->wDay = day_in_month + (date->wDay - 1) * 7;
6061 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6066 #ifndef PLATFORM_WIN32
6068 * Return's the offset from GMT of a local time.
6070 * tm is a local time
6071 * t is the same local time as seconds.
6074 gmt_offset(struct tm *tm, time_t t)
6076 #if defined (HAVE_TM_GMTOFF)
6077 return tm->tm_gmtoff;
6082 g.tm_isdst = tm->tm_isdst;
6084 return (int)difftime(t, t2);
6089 * This is heavily based on zdump.c from glibc 2.2.
6091 * * data[0]: start of daylight saving time (in DateTime ticks).
6092 * * data[1]: end of daylight saving time (in DateTime ticks).
6093 * * data[2]: utcoffset (in TimeSpan ticks).
6094 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6095 * * name[0]: name of this timezone when not daylight saving.
6096 * * name[1]: name of this timezone when daylight saving.
6098 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6099 * the class library allows years between 1 and 9999.
6101 * Returns true on success and zero on failure.
6104 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6106 #ifndef PLATFORM_WIN32
6107 MonoDomain *domain = mono_domain_get ();
6108 struct tm start, tt;
6112 int is_daylight = 0, day;
6115 MONO_ARCH_SAVE_REGS;
6117 MONO_CHECK_ARG_NULL (data);
6118 MONO_CHECK_ARG_NULL (names);
6120 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6121 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6124 * no info is better than crashing: we'll need our own tz data
6125 * to make this work properly, anyway. The range is probably
6126 * reduced to 1970 .. 2037 because that is what mktime is
6127 * guaranteed to support (we get into an infinite loop
6131 memset (&start, 0, sizeof (start));
6134 start.tm_year = year-1900;
6136 t = mktime (&start);
6138 if ((year < 1970) || (year > 2037) || (t == -1)) {
6140 tt = *localtime (&t);
6141 strftime (tzone, sizeof (tzone), "%Z", &tt);
6142 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6143 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6147 gmtoff = gmt_offset (&start, t);
6149 /* For each day of the year, calculate the tm_gmtoff. */
6150 for (day = 0; day < 365; day++) {
6153 tt = *localtime (&t);
6155 /* Daylight saving starts or ends here. */
6156 if (gmt_offset (&tt, t) != gmtoff) {
6160 /* Try to find the exact hour when daylight saving starts/ends. */
6164 tt1 = *localtime (&t1);
6165 } while (gmt_offset (&tt1, t1) != gmtoff);
6167 /* Try to find the exact minute when daylight saving starts/ends. */
6170 tt1 = *localtime (&t1);
6171 } while (gmt_offset (&tt1, t1) == gmtoff);
6173 strftime (tzone, sizeof (tzone), "%Z", &tt);
6175 /* Write data, if we're already in daylight saving, we're done. */
6177 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6178 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6181 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6182 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6186 /* This is only set once when we enter daylight saving. */
6187 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6188 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6190 gmtoff = gmt_offset (&tt, t);
6195 strftime (tzone, sizeof (tzone), "%Z", &tt);
6196 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6197 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6198 mono_array_set ((*data), gint64, 0, 0);
6199 mono_array_set ((*data), gint64, 1, 0);
6200 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6201 mono_array_set ((*data), gint64, 3, 0);
6206 MonoDomain *domain = mono_domain_get ();
6207 TIME_ZONE_INFORMATION tz_info;
6212 tz_id = GetTimeZoneInformation (&tz_info);
6213 if (tz_id == TIME_ZONE_ID_INVALID)
6216 MONO_CHECK_ARG_NULL (data);
6217 MONO_CHECK_ARG_NULL (names);
6219 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6220 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6222 for (i = 0; i < 32; ++i)
6223 if (!tz_info.DaylightName [i])
6225 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6226 for (i = 0; i < 32; ++i)
6227 if (!tz_info.StandardName [i])
6229 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6231 if ((year <= 1601) || (year > 30827)) {
6233 * According to MSDN, the MS time functions can't handle dates outside
6239 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6240 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6241 tz_info.StandardDate.wYear = year;
6242 convert_to_absolute_date(&tz_info.StandardDate);
6243 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6248 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6249 tz_info.DaylightDate.wYear = year;
6250 convert_to_absolute_date(&tz_info.DaylightDate);
6251 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6256 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6258 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6259 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6266 ves_icall_System_Object_obj_address (MonoObject *this)
6268 MONO_ARCH_SAVE_REGS;
6275 static inline gint32
6276 mono_array_get_byte_length (MonoArray *array)
6282 klass = array->obj.vtable->klass;
6284 if (array->bounds == NULL)
6285 length = array->max_length;
6288 for (i = 0; i < klass->rank; ++ i)
6289 length *= array->bounds [i].length;
6292 switch (klass->element_class->byval_arg.type) {
6295 case MONO_TYPE_BOOLEAN:
6299 case MONO_TYPE_CHAR:
6307 return length * sizeof (gpointer);
6318 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6320 MONO_ARCH_SAVE_REGS;
6322 return mono_array_get_byte_length (array);
6326 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6328 MONO_ARCH_SAVE_REGS;
6330 return mono_array_get (array, gint8, idx);
6334 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6336 MONO_ARCH_SAVE_REGS;
6338 mono_array_set (array, gint8, idx, value);
6342 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6344 guint8 *src_buf, *dest_buf;
6346 MONO_ARCH_SAVE_REGS;
6348 /* watch out for integer overflow */
6349 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6352 src_buf = (guint8 *)src->vector + src_offset;
6353 dest_buf = (guint8 *)dest->vector + dest_offset;
6356 memcpy (dest_buf, src_buf, count);
6358 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6364 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6366 MonoDomain *domain = mono_object_domain (this);
6368 MonoRealProxy *rp = ((MonoRealProxy *)this);
6369 MonoTransparentProxy *tp;
6373 MONO_ARCH_SAVE_REGS;
6375 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6376 tp = (MonoTransparentProxy*) res;
6378 MONO_OBJECT_SETREF (tp, rp, rp);
6379 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6380 klass = mono_class_from_mono_type (type);
6382 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6383 tp->remote_class = mono_remote_class (domain, class_name, klass);
6385 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6389 static MonoReflectionType *
6390 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6392 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6395 /* System.Environment */
6398 ves_icall_System_Environment_get_UserName (void)
6400 MONO_ARCH_SAVE_REGS;
6402 /* using glib is more portable */
6403 return mono_string_new (mono_domain_get (), g_get_user_name ());
6408 ves_icall_System_Environment_get_MachineName (void)
6410 #if defined (PLATFORM_WIN32)
6415 len = MAX_COMPUTERNAME_LENGTH + 1;
6416 buf = g_new (gunichar2, len);
6419 if (GetComputerName (buf, (PDWORD) &len))
6420 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6424 #elif !defined(DISABLE_SOCKETS)
6428 if (gethostname (buf, sizeof (buf)) == 0)
6429 result = mono_string_new (mono_domain_get (), buf);
6435 return mono_string_new (mono_domain_get (), "mono");
6440 ves_icall_System_Environment_get_Platform (void)
6442 #if defined (PLATFORM_WIN32)
6445 #elif defined(__MACH__)
6447 if (mono_framework_version () < 2)
6451 // For compatibility with our client code, this will be 4 for a while.
6452 // We will eventually move to 6 to match .NET, but it requires all client
6453 // code to be updated and the documentation everywhere to be updated
6459 if (mono_framework_version () < 2)
6466 ves_icall_System_Environment_get_NewLine (void)
6468 MONO_ARCH_SAVE_REGS;
6470 #if defined (PLATFORM_WIN32)
6471 return mono_string_new (mono_domain_get (), "\r\n");
6473 return mono_string_new (mono_domain_get (), "\n");
6478 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6483 MONO_ARCH_SAVE_REGS;
6488 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6489 value = g_getenv (utf8_name);
6496 return mono_string_new (mono_domain_get (), value);
6500 * There is no standard way to get at environ.
6503 #ifndef __MINGW32_VERSION
6505 /* Apple defines this in crt_externs.h but doesn't provide that header for
6506 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6507 * in fact exist on all implementations (so far)
6509 gchar ***_NSGetEnviron();
6510 #define environ (*_NSGetEnviron())
6519 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6521 #ifdef PLATFORM_WIN32
6530 env_strings = GetEnvironmentStrings();
6533 env_string = env_strings;
6534 while (*env_string != '\0') {
6535 /* weird case that MS seems to skip */
6536 if (*env_string != '=')
6538 while (*env_string != '\0')
6544 domain = mono_domain_get ();
6545 names = mono_array_new (domain, mono_defaults.string_class, n);
6549 env_string = env_strings;
6550 while (*env_string != '\0') {
6551 /* weird case that MS seems to skip */
6552 if (*env_string != '=') {
6553 equal_str = wcschr(env_string, '=');
6554 g_assert(equal_str);
6555 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6556 mono_array_setref (names, n, str);
6559 while (*env_string != '\0')
6564 FreeEnvironmentStrings (env_strings);
6576 MONO_ARCH_SAVE_REGS;
6579 for (e = environ; *e != 0; ++ e)
6582 domain = mono_domain_get ();
6583 names = mono_array_new (domain, mono_defaults.string_class, n);
6586 for (e = environ; *e != 0; ++ e) {
6587 parts = g_strsplit (*e, "=", 2);
6589 str = mono_string_new (domain, *parts);
6590 mono_array_setref (names, n, str);
6603 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6605 #if !GLIB_CHECK_VERSION(2,4,0)
6606 #define g_setenv(a,b,c) setenv(a,b,c)
6607 #define g_unsetenv(a) unsetenv(a)
6611 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6613 #ifdef PLATFORM_WIN32
6614 gunichar2 *utf16_name, *utf16_value;
6616 gchar *utf8_name, *utf8_value;
6619 MONO_ARCH_SAVE_REGS;
6621 #ifdef PLATFORM_WIN32
6622 utf16_name = mono_string_to_utf16 (name);
6623 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6624 SetEnvironmentVariable (utf16_name, NULL);
6625 g_free (utf16_name);
6629 utf16_value = mono_string_to_utf16 (value);
6631 SetEnvironmentVariable (utf16_name, utf16_value);
6633 g_free (utf16_name);
6634 g_free (utf16_value);
6636 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6638 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6639 g_unsetenv (utf8_name);
6644 utf8_value = mono_string_to_utf8 (value);
6645 g_setenv (utf8_name, utf8_value, TRUE);
6648 g_free (utf8_value);
6653 ves_icall_System_Environment_Exit (int result)
6655 MONO_ARCH_SAVE_REGS;
6657 mono_threads_set_shutting_down ();
6659 mono_runtime_set_shutting_down ();
6661 /* Suspend all managed threads since the runtime is going away */
6662 mono_thread_suspend_all_other_threads ();
6664 mono_runtime_quit ();
6666 /* we may need to do some cleanup here... */
6671 ves_icall_System_Environment_GetGacPath (void)
6673 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6677 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6679 #if defined (PLATFORM_WIN32)
6680 #ifndef CSIDL_FLAG_CREATE
6681 #define CSIDL_FLAG_CREATE 0x8000
6684 WCHAR path [MAX_PATH];
6685 /* Create directory if no existing */
6686 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6690 return mono_string_new_utf16 (mono_domain_get (), path, len);
6693 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6695 return mono_string_new (mono_domain_get (), "");
6699 ves_icall_System_Environment_GetLogicalDrives (void)
6701 gunichar2 buf [128], *ptr, *dname;
6703 guint initial_size = 127, size = 128;
6706 MonoString *drivestr;
6707 MonoDomain *domain = mono_domain_get ();
6710 MONO_ARCH_SAVE_REGS;
6715 while (size > initial_size) {
6716 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6717 if (size > initial_size) {
6720 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6721 initial_size = size;
6735 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6740 while (*u16) { u16++; len ++; }
6741 drivestr = mono_string_new_utf16 (domain, dname, len);
6742 mono_array_setref (result, ndrives++, drivestr);
6753 ves_icall_System_Environment_InternalGetHome (void)
6755 MONO_ARCH_SAVE_REGS;
6757 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6760 static const char *encodings [] = {
6762 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6763 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6764 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6766 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6767 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6768 "x_unicode_2_0_utf_7",
6770 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6771 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6773 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6776 "unicodefffe", "utf_16be",
6783 * Returns the internal codepage, if the value of "int_code_page" is
6784 * 1 at entry, and we can not compute a suitable code page number,
6785 * returns the code page as a string
6788 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6793 char *codepage = NULL;
6795 int want_name = *int_code_page;
6798 *int_code_page = -1;
6799 MONO_ARCH_SAVE_REGS;
6801 g_get_charset (&cset);
6802 c = codepage = strdup (cset);
6803 for (c = codepage; *c; c++){
6804 if (isascii (*c) && isalpha (*c))
6809 /* g_print ("charset: %s\n", cset); */
6811 /* handle some common aliases */
6814 for (i = 0; p != 0; ){
6815 if ((gssize) p < 7){
6817 p = encodings [++i];
6820 if (strcmp (p, codepage) == 0){
6821 *int_code_page = code;
6824 p = encodings [++i];
6827 if (strstr (codepage, "utf_8") != NULL)
6828 *int_code_page |= 0x10000000;
6831 if (want_name && *int_code_page == -1)
6832 return mono_string_new (mono_domain_get (), cset);
6838 ves_icall_System_Environment_get_HasShutdownStarted (void)
6840 if (mono_runtime_is_shutting_down ())
6843 if (mono_domain_is_unloading (mono_domain_get ()))
6850 ves_icall_System_Environment_BroadcastSettingChange (void)
6852 #ifdef PLATFORM_WIN32
6853 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6858 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6859 MonoReflectionMethod *method,
6860 MonoArray *out_args)
6862 MONO_ARCH_SAVE_REGS;
6864 mono_message_init (mono_object_domain (this), this, method, out_args);
6868 ves_icall_IsTransparentProxy (MonoObject *proxy)
6870 MONO_ARCH_SAVE_REGS;
6875 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6881 static MonoReflectionMethod *
6882 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6883 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6887 MonoMethod **vtable;
6888 MonoMethod *res = NULL;
6890 MONO_CHECK_ARG_NULL (rtype);
6891 MONO_CHECK_ARG_NULL (rmethod);
6893 method = rmethod->method;
6894 klass = mono_class_from_mono_type (rtype->type);
6896 if (MONO_CLASS_IS_INTERFACE (klass))
6899 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6902 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6903 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6909 mono_class_setup_vtable (klass);
6910 vtable = klass->vtable;
6912 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6913 int offs = mono_class_interface_offset (klass, method->klass);
6915 res = vtable [offs + method->slot];
6917 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6920 if (method->slot != -1)
6921 res = vtable [method->slot];
6927 return mono_method_get_object (mono_domain_get (), res, NULL);
6931 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6936 MONO_ARCH_SAVE_REGS;
6938 klass = mono_class_from_mono_type (type->type);
6939 vtable = mono_class_vtable (mono_domain_get (), klass);
6941 if (enable) vtable->remote = 1;
6942 else vtable->remote = 0;
6946 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6951 MONO_ARCH_SAVE_REGS;
6953 domain = mono_object_domain (type);
6954 klass = mono_class_from_mono_type (type->type);
6956 if (klass->rank >= 1) {
6957 g_assert (klass->rank == 1);
6958 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6960 /* Bypass remoting object creation check */
6961 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6966 ves_icall_System_IO_get_temp_path (void)
6968 MONO_ARCH_SAVE_REGS;
6970 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6973 #ifndef PLATFORM_NO_DRIVEINFO
6975 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6976 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6980 ULARGE_INTEGER wapi_free_bytes_avail;
6981 ULARGE_INTEGER wapi_total_number_of_bytes;
6982 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6984 MONO_ARCH_SAVE_REGS;
6986 *error = ERROR_SUCCESS;
6987 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6988 &wapi_total_number_of_free_bytes);
6991 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6992 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6993 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6995 *free_bytes_avail = 0;
6996 *total_number_of_bytes = 0;
6997 *total_number_of_free_bytes = 0;
6998 *error = GetLastError ();
7005 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7007 MONO_ARCH_SAVE_REGS;
7009 return GetDriveType (mono_string_chars (root_path_name));
7014 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7016 MONO_ARCH_SAVE_REGS;
7018 return mono_compile_method (method);
7022 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7027 MONO_ARCH_SAVE_REGS;
7029 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7031 #if defined (PLATFORM_WIN32)
7032 /* Avoid mixing '/' and '\\' */
7035 for (i = strlen (path) - 1; i >= 0; i--)
7036 if (path [i] == '/')
7040 mcpath = mono_string_new (mono_domain_get (), path);
7047 get_bundled_machine_config (void)
7049 const gchar *machine_config;
7051 MONO_ARCH_SAVE_REGS;
7053 machine_config = mono_get_machine_config ();
7055 if (!machine_config)
7058 return mono_string_new (mono_domain_get (), machine_config);
7062 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7067 MONO_ARCH_SAVE_REGS;
7069 path = g_path_get_dirname (mono_get_config_dir ());
7071 #if defined (PLATFORM_WIN32)
7072 /* Avoid mixing '/' and '\\' */
7075 for (i = strlen (path) - 1; i >= 0; i--)
7076 if (path [i] == '/')
7080 ipath = mono_string_new (mono_domain_get (), path);
7087 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7089 MonoPEResourceDataEntry *entry;
7092 MONO_ARCH_SAVE_REGS;
7094 if (!assembly || !result || !size)
7099 image = assembly->assembly->image;
7100 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7104 *result = mono_image_rva_map (image, entry->rde_data_offset);
7109 *size = entry->rde_size;
7115 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7117 return mono_debug_using_mono_debugger ();
7121 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7123 #if defined (PLATFORM_WIN32)
7124 OutputDebugString (mono_string_chars (message));
7126 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7130 /* Only used for value types */
7132 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7137 MONO_ARCH_SAVE_REGS;
7139 domain = mono_object_domain (type);
7140 klass = mono_class_from_mono_type (type->type);
7142 if (mono_class_is_nullable (klass))
7143 /* No arguments -> null */
7146 return mono_object_new (domain, klass);
7149 static MonoReflectionMethod *
7150 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7152 MonoClass *klass, *parent;
7153 MonoMethod *method = m->method;
7154 MonoMethod *result = NULL;
7156 MONO_ARCH_SAVE_REGS;
7158 if (method->klass == NULL)
7161 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7162 MONO_CLASS_IS_INTERFACE (method->klass) ||
7163 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7166 klass = method->klass;
7167 if (klass->generic_class)
7168 klass = klass->generic_class->container_class;
7170 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7171 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7172 mono_class_setup_vtable (parent);
7173 if (parent->vtable_size <= method->slot)
7178 if (klass == method->klass)
7181 result = klass->vtable [method->slot];
7182 if (result == NULL) {
7183 /* It is an abstract method */
7184 gpointer iter = NULL;
7185 while ((result = mono_class_get_methods (klass, &iter)))
7186 if (result->slot == method->slot)
7193 return mono_method_get_object (mono_domain_get (), result, NULL);
7197 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7199 MonoMethod *method = m->method;
7201 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7206 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7208 MONO_ARCH_SAVE_REGS;
7210 iter->sig = *(MonoMethodSignature**)argsp;
7212 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7213 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7216 /* FIXME: it's not documented what start is exactly... */
7220 iter->args = argsp + sizeof (gpointer);
7221 #ifndef MONO_ARCH_REGPARMS
7223 guint32 i, arg_size;
7225 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7226 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7227 iter->args = (char*)iter->args + arg_size;
7232 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7234 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7238 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7240 guint32 i, arg_size;
7243 MONO_ARCH_SAVE_REGS;
7245 i = iter->sig->sentinelpos + iter->next_arg;
7247 g_assert (i < iter->sig->param_count);
7249 res.type = iter->sig->params [i];
7250 res.klass = mono_class_from_mono_type (res.type);
7251 res.value = iter->args;
7252 arg_size = mono_type_stack_size (res.type, &align);
7253 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7254 if (arg_size <= sizeof (gpointer)) {
7256 int padding = arg_size - mono_type_size (res.type, &dummy);
7257 res.value = (guint8*)res.value + padding;
7260 iter->args = (char*)iter->args + arg_size;
7263 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7269 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7271 guint32 i, arg_size;
7274 MONO_ARCH_SAVE_REGS;
7276 i = iter->sig->sentinelpos + iter->next_arg;
7278 g_assert (i < iter->sig->param_count);
7280 while (i < iter->sig->param_count) {
7281 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7283 res.type = iter->sig->params [i];
7284 res.klass = mono_class_from_mono_type (res.type);
7285 /* FIXME: endianess issue... */
7286 res.value = iter->args;
7287 arg_size = mono_type_stack_size (res.type, &align);
7288 iter->args = (char*)iter->args + arg_size;
7290 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7293 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7302 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7305 MONO_ARCH_SAVE_REGS;
7307 i = iter->sig->sentinelpos + iter->next_arg;
7309 g_assert (i < iter->sig->param_count);
7311 return iter->sig->params [i];
7315 mono_TypedReference_ToObject (MonoTypedRef tref)
7317 MONO_ARCH_SAVE_REGS;
7319 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7320 MonoObject** objp = tref.value;
7324 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7328 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7330 MONO_ARCH_SAVE_REGS;
7332 if (MONO_TYPE_IS_REFERENCE (type)) {
7333 MonoObject** objp = value;
7337 return mono_value_box (mono_domain_get (), klass, value);
7341 prelink_method (MonoMethod *method)
7343 const char *exc_class, *exc_arg;
7344 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7346 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7348 mono_raise_exception(
7349 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7351 /* create the wrapper, too? */
7355 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7357 MONO_ARCH_SAVE_REGS;
7358 prelink_method (method->method);
7362 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7364 MonoClass *klass = mono_class_from_mono_type (type->type);
7366 gpointer iter = NULL;
7367 MONO_ARCH_SAVE_REGS;
7369 while ((m = mono_class_get_methods (klass, &iter)))
7373 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7375 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7376 gint32 const **exponents,
7377 gunichar2 const **digitLowerTable,
7378 gunichar2 const **digitUpperTable,
7379 gint64 const **tenPowersList,
7380 gint32 const **decHexDigits)
7382 *mantissas = Formatter_MantissaBitsTable;
7383 *exponents = Formatter_TensExponentTable;
7384 *digitLowerTable = Formatter_DigitLowerTable;
7385 *digitUpperTable = Formatter_DigitUpperTable;
7386 *tenPowersList = Formatter_TenPowersList;
7387 *decHexDigits = Formatter_DecHexDigits;
7390 /* These parameters are "readonly" in corlib/System/Char.cs */
7392 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7393 guint8 const **numeric_data,
7394 gdouble const **numeric_data_values,
7395 guint16 const **to_lower_data_low,
7396 guint16 const **to_lower_data_high,
7397 guint16 const **to_upper_data_low,
7398 guint16 const **to_upper_data_high)
7400 *category_data = CategoryData;
7401 *numeric_data = NumericData;
7402 *numeric_data_values = NumericDataValues;
7403 *to_lower_data_low = ToLowerDataLow;
7404 *to_lower_data_high = ToLowerDataHigh;
7405 *to_upper_data_low = ToUpperDataLow;
7406 *to_upper_data_high = ToUpperDataHigh;
7410 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7412 return method->method->token;
7416 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7417 * and avoid useless allocations.
7420 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7424 for (i = 0; i < type->num_mods; ++i) {
7425 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7430 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7432 for (i = 0; i < type->num_mods; ++i) {
7433 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7434 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7435 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7443 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7445 MonoType *type = param->ClassImpl->type;
7446 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7447 MonoImage *image = method->method->klass->image;
7448 int pos = param->PositionImpl;
7449 MonoMethodSignature *sig = mono_method_signature (method->method);
7453 type = sig->params [pos];
7455 return type_array_from_modifiers (image, type, optional);
7459 get_property_type (MonoProperty *prop)
7461 MonoMethodSignature *sig;
7463 sig = mono_method_signature (prop->get);
7465 } else if (prop->set) {
7466 sig = mono_method_signature (prop->set);
7467 return sig->params [sig->param_count - 1];
7473 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7475 MonoType *type = get_property_type (property->property);
7476 MonoImage *image = property->klass->image;
7480 return type_array_from_modifiers (image, type, optional);
7484 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7486 MonoCustomAttrInfo *cinfo;
7489 cinfo = mono_reflection_get_custom_attrs_info (obj);
7492 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7494 mono_custom_attrs_free (cinfo);
7499 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7501 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7503 if (mono_loader_get_last_error ()) {
7504 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7505 g_assert_not_reached ();
7514 GCHandle_CheckCurrentDomain (guint32 gchandle)
7516 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7520 ves_icall_Mono_Runtime_GetDisplayName (void)
7522 static const char display_name_str [] = "Mono " VERSION;
7523 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7524 return display_name;
7528 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7530 MonoString *message;
7534 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7535 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7538 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7540 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7548 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7549 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7550 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7551 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7552 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7553 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7554 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7555 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7559 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7564 gunichar2 last, prev_last, prev2_last;
7572 last = prev_last = 0, prev2_last = 0;
7573 for (i = 0; i < ilength; i++) {
7575 if (c >= sizeof (dbase64)) {
7576 exc = mono_exception_from_name_msg (mono_get_corlib (),
7577 "System", "FormatException",
7578 "Invalid character found.");
7579 mono_raise_exception (exc);
7580 } else if (isspace (c)) {
7583 prev2_last = prev_last;
7589 olength = ilength - ignored;
7591 if (allowWhitespaceOnly && olength == 0) {
7592 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7595 if ((olength & 3) != 0 || olength <= 0) {
7596 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7597 "FormatException", "Invalid length.");
7598 mono_raise_exception (exc);
7601 if (prev2_last == '=') {
7602 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7603 mono_raise_exception (exc);
7606 olength = (olength * 3) / 4;
7610 if (prev_last == '=')
7613 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7614 res_ptr = mono_array_addr (result, guchar, 0);
7615 for (i = 0; i < ilength; ) {
7618 for (k = 0; k < 4 && i < ilength;) {
7624 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7625 exc = mono_exception_from_name_msg (mono_get_corlib (),
7626 "System", "FormatException",
7627 "Invalid character found.");
7628 mono_raise_exception (exc);
7633 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7635 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7637 *res_ptr++ = (b [2] << 6) | b [3];
7639 while (i < ilength && isspace (start [i]))
7647 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7649 MONO_ARCH_SAVE_REGS;
7651 return base64_to_byte_array (mono_string_chars (str),
7652 mono_string_length (str), allowWhitespaceOnly);
7656 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7658 MONO_ARCH_SAVE_REGS;
7660 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7664 #define ICALL_TYPE(id,name,first)
7665 #define ICALL(id,name,func) Icall_ ## id,
7668 #include "metadata/icall-def.h"
7674 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7675 #define ICALL(id,name,func)
7677 #include "metadata/icall-def.h"
7683 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7684 #define ICALL(id,name,func)
7686 guint16 first_icall;
7689 static const IcallTypeDesc
7690 icall_type_descs [] = {
7691 #include "metadata/icall-def.h"
7695 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7698 #define ICALL_TYPE(id,name,first)
7701 #ifdef HAVE_ARRAY_ELEM_INIT
7702 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7703 #define MSGSTRFIELD1(line) str##line
7705 static const struct msgstrtn_t {
7706 #define ICALL(id,name,func)
7708 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7709 #include "metadata/icall-def.h"
7711 } icall_type_names_str = {
7712 #define ICALL_TYPE(id,name,first) (name),
7713 #include "metadata/icall-def.h"
7716 static const guint16 icall_type_names_idx [] = {
7717 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7718 #include "metadata/icall-def.h"
7721 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7723 static const struct msgstr_t {
7725 #define ICALL_TYPE(id,name,first)
7726 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7727 #include "metadata/icall-def.h"
7729 } icall_names_str = {
7730 #define ICALL(id,name,func) (name),
7731 #include "metadata/icall-def.h"
7734 static const guint16 icall_names_idx [] = {
7735 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7736 #include "metadata/icall-def.h"
7739 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7745 #define ICALL_TYPE(id,name,first) name,
7746 #define ICALL(id,name,func)
7747 static const char* const
7748 icall_type_names [] = {
7749 #include "metadata/icall-def.h"
7753 #define icall_type_name_get(id) (icall_type_names [(id)])
7757 #define ICALL_TYPE(id,name,first)
7758 #define ICALL(id,name,func) name,
7759 static const char* const
7761 #include "metadata/icall-def.h"
7764 #define icall_name_get(id) icall_names [(id)]
7766 #endif /* !HAVE_ARRAY_ELEM_INIT */
7770 #define ICALL_TYPE(id,name,first)
7771 #define ICALL(id,name,func) func,
7772 static const gconstpointer
7773 icall_functions [] = {
7774 #include "metadata/icall-def.h"
7778 static GHashTable *icall_hash = NULL;
7779 static GHashTable *jit_icall_hash_name = NULL;
7780 static GHashTable *jit_icall_hash_addr = NULL;
7783 mono_icall_init (void)
7787 /* check that tables are sorted: disable in release */
7790 const char *prev_class = NULL;
7791 const char *prev_method;
7793 for (i = 0; i < Icall_type_num; ++i) {
7794 const IcallTypeDesc *desc;
7797 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7798 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7799 prev_class = icall_type_name_get (i);
7800 desc = &icall_type_descs [i];
7801 num_icalls = icall_desc_num_icalls (desc);
7802 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7803 for (j = 0; j < num_icalls; ++j) {
7804 const char *methodn = icall_name_get (desc->first_icall + j);
7805 if (prev_method && strcmp (prev_method, methodn) >= 0)
7806 g_print ("method %s should come before method %s\n", methodn, prev_method);
7807 prev_method = methodn;
7812 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7816 mono_icall_cleanup (void)
7818 g_hash_table_destroy (icall_hash);
7819 g_hash_table_destroy (jit_icall_hash_name);
7820 g_hash_table_destroy (jit_icall_hash_addr);
7824 mono_add_internal_call (const char *name, gconstpointer method)
7826 mono_loader_lock ();
7828 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7830 mono_loader_unlock ();
7833 #ifdef HAVE_ARRAY_ELEM_INIT
7835 compare_method_imap (const void *key, const void *elem)
7837 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7838 return strcmp (key, method_name);
7842 find_method_icall (const IcallTypeDesc *imap, const char *name)
7844 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7847 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7851 compare_class_imap (const void *key, const void *elem)
7853 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7854 return strcmp (key, class_name);
7857 static const IcallTypeDesc*
7858 find_class_icalls (const char *name)
7860 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7863 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7868 compare_method_imap (const void *key, const void *elem)
7870 const char** method_name = (const char**)elem;
7871 return strcmp (key, *method_name);
7875 find_method_icall (const IcallTypeDesc *imap, const char *name)
7877 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7880 return (gpointer)icall_functions [(nameslot - icall_names)];
7884 compare_class_imap (const void *key, const void *elem)
7886 const char** class_name = (const char**)elem;
7887 return strcmp (key, *class_name);
7890 static const IcallTypeDesc*
7891 find_class_icalls (const char *name)
7893 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7896 return &icall_type_descs [nameslot - icall_type_names];
7902 * we should probably export this as an helper (handle nested types).
7903 * Returns the number of chars written in buf.
7906 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7908 int nspacelen, cnamelen;
7909 nspacelen = strlen (klass->name_space);
7910 cnamelen = strlen (klass->name);
7911 if (nspacelen + cnamelen + 2 > bufsize)
7914 memcpy (buf, klass->name_space, nspacelen);
7915 buf [nspacelen ++] = '.';
7917 memcpy (buf + nspacelen, klass->name, cnamelen);
7918 buf [nspacelen + cnamelen] = 0;
7919 return nspacelen + cnamelen;
7923 mono_lookup_internal_call (MonoMethod *method)
7928 int typelen = 0, mlen, siglen;
7930 const IcallTypeDesc *imap;
7932 g_assert (method != NULL);
7934 if (method->is_inflated)
7935 method = ((MonoMethodInflated *) method)->declaring;
7937 if (method->klass->nested_in) {
7938 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7942 mname [pos++] = '/';
7945 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7951 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7956 imap = find_class_icalls (mname);
7958 mname [typelen] = ':';
7959 mname [typelen + 1] = ':';
7961 mlen = strlen (method->name);
7962 memcpy (mname + typelen + 2, method->name, mlen);
7963 sigstart = mname + typelen + 2 + mlen;
7966 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7967 siglen = strlen (tmpsig);
7968 if (typelen + mlen + siglen + 6 > sizeof (mname))
7971 memcpy (sigstart + 1, tmpsig, siglen);
7972 sigstart [siglen + 1] = ')';
7973 sigstart [siglen + 2] = 0;
7976 mono_loader_lock ();
7978 res = g_hash_table_lookup (icall_hash, mname);
7980 mono_loader_unlock ();
7983 /* try without signature */
7985 res = g_hash_table_lookup (icall_hash, mname);
7987 mono_loader_unlock ();
7991 /* it wasn't found in the static call tables */
7993 mono_loader_unlock ();
7996 res = find_method_icall (imap, sigstart - mlen);
7998 mono_loader_unlock ();
8001 /* try _with_ signature */
8003 res = find_method_icall (imap, sigstart - mlen);
8005 mono_loader_unlock ();
8009 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8010 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8011 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8012 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8013 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");
8014 g_print ("If you see other errors or faults after this message they are probably related\n");
8015 g_print ("and you need to fix your mono install first.\n");
8017 mono_loader_unlock ();
8023 type_from_typename (char *typename)
8025 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8027 if (!strcmp (typename, "int"))
8028 klass = mono_defaults.int_class;
8029 else if (!strcmp (typename, "ptr"))
8030 klass = mono_defaults.int_class;
8031 else if (!strcmp (typename, "void"))
8032 klass = mono_defaults.void_class;
8033 else if (!strcmp (typename, "int32"))
8034 klass = mono_defaults.int32_class;
8035 else if (!strcmp (typename, "uint32"))
8036 klass = mono_defaults.uint32_class;
8037 else if (!strcmp (typename, "int8"))
8038 klass = mono_defaults.sbyte_class;
8039 else if (!strcmp (typename, "uint8"))
8040 klass = mono_defaults.byte_class;
8041 else if (!strcmp (typename, "int16"))
8042 klass = mono_defaults.int16_class;
8043 else if (!strcmp (typename, "uint16"))
8044 klass = mono_defaults.uint16_class;
8045 else if (!strcmp (typename, "long"))
8046 klass = mono_defaults.int64_class;
8047 else if (!strcmp (typename, "ulong"))
8048 klass = mono_defaults.uint64_class;
8049 else if (!strcmp (typename, "float"))
8050 klass = mono_defaults.single_class;
8051 else if (!strcmp (typename, "double"))
8052 klass = mono_defaults.double_class;
8053 else if (!strcmp (typename, "object"))
8054 klass = mono_defaults.object_class;
8055 else if (!strcmp (typename, "obj"))
8056 klass = mono_defaults.object_class;
8057 else if (!strcmp (typename, "string"))
8058 klass = mono_defaults.string_class;
8059 else if (!strcmp (typename, "bool"))
8060 klass = mono_defaults.boolean_class;
8061 else if (!strcmp (typename, "boolean"))
8062 klass = mono_defaults.boolean_class;
8064 g_error ("%s", typename);
8065 g_assert_not_reached ();
8067 return &klass->byval_arg;
8070 MonoMethodSignature*
8071 mono_create_icall_signature (const char *sigstr)
8076 MonoMethodSignature *res;
8078 mono_loader_lock ();
8079 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8081 mono_loader_unlock ();
8085 parts = g_strsplit (sigstr, " ", 256);
8094 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8097 #ifdef PLATFORM_WIN32
8099 * Under windows, the default pinvoke calling convention is STDCALL but
8102 res->call_convention = MONO_CALL_C;
8105 res->ret = type_from_typename (parts [0]);
8106 for (i = 1; i < len; ++i) {
8107 res->params [i - 1] = type_from_typename (parts [i]);
8112 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8114 mono_loader_unlock ();
8120 mono_find_jit_icall_by_name (const char *name)
8122 MonoJitICallInfo *info;
8123 g_assert (jit_icall_hash_name);
8125 mono_loader_lock ();
8126 info = g_hash_table_lookup (jit_icall_hash_name, name);
8127 mono_loader_unlock ();
8132 mono_find_jit_icall_by_addr (gconstpointer addr)
8134 MonoJitICallInfo *info;
8135 g_assert (jit_icall_hash_addr);
8137 mono_loader_lock ();
8138 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8139 mono_loader_unlock ();
8145 * mono_get_jit_icall_info:
8147 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8148 * caller should access it while holding the loader lock.
8151 mono_get_jit_icall_info (void)
8153 return jit_icall_hash_name;
8157 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8159 mono_loader_lock ();
8160 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8161 mono_loader_unlock ();
8165 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8167 MonoJitICallInfo *info;
8172 mono_loader_lock ();
8174 if (!jit_icall_hash_name) {
8175 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8176 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8179 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8180 g_warning ("jit icall already defined \"%s\"\n", name);
8181 g_assert_not_reached ();
8184 info = g_new0 (MonoJitICallInfo, 1);
8191 info->wrapper = func;
8193 info->wrapper = NULL;
8196 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8197 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8199 mono_loader_unlock ();