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);
3755 mono_class_setup_vtable (klass);
3757 if (is_generic_parameter (type->type))
3758 nslots = klass->parent->vtable_size;
3760 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : klass->vtable_size;
3761 if (nslots >= sizeof (method_slots_default) * 8) {
3762 method_slots = g_new0 (guint32, nslots / 32 + 1);
3764 method_slots = method_slots_default;
3765 memset (method_slots, 0, sizeof (method_slots_default));
3768 mono_class_setup_vtable (klass);
3769 if (klass->exception_type != MONO_EXCEPTION_NONE)
3770 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3773 while ((method = mono_class_get_methods (klass, &iter))) {
3775 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3777 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3778 if (bflags & BFLAGS_Public)
3780 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3786 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3787 if (bflags & BFLAGS_Static)
3788 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3791 if (bflags & BFLAGS_Instance)
3799 if (compare_func (mname, method->name))
3804 if (method->slot != -1) {
3805 g_assert (method->slot < nslots);
3806 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3808 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3811 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3813 mono_ptr_array_append (tmp_array, member);
3815 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3819 if (method_slots != method_slots_default)
3820 g_free (method_slots);
3822 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3824 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3825 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3827 mono_ptr_array_destroy (tmp_array);
3832 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3835 static MonoClass *System_Reflection_ConstructorInfo;
3836 MonoClass *startklass, *klass, *refklass;
3841 gpointer iter = NULL;
3842 MonoPtrArray tmp_array;
3844 MONO_ARCH_SAVE_REGS;
3846 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3848 domain = ((MonoObject *)type)->vtable->domain;
3849 if (type->type->byref)
3850 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3851 klass = startklass = mono_class_from_mono_type (type->type);
3852 refklass = mono_class_from_mono_type (reftype->type);
3854 if (klass->exception_type != MONO_EXCEPTION_NONE)
3855 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3857 if (!System_Reflection_ConstructorInfo)
3858 System_Reflection_ConstructorInfo = mono_class_from_name (
3859 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3862 while ((method = mono_class_get_methods (klass, &iter))) {
3864 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3866 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3867 if (bflags & BFLAGS_Public)
3870 if (bflags & BFLAGS_NonPublic)
3876 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3877 if (bflags & BFLAGS_Static)
3878 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3881 if (bflags & BFLAGS_Instance)
3887 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3889 mono_ptr_array_append (tmp_array, member);
3892 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3894 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3895 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3897 mono_ptr_array_destroy (tmp_array);
3903 property_hash (gconstpointer data)
3905 MonoProperty *prop = (MonoProperty*)data;
3907 return g_str_hash (prop->name);
3911 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3913 // Properties are hide-by-name-and-signature
3914 if (!g_str_equal (prop1->name, prop2->name))
3917 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3919 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3925 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3930 return method_nonpublic (accessor, start_klass);
3934 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3937 static MonoClass *System_Reflection_PropertyInfo;
3938 MonoClass *startklass, *klass;
3944 gchar *propname = NULL;
3945 int (*compare_func) (const char *s1, const char *s2) = NULL;
3947 GHashTable *properties;
3948 MonoPtrArray tmp_array;
3950 MONO_ARCH_SAVE_REGS;
3952 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3954 if (!System_Reflection_PropertyInfo)
3955 System_Reflection_PropertyInfo = mono_class_from_name (
3956 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3958 domain = ((MonoObject *)type)->vtable->domain;
3959 if (type->type->byref)
3960 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3961 klass = startklass = mono_class_from_mono_type (type->type);
3963 propname = mono_string_to_utf8 (name);
3964 compare_func = (ignore_case) ? g_strcasecmp : strcmp;
3967 mono_class_setup_vtable (klass);
3969 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3971 mono_class_setup_vtable (klass);
3972 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3973 g_hash_table_destroy (properties);
3976 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3980 while ((prop = mono_class_get_properties (klass, &iter))) {
3986 flags = method->flags;
3989 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3990 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3991 if (bflags & BFLAGS_Public)
3993 } else if (bflags & BFLAGS_NonPublic) {
3994 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3995 property_accessor_nonpublic(prop->set, startklass == klass)) {
4002 if (flags & METHOD_ATTRIBUTE_STATIC) {
4003 if (bflags & BFLAGS_Static)
4004 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4007 if (bflags & BFLAGS_Instance)
4016 if (compare_func (propname, prop->name))
4020 if (g_hash_table_lookup (properties, prop))
4023 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
4025 g_hash_table_insert (properties, prop, prop);
4027 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
4030 g_hash_table_destroy (properties);
4033 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
4034 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4035 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4037 mono_ptr_array_destroy (tmp_array);
4042 static MonoReflectionEvent *
4043 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
4046 MonoClass *klass, *startklass;
4052 MONO_ARCH_SAVE_REGS;
4054 event_name = mono_string_to_utf8 (name);
4055 if (type->type->byref)
4057 klass = startklass = mono_class_from_mono_type (type->type);
4058 domain = mono_object_domain (type);
4061 if (klass->exception_type != MONO_EXCEPTION_NONE)
4062 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4065 while ((event = mono_class_get_events (klass, &iter))) {
4066 if (strcmp (event->name, event_name))
4069 method = event->add;
4071 method = event->remove;
4073 method = event->raise;
4075 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4076 if (!(bflags & BFLAGS_Public))
4079 if (!(bflags & BFLAGS_NonPublic))
4081 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
4086 if (!(bflags & BFLAGS_NonPublic))
4089 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4090 if (!(bflags & BFLAGS_Static))
4092 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
4095 if (!(bflags & BFLAGS_Instance))
4099 g_free (event_name);
4100 return mono_event_get_object (domain, startklass, event);
4103 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4106 g_free (event_name);
4111 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
4114 static MonoClass *System_Reflection_EventInfo;
4115 MonoClass *startklass, *klass;
4122 MonoPtrArray tmp_array;
4124 MONO_ARCH_SAVE_REGS;
4126 mono_ptr_array_init (tmp_array, 4);
4128 if (!System_Reflection_EventInfo)
4129 System_Reflection_EventInfo = mono_class_from_name (
4130 mono_defaults.corlib, "System.Reflection", "EventInfo");
4132 domain = mono_object_domain (type);
4133 if (type->type->byref)
4134 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
4135 klass = startklass = mono_class_from_mono_type (type->type);
4138 if (klass->exception_type != MONO_EXCEPTION_NONE)
4139 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4142 while ((event = mono_class_get_events (klass, &iter))) {
4144 method = event->add;
4146 method = event->remove;
4148 method = event->raise;
4150 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
4151 if (bflags & BFLAGS_Public)
4153 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
4154 if (bflags & BFLAGS_NonPublic)
4159 if (bflags & BFLAGS_NonPublic)
4165 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
4166 if (bflags & BFLAGS_Static)
4167 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
4170 if (bflags & BFLAGS_Instance)
4175 if (bflags & BFLAGS_Instance)
4179 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4181 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4184 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4186 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4187 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4189 mono_ptr_array_destroy (tmp_array);
4194 static MonoReflectionType *
4195 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4203 MONO_ARCH_SAVE_REGS;
4205 domain = ((MonoObject *)type)->vtable->domain;
4206 if (type->type->byref)
4208 klass = mono_class_from_mono_type (type->type);
4209 str = mono_string_to_utf8 (name);
4212 if (klass->exception_type != MONO_EXCEPTION_NONE)
4213 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4216 * If a nested type is generic, return its generic type definition.
4217 * Note that this means that the return value is essentially a
4218 * nested type of the generic type definition of @klass.
4220 * A note in MSDN claims that a generic type definition can have
4221 * nested types that aren't generic. In any case, the container of that
4222 * nested type would be the generic type definition.
4224 if (klass->generic_class)
4225 klass = klass->generic_class->container_class;
4228 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4230 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4231 if (bflags & BFLAGS_Public)
4234 if (bflags & BFLAGS_NonPublic)
4239 if (strcmp (nested->name, str) == 0){
4241 return mono_type_get_object (domain, &nested->byval_arg);
4244 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4251 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4260 MonoPtrArray tmp_array;
4262 MONO_ARCH_SAVE_REGS;
4264 domain = ((MonoObject *)type)->vtable->domain;
4265 if (type->type->byref)
4266 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4267 klass = mono_class_from_mono_type (type->type);
4268 if (klass->exception_type != MONO_EXCEPTION_NONE)
4269 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4272 * If a nested type is generic, return its generic type definition.
4273 * Note that this means that the return value is essentially the set
4274 * of nested types of the generic type definition of @klass.
4276 * A note in MSDN claims that a generic type definition can have
4277 * nested types that aren't generic. In any case, the container of that
4278 * nested type would be the generic type definition.
4280 if (klass->generic_class)
4281 klass = klass->generic_class->container_class;
4283 mono_ptr_array_init (tmp_array, 1);
4285 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4287 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4288 if (bflags & BFLAGS_Public)
4291 if (bflags & BFLAGS_NonPublic)
4296 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4297 mono_ptr_array_append (tmp_array, member);
4300 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4302 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4303 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4305 mono_ptr_array_destroy (tmp_array);
4310 static MonoReflectionType*
4311 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4314 MonoType *type = NULL;
4315 MonoTypeNameParse info;
4316 gboolean type_resolve;
4318 MONO_ARCH_SAVE_REGS;
4320 /* On MS.NET, this does not fire a TypeResolve event */
4321 type_resolve = TRUE;
4322 str = mono_string_to_utf8 (name);
4323 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4324 if (!mono_reflection_parse_type (str, &info)) {
4326 mono_reflection_free_type_info (&info);
4327 if (throwOnError) /* uhm: this is a parse error, though... */
4328 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4329 /*g_print ("failed parse\n");*/
4333 if (info.assembly.name) {
4335 mono_reflection_free_type_info (&info);
4337 /* 1.0 and 2.0 throw different exceptions */
4338 if (mono_defaults.generic_ilist_class)
4339 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4341 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4346 if (module != NULL) {
4348 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4353 if (assembly->assembly->dynamic) {
4354 /* Enumerate all modules */
4355 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4359 if (abuilder->modules) {
4360 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4361 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4362 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4368 if (!type && abuilder->loaded_modules) {
4369 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4370 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4371 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4378 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4380 mono_reflection_free_type_info (&info);
4382 MonoException *e = NULL;
4385 e = mono_get_exception_type_load (name, NULL);
4387 mono_loader_clear_error ();
4390 mono_raise_exception (e);
4395 if (type->type == MONO_TYPE_CLASS) {
4396 MonoClass *klass = mono_type_get_class (type);
4398 if (mono_is_security_manager_active () && !klass->exception_type)
4399 /* Some security problems are detected during generic vtable construction */
4400 mono_class_setup_vtable (klass);
4401 /* need to report exceptions ? */
4402 if (throwOnError && klass->exception_type) {
4403 /* report SecurityException (or others) that occured when loading the assembly */
4404 MonoException *exc = mono_class_get_exception_for_failure (klass);
4405 mono_loader_clear_error ();
4406 mono_raise_exception (exc);
4407 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4412 /* g_print ("got it\n"); */
4413 return mono_type_get_object (mono_object_domain (assembly), type);
4417 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4420 gchar *shadow_ini_file;
4423 /* Check for shadow-copied assembly */
4424 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4425 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4427 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4428 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4434 g_free (shadow_ini_file);
4435 if (content != NULL) {
4438 *filename = content;
4446 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4448 MonoDomain *domain = mono_object_domain (assembly);
4449 MonoAssembly *mass = assembly->assembly;
4450 MonoString *res = NULL;
4455 MONO_ARCH_SAVE_REGS;
4457 if (g_path_is_absolute (mass->image->name)) {
4458 absolute = g_strdup (mass->image->name);
4459 dirname = g_path_get_dirname (absolute);
4461 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4462 dirname = g_strdup (mass->basedir);
4465 replace_shadow_path (domain, dirname, &absolute);
4470 for (i = strlen (absolute) - 1; i >= 0; i--)
4471 if (absolute [i] == '\\')
4476 uri = g_filename_to_uri (absolute, NULL, NULL);
4478 const char *prepend = "file://";
4480 if (*absolute == '/' && *(absolute + 1) == '/') {
4483 prepend = "file:///";
4486 uri = g_strconcat (prepend, absolute, NULL);
4490 res = mono_string_new (domain, uri);
4498 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4500 MonoAssembly *mass = assembly->assembly;
4502 MONO_ARCH_SAVE_REGS;
4504 return mass->in_gac;
4507 static MonoReflectionAssembly*
4508 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4512 MonoImageOpenStatus status;
4514 MONO_ARCH_SAVE_REGS;
4516 name = mono_string_to_utf8 (mname);
4517 res = mono_assembly_load_with_partial_name (name, &status);
4523 return mono_assembly_get_object (mono_domain_get (), res);
4527 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4529 MonoDomain *domain = mono_object_domain (assembly);
4532 MONO_ARCH_SAVE_REGS;
4534 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4540 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4542 MONO_ARCH_SAVE_REGS;
4544 return assembly->assembly->ref_only;
4548 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4550 MonoDomain *domain = mono_object_domain (assembly);
4552 MONO_ARCH_SAVE_REGS;
4554 return mono_string_new (domain, assembly->assembly->image->version);
4557 static MonoReflectionMethod*
4558 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4560 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4562 MONO_ARCH_SAVE_REGS;
4566 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4569 static MonoReflectionModule*
4570 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4572 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4576 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4578 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4579 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4583 MONO_ARCH_SAVE_REGS;
4585 for (i = 0; i < table->rows; ++i) {
4586 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4587 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4593 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4595 static MonoClass *System_Version = NULL;
4596 static MonoMethod *create_version = NULL;
4600 if (!System_Version) {
4601 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4602 g_assert (System_Version);
4605 if (!create_version) {
4606 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4607 create_version = mono_method_desc_search_in_class (desc, System_Version);
4608 g_assert (create_version);
4609 mono_method_desc_free (desc);
4615 args [3] = &revision;
4616 result = mono_object_new (domain, System_Version);
4617 mono_runtime_invoke (create_version, result, args, NULL);
4623 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4625 static MonoClass *System_Reflection_AssemblyName;
4627 MonoDomain *domain = mono_object_domain (assembly);
4629 static MonoMethod *create_culture = NULL;
4630 MonoImage *image = assembly->assembly->image;
4633 MONO_ARCH_SAVE_REGS;
4635 if (!System_Reflection_AssemblyName)
4636 System_Reflection_AssemblyName = mono_class_from_name (
4637 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4639 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4642 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4644 if (count > 0 && !create_culture) {
4645 MonoMethodDesc *desc = mono_method_desc_new (
4646 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4647 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4648 g_assert (create_culture);
4649 mono_method_desc_free (desc);
4652 for (i = 0; i < count; i++) {
4653 MonoReflectionAssemblyName *aname;
4654 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4656 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4658 aname = (MonoReflectionAssemblyName *) mono_object_new (
4659 domain, System_Reflection_AssemblyName);
4661 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4663 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4664 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4665 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4666 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4667 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4668 aname->versioncompat = 1; /* SameMachine (default) */
4669 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4670 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4672 if (create_culture) {
4674 MonoBoolean assembly_ref = 1;
4675 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4676 args [1] = &assembly_ref;
4677 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4680 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4681 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4682 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4684 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4685 /* public key token isn't copied - the class library will
4686 automatically generate it from the public key if required */
4687 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4688 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4690 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4691 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4694 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4697 /* note: this function doesn't return the codebase on purpose (i.e. it can
4698 be used under partial trust as path information isn't present). */
4700 mono_array_setref (result, i, aname);
4711 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4713 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4715 mono_array_setref (info->res, info->idx, name);
4720 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4722 MonoImage *img = assembly->assembly->image;
4726 MONO_ARCH_SAVE_REGS;
4728 if (!img->name_cache)
4729 mono_image_init_name_cache (img);
4731 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, g_hash_table_size (img->name_cache));
4734 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4739 /* move this in some file in mono/util/ */
4741 g_concat_dir_and_file (const char *dir, const char *file)
4743 g_return_val_if_fail (dir != NULL, NULL);
4744 g_return_val_if_fail (file != NULL, NULL);
4747 * If the directory name doesn't have a / on the end, we need
4748 * to add one so we get a proper path to the file
4750 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4751 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4753 return g_strconcat (dir, file, NULL);
4757 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4759 char *n = mono_string_to_utf8 (name);
4760 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4762 guint32 cols [MONO_MANIFEST_SIZE];
4763 guint32 impl, file_idx;
4767 MONO_ARCH_SAVE_REGS;
4769 for (i = 0; i < table->rows; ++i) {
4770 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4771 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4772 if (strcmp (val, n) == 0)
4776 if (i == table->rows)
4779 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4782 * this code should only be called after obtaining the
4783 * ResourceInfo and handling the other cases.
4785 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4786 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4788 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4793 module = assembly->assembly->image;
4795 *ref_module = mono_module_get_object (mono_domain_get (), module);
4797 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4801 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4803 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4805 guint32 cols [MONO_MANIFEST_SIZE];
4806 guint32 file_cols [MONO_FILE_SIZE];
4810 MONO_ARCH_SAVE_REGS;
4812 n = mono_string_to_utf8 (name);
4813 for (i = 0; i < table->rows; ++i) {
4814 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4815 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4816 if (strcmp (val, n) == 0)
4820 if (i == table->rows)
4823 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4824 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4827 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4828 case MONO_IMPLEMENTATION_FILE:
4829 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4830 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4831 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4832 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4833 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4834 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4837 info->location = RESOURCE_LOCATION_EMBEDDED;
4840 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4841 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4842 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4843 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4844 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4845 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4847 mono_raise_exception (ex);
4849 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4851 /* Obtain info recursively */
4852 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4853 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4856 case MONO_IMPLEMENTATION_EXP_TYPE:
4857 g_assert_not_reached ();
4866 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4868 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4869 MonoArray *result = NULL;
4874 MONO_ARCH_SAVE_REGS;
4876 /* check hash if needed */
4878 n = mono_string_to_utf8 (name);
4879 for (i = 0; i < table->rows; ++i) {
4880 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4881 if (strcmp (val, n) == 0) {
4884 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4885 fn = mono_string_new (mono_object_domain (assembly), n);
4887 return (MonoObject*)fn;
4895 for (i = 0; i < table->rows; ++i) {
4896 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4900 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4903 for (i = 0; i < table->rows; ++i) {
4904 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4905 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4906 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4907 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4912 return (MonoObject*)result;
4916 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4918 MonoDomain *domain = mono_domain_get();
4921 int i, j, file_count = 0;
4922 MonoImage **modules;
4923 guint32 module_count, real_module_count;
4924 MonoTableInfo *table;
4925 guint32 cols [MONO_FILE_SIZE];
4926 MonoImage *image = assembly->assembly->image;
4928 g_assert (image != NULL);
4929 g_assert (!assembly->assembly->dynamic);
4931 table = &image->tables [MONO_TABLE_FILE];
4932 file_count = table->rows;
4934 modules = image->modules;
4935 module_count = image->module_count;
4937 real_module_count = 0;
4938 for (i = 0; i < module_count; ++i)
4940 real_module_count ++;
4942 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4943 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4945 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4947 for (i = 0; i < module_count; ++i)
4949 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4953 for (i = 0; i < file_count; ++i, ++j) {
4954 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4955 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4956 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4958 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4960 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4961 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4963 mono_array_setref (res, j, mono_module_get_object (domain, m));
4970 static MonoReflectionMethod*
4971 ves_icall_GetCurrentMethod (void)
4973 MonoMethod *m = mono_method_get_last_managed ();
4975 MONO_ARCH_SAVE_REGS;
4977 return mono_method_get_object (mono_domain_get (), m, NULL);
4982 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4985 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4986 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4987 //method is inflated, we should inflate it on the other class
4988 MonoGenericContext ctx;
4989 ctx.method_inst = inflated->context.method_inst;
4990 ctx.class_inst = inflated->context.class_inst;
4991 if (klass->generic_class)
4992 ctx.class_inst = klass->generic_class->context.class_inst;
4993 else if (klass->generic_container)
4994 ctx.class_inst = klass->generic_container->context.class_inst;
4995 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4998 mono_class_setup_methods (method->klass);
4999 for (i = 0; i < method->klass->method.count; ++i) {
5000 if (method->klass->methods [i] == method) {
5005 mono_class_setup_methods (klass);
5006 g_assert (offset >= 0 && offset < klass->method.count);
5007 return klass->methods [offset];
5010 static MonoReflectionMethod*
5011 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
5015 klass = mono_class_from_mono_type (type);
5016 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
5018 if (method->klass != klass)
5019 method = mono_method_get_equivalent_method (method, klass);
5021 klass = method->klass;
5022 return mono_method_get_object (mono_domain_get (), method, klass);
5025 static MonoReflectionMethod*
5026 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
5028 return mono_method_get_object (mono_domain_get (), method, NULL);
5031 static MonoReflectionMethodBody*
5032 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
5034 return mono_method_body_get_object (mono_domain_get (), method);
5037 static MonoReflectionAssembly*
5038 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
5040 MonoMethod *dest = NULL;
5042 MONO_ARCH_SAVE_REGS;
5044 mono_stack_walk_no_il (get_executing, &dest);
5045 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5049 static MonoReflectionAssembly*
5050 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
5052 MonoDomain* domain = mono_domain_get ();
5054 MONO_ARCH_SAVE_REGS;
5056 if (!domain->entry_assembly)
5059 return mono_assembly_get_object (domain, domain->entry_assembly);
5062 static MonoReflectionAssembly*
5063 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
5068 MONO_ARCH_SAVE_REGS;
5071 mono_stack_walk_no_il (get_executing, &dest);
5073 mono_stack_walk_no_il (get_caller, &dest);
5076 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
5080 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
5081 gboolean assembly_qualified)
5083 MonoDomain *domain = mono_object_domain (object);
5084 MonoTypeNameFormat format;
5088 MONO_ARCH_SAVE_REGS;
5090 format = assembly_qualified ?
5091 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
5092 MONO_TYPE_NAME_FORMAT_FULL_NAME;
5094 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
5096 name = mono_type_get_name_full (object->type, format);
5100 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
5105 res = mono_string_new (domain, name);
5112 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
5114 static MonoMethod *create_culture = NULL;
5117 const char *pkey_ptr;
5119 MonoBoolean assembly_ref = 0;
5121 MONO_ARCH_SAVE_REGS;
5123 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
5124 aname->major = name->major;
5125 aname->minor = name->minor;
5126 aname->build = name->build;
5127 aname->flags = name->flags;
5128 aname->revision = name->revision;
5129 aname->hashalg = name->hash_alg;
5130 aname->versioncompat = 1; /* SameMachine (default) */
5132 if (by_default_version)
5133 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5136 if (absolute != NULL && *absolute != '\0') {
5137 const gchar *prepend = "file://";
5140 codebase = g_strdup (absolute);
5145 for (i = strlen (codebase) - 1; i >= 0; i--)
5146 if (codebase [i] == '\\')
5149 if (*codebase == '/' && *(codebase + 1) == '/') {
5152 prepend = "file:///";
5156 result = g_strconcat (prepend, codebase, NULL);
5162 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5166 if (!create_culture) {
5167 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5168 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5169 g_assert (create_culture);
5170 mono_method_desc_free (desc);
5173 if (name->culture) {
5174 args [0] = mono_string_new (domain, name->culture);
5175 args [1] = &assembly_ref;
5176 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5179 if (name->public_key) {
5180 pkey_ptr = (char*)name->public_key;
5181 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5183 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5184 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5185 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5186 } else if (default_publickey) {
5187 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5188 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5191 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5192 if (name->public_key_token [0]) {
5196 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5197 p = mono_array_addr (aname->keyToken, char, 0);
5199 for (i = 0, j = 0; i < 8; i++) {
5200 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5201 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5204 } else if (default_token) {
5205 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5210 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5212 MonoDomain *domain = mono_object_domain (assembly);
5213 MonoAssembly *mass = assembly->assembly;
5217 name = g_strdup_printf (
5218 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5220 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5221 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5222 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5223 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5225 res = mono_string_new (domain, name);
5232 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5235 MonoAssembly *mass = assembly->assembly;
5237 MONO_ARCH_SAVE_REGS;
5239 if (g_path_is_absolute (mass->image->name)) {
5240 fill_reflection_assembly_name (mono_object_domain (assembly),
5241 aname, &mass->aname, mass->image->name, TRUE,
5242 TRUE, mono_framework_version () >= 2);
5245 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5247 fill_reflection_assembly_name (mono_object_domain (assembly),
5248 aname, &mass->aname, absolute, TRUE, TRUE,
5249 mono_framework_version () >= 2);
5255 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5258 MonoImageOpenStatus status = MONO_IMAGE_OK;
5261 MonoAssemblyName name;
5264 MONO_ARCH_SAVE_REGS;
5266 filename = mono_string_to_utf8 (fname);
5268 dirname = g_path_get_dirname (filename);
5269 replace_shadow_path (mono_domain_get (), dirname, &filename);
5272 image = mono_image_open (filename, &status);
5278 if (status == MONO_IMAGE_IMAGE_INVALID)
5279 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5281 exc = mono_get_exception_file_not_found2 (NULL, fname);
5282 mono_raise_exception (exc);
5285 res = mono_assembly_fill_assembly_name (image, &name);
5287 mono_image_close (image);
5289 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5292 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5293 TRUE, mono_framework_version () == 1,
5294 mono_framework_version () >= 2);
5297 mono_image_close (image);
5301 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5302 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5304 MonoBoolean result = FALSE;
5305 MonoDeclSecurityEntry entry;
5307 /* SecurityAction.RequestMinimum */
5308 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5309 *minimum = entry.blob;
5310 *minLength = entry.size;
5313 /* SecurityAction.RequestOptional */
5314 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5315 *optional = entry.blob;
5316 *optLength = entry.size;
5319 /* SecurityAction.RequestRefuse */
5320 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5321 *refused = entry.blob;
5322 *refLength = entry.size;
5330 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5334 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5336 guint32 attrs, visibility;
5338 /* we start the count from 1 because we skip the special type <Module> */
5341 for (i = 1; i < tdef->rows; ++i) {
5342 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5343 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5344 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5348 count = tdef->rows - 1;
5350 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5351 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5353 for (i = 1; i < tdef->rows; ++i) {
5354 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5355 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5356 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5357 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5359 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5361 MonoLoaderError *error;
5364 error = mono_loader_get_last_error ();
5365 g_assert (error != NULL);
5367 ex = mono_loader_error_prepare_exception (error);
5368 mono_array_setref (*exceptions, count, ex);
5370 if (mono_loader_get_last_error ())
5371 mono_loader_clear_error ();
5380 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5382 MonoArray *res = NULL;
5383 MonoArray *exceptions = NULL;
5384 MonoImage *image = NULL;
5385 MonoTableInfo *table = NULL;
5388 int i, len, ex_count;
5390 MONO_ARCH_SAVE_REGS;
5392 domain = mono_object_domain (assembly);
5394 g_assert (!assembly->assembly->dynamic);
5395 image = assembly->assembly->image;
5396 table = &image->tables [MONO_TABLE_FILE];
5397 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5399 /* Append data from all modules in the assembly */
5400 for (i = 0; i < table->rows; ++i) {
5401 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5402 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5405 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5406 /* Append the new types to the end of the array */
5407 if (mono_array_length (res2) > 0) {
5409 MonoArray *res3, *ex3;
5411 len1 = mono_array_length (res);
5412 len2 = mono_array_length (res2);
5414 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5415 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5416 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5419 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5420 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5421 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5428 /* the ReflectionTypeLoadException must have all the types (Types property),
5429 * NULL replacing types which throws an exception. The LoaderException must
5430 * contain all exceptions for NULL items.
5433 len = mono_array_length (res);
5436 for (i = 0; i < len; i++) {
5437 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5441 klass = mono_type_get_class (t->type);
5442 if ((klass != NULL) && klass->exception_type) {
5443 /* keep the class in the list */
5444 list = g_list_append (list, klass);
5445 /* and replace Type with NULL */
5446 mono_array_setref (res, i, NULL);
5453 if (list || ex_count) {
5455 MonoException *exc = NULL;
5456 MonoArray *exl = NULL;
5457 int j, length = g_list_length (list) + ex_count;
5459 mono_loader_clear_error ();
5461 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5462 /* Types for which mono_class_get () succeeded */
5463 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5464 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5465 mono_array_setref (exl, i, exc);
5467 /* Types for which it don't */
5468 for (j = 0; j < mono_array_length (exceptions); ++j) {
5469 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5471 g_assert (i < length);
5472 mono_array_setref (exl, i, exc);
5479 exc = mono_get_exception_reflection_type_load (res, exl);
5480 mono_loader_clear_error ();
5481 mono_raise_exception (exc);
5488 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5490 MonoAssemblyName aname;
5491 MonoDomain *domain = mono_object_domain (name);
5493 gboolean is_version_defined;
5494 gboolean is_token_defined;
5496 aname.public_key = NULL;
5497 val = mono_string_to_utf8 (assname);
5498 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5499 g_free ((guint8*) aname.public_key);
5504 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5505 FALSE, is_token_defined);
5507 mono_assembly_name_free (&aname);
5508 g_free ((guint8*) aname.public_key);
5514 static MonoReflectionType*
5515 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5517 MonoDomain *domain = mono_object_domain (module);
5520 MONO_ARCH_SAVE_REGS;
5522 g_assert (module->image);
5524 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5525 /* These images do not have a global type */
5528 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5529 return mono_type_get_object (domain, &klass->byval_arg);
5533 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5535 /*if (module->image)
5536 mono_image_close (module->image);*/
5540 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5542 MonoDomain *domain = mono_object_domain (module);
5544 MONO_ARCH_SAVE_REGS;
5546 g_assert (module->image);
5547 return mono_string_new (domain, module->image->guid);
5551 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5553 #ifdef PLATFORM_WIN32
5554 if (module->image && module->image->is_module_handle)
5555 return module->image->raw_data;
5558 return (gpointer) (-1);
5562 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5564 if (image->dynamic) {
5565 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5566 *pe_kind = dyn->pe_kind;
5567 *machine = dyn->machine;
5570 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5571 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5576 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5578 return (image->md_version_major << 16) | (image->md_version_minor);
5582 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5584 MonoArray *exceptions;
5587 MONO_ARCH_SAVE_REGS;
5590 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5592 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5593 for (i = 0; i < mono_array_length (exceptions); ++i) {
5594 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5596 mono_raise_exception (ex);
5603 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5605 guint32 cols [MONO_MEMBERREF_SIZE];
5607 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5608 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5609 mono_metadata_decode_blob_size (sig, &sig);
5610 return (*sig != 0x6);
5614 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5617 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5618 mono_array_addr (type_args, MonoType*, 0));
5620 context->class_inst = NULL;
5622 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5623 mono_array_addr (method_args, MonoType*, 0));
5625 context->method_inst = NULL;
5629 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5632 int table = mono_metadata_token_table (token);
5633 int index = mono_metadata_token_index (token);
5634 MonoGenericContext context;
5636 *error = ResolveTokenError_Other;
5638 /* Validate token */
5639 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5640 (table != MONO_TABLE_TYPESPEC)) {
5641 *error = ResolveTokenError_BadTable;
5645 if (image->dynamic) {
5646 if (type_args || method_args)
5647 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5648 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5651 return &klass->byval_arg;
5654 if ((index <= 0) || (index > image->tables [table].rows)) {
5655 *error = ResolveTokenError_OutOfRange;
5659 init_generic_context_from_args (&context, type_args, method_args);
5660 klass = mono_class_get_full (image, token, &context);
5662 if (mono_loader_get_last_error ())
5663 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5666 return &klass->byval_arg;
5672 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5674 int table = mono_metadata_token_table (token);
5675 int index = mono_metadata_token_index (token);
5676 MonoGenericContext context;
5679 *error = ResolveTokenError_Other;
5681 /* Validate token */
5682 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5683 (table != MONO_TABLE_MEMBERREF)) {
5684 *error = ResolveTokenError_BadTable;
5688 if (image->dynamic) {
5689 if (type_args || method_args)
5690 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5691 /* FIXME: validate memberref token type */
5692 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5695 if ((index <= 0) || (index > image->tables [table].rows)) {
5696 *error = ResolveTokenError_OutOfRange;
5699 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5700 *error = ResolveTokenError_BadTable;
5704 init_generic_context_from_args (&context, type_args, method_args);
5705 method = mono_get_method_full (image, token, NULL, &context);
5707 if (mono_loader_get_last_error ())
5708 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5714 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5716 int index = mono_metadata_token_index (token);
5718 *error = ResolveTokenError_Other;
5720 /* Validate token */
5721 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5722 *error = ResolveTokenError_BadTable;
5727 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5729 if ((index <= 0) || (index >= image->heap_us.size)) {
5730 *error = ResolveTokenError_OutOfRange;
5734 /* FIXME: What to do if the index points into the middle of a string ? */
5736 return mono_ldstr (mono_domain_get (), image, index);
5739 static MonoClassField*
5740 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5743 int table = mono_metadata_token_table (token);
5744 int index = mono_metadata_token_index (token);
5745 MonoGenericContext context;
5746 MonoClassField *field;
5748 *error = ResolveTokenError_Other;
5750 /* Validate token */
5751 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5752 *error = ResolveTokenError_BadTable;
5756 if (image->dynamic) {
5757 if (type_args || method_args)
5758 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5759 /* FIXME: validate memberref token type */
5760 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5763 if ((index <= 0) || (index > image->tables [table].rows)) {
5764 *error = ResolveTokenError_OutOfRange;
5767 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5768 *error = ResolveTokenError_BadTable;
5772 init_generic_context_from_args (&context, type_args, method_args);
5773 field = mono_field_from_token (image, token, &klass, &context);
5775 if (mono_loader_get_last_error ())
5776 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5783 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5785 int table = mono_metadata_token_table (token);
5787 *error = ResolveTokenError_Other;
5790 case MONO_TABLE_TYPEDEF:
5791 case MONO_TABLE_TYPEREF:
5792 case MONO_TABLE_TYPESPEC: {
5793 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5795 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5799 case MONO_TABLE_METHOD:
5800 case MONO_TABLE_METHODSPEC: {
5801 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5803 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5807 case MONO_TABLE_FIELD: {
5808 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5810 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5814 case MONO_TABLE_MEMBERREF:
5815 if (mono_metadata_memberref_is_method (image, token)) {
5816 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5818 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5823 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5825 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5832 *error = ResolveTokenError_BadTable;
5839 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5841 int table = mono_metadata_token_table (token);
5842 int idx = mono_metadata_token_index (token);
5843 MonoTableInfo *tables = image->tables;
5848 *error = ResolveTokenError_OutOfRange;
5850 /* FIXME: Support other tables ? */
5851 if (table != MONO_TABLE_STANDALONESIG)
5857 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5860 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5862 ptr = mono_metadata_blob_heap (image, sig);
5863 len = mono_metadata_decode_blob_size (ptr, &ptr);
5865 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5866 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5870 static MonoReflectionType*
5871 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5874 int isbyref = 0, rank;
5875 char *str = mono_string_to_utf8 (smodifiers);
5878 MONO_ARCH_SAVE_REGS;
5880 klass = mono_class_from_mono_type (tb->type.type);
5882 /* logic taken from mono_reflection_parse_type(): keep in sync */
5886 if (isbyref) { /* only one level allowed by the spec */
5893 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5896 klass = mono_ptr_class_get (&klass->byval_arg);
5897 mono_class_init (klass);
5908 else if (*p != '*') { /* '*' means unknown lower bound */
5919 klass = mono_array_class_get (klass, rank);
5920 mono_class_init (klass);
5927 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5931 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5936 MONO_ARCH_SAVE_REGS;
5939 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5944 static MonoReflectionType *
5945 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5947 MonoClass *klass, *aklass;
5949 MONO_ARCH_SAVE_REGS;
5951 klass = mono_class_from_mono_type (type->type);
5952 aklass = mono_array_class_get (klass, rank);
5954 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5957 static MonoReflectionType *
5958 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5962 MONO_ARCH_SAVE_REGS;
5964 klass = mono_class_from_mono_type (type->type);
5966 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5969 static MonoReflectionType *
5970 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5974 MONO_ARCH_SAVE_REGS;
5976 pklass = mono_ptr_class_get (type->type);
5978 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5982 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5983 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5985 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5986 MonoObject *delegate;
5988 MonoMethod *method = info->method;
5990 MONO_ARCH_SAVE_REGS;
5992 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5994 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5995 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5999 delegate = mono_object_new (mono_object_domain (type), delegate_class);
6001 if (mono_method_needs_static_rgctx_invoke (method, FALSE)) {
6002 method = mono_marshal_get_static_rgctx_invoke (method);
6003 func = mono_compile_method (method);
6004 } else if (method->dynamic) {
6005 /* Creating a trampoline would leak memory */
6006 func = mono_compile_method (method);
6008 func = mono_create_ftnptr (mono_domain_get (),
6009 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
6012 mono_delegate_ctor_with_method (delegate, target, func, method);
6018 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
6020 /* Reset the invoke impl to the default one */
6021 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
6025 * Magic number to convert a time which is relative to
6026 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
6028 #define EPOCH_ADJUST ((guint64)62135596800LL)
6031 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
6033 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
6035 #ifdef PLATFORM_WIN32
6036 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
6038 convert_to_absolute_date(SYSTEMTIME *date)
6040 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
6041 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6042 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
6043 /* from the calendar FAQ */
6044 int a = (14 - date->wMonth) / 12;
6045 int y = date->wYear - a;
6046 int m = date->wMonth + 12 * a - 2;
6047 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
6049 /* d is now the day of the week for the first of the month (0 == Sunday) */
6051 int day_of_week = date->wDayOfWeek;
6053 /* set day_in_month to the first day in the month which falls on day_of_week */
6054 int day_in_month = 1 + (day_of_week - d);
6055 if (day_in_month <= 0)
6058 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
6059 date->wDay = day_in_month + (date->wDay - 1) * 7;
6060 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
6065 #ifndef PLATFORM_WIN32
6067 * Return's the offset from GMT of a local time.
6069 * tm is a local time
6070 * t is the same local time as seconds.
6073 gmt_offset(struct tm *tm, time_t t)
6075 #if defined (HAVE_TM_GMTOFF)
6076 return tm->tm_gmtoff;
6081 g.tm_isdst = tm->tm_isdst;
6083 return (int)difftime(t, t2);
6088 * This is heavily based on zdump.c from glibc 2.2.
6090 * * data[0]: start of daylight saving time (in DateTime ticks).
6091 * * data[1]: end of daylight saving time (in DateTime ticks).
6092 * * data[2]: utcoffset (in TimeSpan ticks).
6093 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
6094 * * name[0]: name of this timezone when not daylight saving.
6095 * * name[1]: name of this timezone when daylight saving.
6097 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6098 * the class library allows years between 1 and 9999.
6100 * Returns true on success and zero on failure.
6103 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6105 #ifndef PLATFORM_WIN32
6106 MonoDomain *domain = mono_domain_get ();
6107 struct tm start, tt;
6111 int is_daylight = 0, day;
6114 MONO_ARCH_SAVE_REGS;
6116 MONO_CHECK_ARG_NULL (data);
6117 MONO_CHECK_ARG_NULL (names);
6119 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6120 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6123 * no info is better than crashing: we'll need our own tz data
6124 * to make this work properly, anyway. The range is probably
6125 * reduced to 1970 .. 2037 because that is what mktime is
6126 * guaranteed to support (we get into an infinite loop
6130 memset (&start, 0, sizeof (start));
6133 start.tm_year = year-1900;
6135 t = mktime (&start);
6137 if ((year < 1970) || (year > 2037) || (t == -1)) {
6139 tt = *localtime (&t);
6140 strftime (tzone, sizeof (tzone), "%Z", &tt);
6141 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6142 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6146 gmtoff = gmt_offset (&start, t);
6148 /* For each day of the year, calculate the tm_gmtoff. */
6149 for (day = 0; day < 365; day++) {
6152 tt = *localtime (&t);
6154 /* Daylight saving starts or ends here. */
6155 if (gmt_offset (&tt, t) != gmtoff) {
6159 /* Try to find the exact hour when daylight saving starts/ends. */
6163 tt1 = *localtime (&t1);
6164 } while (gmt_offset (&tt1, t1) != gmtoff);
6166 /* Try to find the exact minute when daylight saving starts/ends. */
6169 tt1 = *localtime (&t1);
6170 } while (gmt_offset (&tt1, t1) == gmtoff);
6172 strftime (tzone, sizeof (tzone), "%Z", &tt);
6174 /* Write data, if we're already in daylight saving, we're done. */
6176 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6177 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6180 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6181 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6185 /* This is only set once when we enter daylight saving. */
6186 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6187 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6189 gmtoff = gmt_offset (&tt, t);
6194 strftime (tzone, sizeof (tzone), "%Z", &tt);
6195 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6196 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6197 mono_array_set ((*data), gint64, 0, 0);
6198 mono_array_set ((*data), gint64, 1, 0);
6199 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6200 mono_array_set ((*data), gint64, 3, 0);
6205 MonoDomain *domain = mono_domain_get ();
6206 TIME_ZONE_INFORMATION tz_info;
6211 tz_id = GetTimeZoneInformation (&tz_info);
6212 if (tz_id == TIME_ZONE_ID_INVALID)
6215 MONO_CHECK_ARG_NULL (data);
6216 MONO_CHECK_ARG_NULL (names);
6218 (*data) = mono_array_new (domain, mono_defaults.int64_class, 4);
6219 (*names) = mono_array_new (domain, mono_defaults.string_class, 2);
6221 for (i = 0; i < 32; ++i)
6222 if (!tz_info.DaylightName [i])
6224 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6225 for (i = 0; i < 32; ++i)
6226 if (!tz_info.StandardName [i])
6228 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6230 if ((year <= 1601) || (year > 30827)) {
6232 * According to MSDN, the MS time functions can't handle dates outside
6238 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6239 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6240 tz_info.StandardDate.wYear = year;
6241 convert_to_absolute_date(&tz_info.StandardDate);
6242 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6247 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6248 tz_info.DaylightDate.wYear = year;
6249 convert_to_absolute_date(&tz_info.DaylightDate);
6250 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6255 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6257 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6258 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6265 ves_icall_System_Object_obj_address (MonoObject *this)
6267 MONO_ARCH_SAVE_REGS;
6274 static inline gint32
6275 mono_array_get_byte_length (MonoArray *array)
6281 klass = array->obj.vtable->klass;
6283 if (array->bounds == NULL)
6284 length = array->max_length;
6287 for (i = 0; i < klass->rank; ++ i)
6288 length *= array->bounds [i].length;
6291 switch (klass->element_class->byval_arg.type) {
6294 case MONO_TYPE_BOOLEAN:
6298 case MONO_TYPE_CHAR:
6306 return length * sizeof (gpointer);
6317 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6319 MONO_ARCH_SAVE_REGS;
6321 return mono_array_get_byte_length (array);
6325 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6327 MONO_ARCH_SAVE_REGS;
6329 return mono_array_get (array, gint8, idx);
6333 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6335 MONO_ARCH_SAVE_REGS;
6337 mono_array_set (array, gint8, idx, value);
6341 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6343 guint8 *src_buf, *dest_buf;
6345 MONO_ARCH_SAVE_REGS;
6347 /* watch out for integer overflow */
6348 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6351 src_buf = (guint8 *)src->vector + src_offset;
6352 dest_buf = (guint8 *)dest->vector + dest_offset;
6355 memcpy (dest_buf, src_buf, count);
6357 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6363 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6365 MonoDomain *domain = mono_object_domain (this);
6367 MonoRealProxy *rp = ((MonoRealProxy *)this);
6368 MonoTransparentProxy *tp;
6372 MONO_ARCH_SAVE_REGS;
6374 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6375 tp = (MonoTransparentProxy*) res;
6377 MONO_OBJECT_SETREF (tp, rp, rp);
6378 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6379 klass = mono_class_from_mono_type (type);
6381 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6382 tp->remote_class = mono_remote_class (domain, class_name, klass);
6384 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6388 static MonoReflectionType *
6389 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6391 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6394 /* System.Environment */
6397 ves_icall_System_Environment_get_UserName (void)
6399 MONO_ARCH_SAVE_REGS;
6401 /* using glib is more portable */
6402 return mono_string_new (mono_domain_get (), g_get_user_name ());
6407 ves_icall_System_Environment_get_MachineName (void)
6409 #if defined (PLATFORM_WIN32)
6414 len = MAX_COMPUTERNAME_LENGTH + 1;
6415 buf = g_new (gunichar2, len);
6418 if (GetComputerName (buf, (PDWORD) &len))
6419 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6423 #elif !defined(DISABLE_SOCKETS)
6427 if (gethostname (buf, sizeof (buf)) == 0)
6428 result = mono_string_new (mono_domain_get (), buf);
6434 return mono_string_new (mono_domain_get (), "mono");
6439 ves_icall_System_Environment_get_Platform (void)
6441 #if defined (PLATFORM_WIN32)
6444 #elif defined(__MACH__)
6446 if (mono_framework_version () < 2)
6450 // For compatibility with our client code, this will be 4 for a while.
6451 // We will eventually move to 6 to match .NET, but it requires all client
6452 // code to be updated and the documentation everywhere to be updated
6458 if (mono_framework_version () < 2)
6465 ves_icall_System_Environment_get_NewLine (void)
6467 MONO_ARCH_SAVE_REGS;
6469 #if defined (PLATFORM_WIN32)
6470 return mono_string_new (mono_domain_get (), "\r\n");
6472 return mono_string_new (mono_domain_get (), "\n");
6477 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6482 MONO_ARCH_SAVE_REGS;
6487 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6488 value = g_getenv (utf8_name);
6495 return mono_string_new (mono_domain_get (), value);
6499 * There is no standard way to get at environ.
6502 #ifndef __MINGW32_VERSION
6504 /* Apple defines this in crt_externs.h but doesn't provide that header for
6505 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6506 * in fact exist on all implementations (so far)
6508 gchar ***_NSGetEnviron();
6509 #define environ (*_NSGetEnviron())
6518 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6520 #ifdef PLATFORM_WIN32
6529 env_strings = GetEnvironmentStrings();
6532 env_string = env_strings;
6533 while (*env_string != '\0') {
6534 /* weird case that MS seems to skip */
6535 if (*env_string != '=')
6537 while (*env_string != '\0')
6543 domain = mono_domain_get ();
6544 names = mono_array_new (domain, mono_defaults.string_class, n);
6548 env_string = env_strings;
6549 while (*env_string != '\0') {
6550 /* weird case that MS seems to skip */
6551 if (*env_string != '=') {
6552 equal_str = wcschr(env_string, '=');
6553 g_assert(equal_str);
6554 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6555 mono_array_setref (names, n, str);
6558 while (*env_string != '\0')
6563 FreeEnvironmentStrings (env_strings);
6575 MONO_ARCH_SAVE_REGS;
6578 for (e = environ; *e != 0; ++ e)
6581 domain = mono_domain_get ();
6582 names = mono_array_new (domain, mono_defaults.string_class, n);
6585 for (e = environ; *e != 0; ++ e) {
6586 parts = g_strsplit (*e, "=", 2);
6588 str = mono_string_new (domain, *parts);
6589 mono_array_setref (names, n, str);
6602 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6604 #if !GLIB_CHECK_VERSION(2,4,0)
6605 #define g_setenv(a,b,c) setenv(a,b,c)
6606 #define g_unsetenv(a) unsetenv(a)
6610 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6612 #ifdef PLATFORM_WIN32
6613 gunichar2 *utf16_name, *utf16_value;
6615 gchar *utf8_name, *utf8_value;
6618 MONO_ARCH_SAVE_REGS;
6620 #ifdef PLATFORM_WIN32
6621 utf16_name = mono_string_to_utf16 (name);
6622 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6623 SetEnvironmentVariable (utf16_name, NULL);
6624 g_free (utf16_name);
6628 utf16_value = mono_string_to_utf16 (value);
6630 SetEnvironmentVariable (utf16_name, utf16_value);
6632 g_free (utf16_name);
6633 g_free (utf16_value);
6635 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6637 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6638 g_unsetenv (utf8_name);
6643 utf8_value = mono_string_to_utf8 (value);
6644 g_setenv (utf8_name, utf8_value, TRUE);
6647 g_free (utf8_value);
6652 ves_icall_System_Environment_Exit (int result)
6654 MONO_ARCH_SAVE_REGS;
6656 mono_threads_set_shutting_down ();
6658 mono_runtime_set_shutting_down ();
6660 /* Suspend all managed threads since the runtime is going away */
6661 mono_thread_suspend_all_other_threads ();
6663 mono_runtime_quit ();
6665 /* we may need to do some cleanup here... */
6670 ves_icall_System_Environment_GetGacPath (void)
6672 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6676 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6678 #if defined (PLATFORM_WIN32)
6679 #ifndef CSIDL_FLAG_CREATE
6680 #define CSIDL_FLAG_CREATE 0x8000
6683 WCHAR path [MAX_PATH];
6684 /* Create directory if no existing */
6685 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6689 return mono_string_new_utf16 (mono_domain_get (), path, len);
6692 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6694 return mono_string_new (mono_domain_get (), "");
6698 ves_icall_System_Environment_GetLogicalDrives (void)
6700 gunichar2 buf [128], *ptr, *dname;
6702 guint initial_size = 127, size = 128;
6705 MonoString *drivestr;
6706 MonoDomain *domain = mono_domain_get ();
6709 MONO_ARCH_SAVE_REGS;
6714 while (size > initial_size) {
6715 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6716 if (size > initial_size) {
6719 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6720 initial_size = size;
6734 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6739 while (*u16) { u16++; len ++; }
6740 drivestr = mono_string_new_utf16 (domain, dname, len);
6741 mono_array_setref (result, ndrives++, drivestr);
6752 ves_icall_System_Environment_InternalGetHome (void)
6754 MONO_ARCH_SAVE_REGS;
6756 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6759 static const char *encodings [] = {
6761 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6762 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6763 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6765 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6766 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6767 "x_unicode_2_0_utf_7",
6769 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6770 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6772 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6775 "unicodefffe", "utf_16be",
6782 * Returns the internal codepage, if the value of "int_code_page" is
6783 * 1 at entry, and we can not compute a suitable code page number,
6784 * returns the code page as a string
6787 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6792 char *codepage = NULL;
6794 int want_name = *int_code_page;
6797 *int_code_page = -1;
6798 MONO_ARCH_SAVE_REGS;
6800 g_get_charset (&cset);
6801 c = codepage = strdup (cset);
6802 for (c = codepage; *c; c++){
6803 if (isascii (*c) && isalpha (*c))
6808 /* g_print ("charset: %s\n", cset); */
6810 /* handle some common aliases */
6813 for (i = 0; p != 0; ){
6814 if ((gssize) p < 7){
6816 p = encodings [++i];
6819 if (strcmp (p, codepage) == 0){
6820 *int_code_page = code;
6823 p = encodings [++i];
6826 if (strstr (codepage, "utf_8") != NULL)
6827 *int_code_page |= 0x10000000;
6830 if (want_name && *int_code_page == -1)
6831 return mono_string_new (mono_domain_get (), cset);
6837 ves_icall_System_Environment_get_HasShutdownStarted (void)
6839 if (mono_runtime_is_shutting_down ())
6842 if (mono_domain_is_unloading (mono_domain_get ()))
6849 ves_icall_System_Environment_BroadcastSettingChange (void)
6851 #ifdef PLATFORM_WIN32
6852 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6857 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6858 MonoReflectionMethod *method,
6859 MonoArray *out_args)
6861 MONO_ARCH_SAVE_REGS;
6863 mono_message_init (mono_object_domain (this), this, method, out_args);
6867 ves_icall_IsTransparentProxy (MonoObject *proxy)
6869 MONO_ARCH_SAVE_REGS;
6874 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6880 static MonoReflectionMethod *
6881 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6882 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6886 MonoMethod **vtable;
6887 MonoMethod *res = NULL;
6889 MONO_CHECK_ARG_NULL (rtype);
6890 MONO_CHECK_ARG_NULL (rmethod);
6892 method = rmethod->method;
6893 klass = mono_class_from_mono_type (rtype->type);
6895 if (MONO_CLASS_IS_INTERFACE (klass))
6898 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6901 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6902 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6908 mono_class_setup_vtable (klass);
6909 vtable = klass->vtable;
6911 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6912 int offs = mono_class_interface_offset (klass, method->klass);
6914 res = vtable [offs + method->slot];
6916 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6919 if (method->slot != -1)
6920 res = vtable [method->slot];
6926 return mono_method_get_object (mono_domain_get (), res, NULL);
6930 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6935 MONO_ARCH_SAVE_REGS;
6937 klass = mono_class_from_mono_type (type->type);
6938 vtable = mono_class_vtable (mono_domain_get (), klass);
6940 if (enable) vtable->remote = 1;
6941 else vtable->remote = 0;
6945 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6950 MONO_ARCH_SAVE_REGS;
6952 domain = mono_object_domain (type);
6953 klass = mono_class_from_mono_type (type->type);
6955 if (klass->rank >= 1) {
6956 g_assert (klass->rank == 1);
6957 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6959 /* Bypass remoting object creation check */
6960 return mono_object_new_alloc_specific (mono_class_vtable (domain, klass));
6965 ves_icall_System_IO_get_temp_path (void)
6967 MONO_ARCH_SAVE_REGS;
6969 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6972 #ifndef PLATFORM_NO_DRIVEINFO
6974 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6975 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6979 ULARGE_INTEGER wapi_free_bytes_avail;
6980 ULARGE_INTEGER wapi_total_number_of_bytes;
6981 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6983 MONO_ARCH_SAVE_REGS;
6985 *error = ERROR_SUCCESS;
6986 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6987 &wapi_total_number_of_free_bytes);
6990 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6991 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6992 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6994 *free_bytes_avail = 0;
6995 *total_number_of_bytes = 0;
6996 *total_number_of_free_bytes = 0;
6997 *error = GetLastError ();
7004 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
7006 MONO_ARCH_SAVE_REGS;
7008 return GetDriveType (mono_string_chars (root_path_name));
7013 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
7015 MONO_ARCH_SAVE_REGS;
7017 return mono_compile_method (method);
7021 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
7026 MONO_ARCH_SAVE_REGS;
7028 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
7030 #if defined (PLATFORM_WIN32)
7031 /* Avoid mixing '/' and '\\' */
7034 for (i = strlen (path) - 1; i >= 0; i--)
7035 if (path [i] == '/')
7039 mcpath = mono_string_new (mono_domain_get (), path);
7046 get_bundled_machine_config (void)
7048 const gchar *machine_config;
7050 MONO_ARCH_SAVE_REGS;
7052 machine_config = mono_get_machine_config ();
7054 if (!machine_config)
7057 return mono_string_new (mono_domain_get (), machine_config);
7061 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7066 MONO_ARCH_SAVE_REGS;
7068 path = g_path_get_dirname (mono_get_config_dir ());
7070 #if defined (PLATFORM_WIN32)
7071 /* Avoid mixing '/' and '\\' */
7074 for (i = strlen (path) - 1; i >= 0; i--)
7075 if (path [i] == '/')
7079 ipath = mono_string_new (mono_domain_get (), path);
7086 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7088 MonoPEResourceDataEntry *entry;
7091 MONO_ARCH_SAVE_REGS;
7093 if (!assembly || !result || !size)
7098 image = assembly->assembly->image;
7099 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7103 *result = mono_image_rva_map (image, entry->rde_data_offset);
7108 *size = entry->rde_size;
7114 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7116 return mono_debug_using_mono_debugger ();
7120 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7122 #if defined (PLATFORM_WIN32)
7123 OutputDebugString (mono_string_chars (message));
7125 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
7129 /* Only used for value types */
7131 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7136 MONO_ARCH_SAVE_REGS;
7138 domain = mono_object_domain (type);
7139 klass = mono_class_from_mono_type (type->type);
7141 if (mono_class_is_nullable (klass))
7142 /* No arguments -> null */
7145 return mono_object_new (domain, klass);
7148 static MonoReflectionMethod *
7149 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
7151 MonoClass *klass, *parent;
7152 MonoMethod *method = m->method;
7153 MonoMethod *result = NULL;
7155 MONO_ARCH_SAVE_REGS;
7157 if (method->klass == NULL)
7160 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7161 MONO_CLASS_IS_INTERFACE (method->klass) ||
7162 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7165 klass = method->klass;
7166 if (klass->generic_class)
7167 klass = klass->generic_class->container_class;
7169 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7170 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7171 mono_class_setup_vtable (parent);
7172 if (parent->vtable_size <= method->slot)
7177 if (klass == method->klass)
7180 result = klass->vtable [method->slot];
7181 if (result == NULL) {
7182 /* It is an abstract method */
7183 gpointer iter = NULL;
7184 while ((result = mono_class_get_methods (klass, &iter)))
7185 if (result->slot == method->slot)
7192 return mono_method_get_object (mono_domain_get (), result, NULL);
7196 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7198 MonoMethod *method = m->method;
7200 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7205 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7207 MONO_ARCH_SAVE_REGS;
7209 iter->sig = *(MonoMethodSignature**)argsp;
7211 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7212 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7215 /* FIXME: it's not documented what start is exactly... */
7219 guint32 i, arg_size;
7221 iter->args = argsp + sizeof (gpointer);
7222 #ifndef MONO_ARCH_REGPARMS
7223 for (i = 0; i < iter->sig->sentinelpos; ++i) {
7224 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
7225 iter->args = (char*)iter->args + arg_size;
7229 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7231 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7235 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7237 guint32 i, arg_size;
7240 MONO_ARCH_SAVE_REGS;
7242 i = iter->sig->sentinelpos + iter->next_arg;
7244 g_assert (i < iter->sig->param_count);
7246 res.type = iter->sig->params [i];
7247 res.klass = mono_class_from_mono_type (res.type);
7248 res.value = iter->args;
7249 arg_size = mono_type_stack_size (res.type, &align);
7250 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7251 if (arg_size <= sizeof (gpointer)) {
7253 int padding = arg_size - mono_type_size (res.type, &dummy);
7254 res.value = (guint8*)res.value + padding;
7257 iter->args = (char*)iter->args + arg_size;
7260 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7266 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7268 guint32 i, arg_size;
7271 MONO_ARCH_SAVE_REGS;
7273 i = iter->sig->sentinelpos + iter->next_arg;
7275 g_assert (i < iter->sig->param_count);
7277 while (i < iter->sig->param_count) {
7278 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7280 res.type = iter->sig->params [i];
7281 res.klass = mono_class_from_mono_type (res.type);
7282 /* FIXME: endianess issue... */
7283 res.value = iter->args;
7284 arg_size = mono_type_stack_size (res.type, &align);
7285 iter->args = (char*)iter->args + arg_size;
7287 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7290 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7299 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7302 MONO_ARCH_SAVE_REGS;
7304 i = iter->sig->sentinelpos + iter->next_arg;
7306 g_assert (i < iter->sig->param_count);
7308 return iter->sig->params [i];
7312 mono_TypedReference_ToObject (MonoTypedRef tref)
7314 MONO_ARCH_SAVE_REGS;
7316 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7317 MonoObject** objp = tref.value;
7321 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7325 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7327 MONO_ARCH_SAVE_REGS;
7329 if (MONO_TYPE_IS_REFERENCE (type)) {
7330 MonoObject** objp = value;
7334 return mono_value_box (mono_domain_get (), klass, value);
7338 prelink_method (MonoMethod *method)
7340 const char *exc_class, *exc_arg;
7341 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7343 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7345 mono_raise_exception(
7346 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7348 /* create the wrapper, too? */
7352 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7354 MONO_ARCH_SAVE_REGS;
7355 prelink_method (method->method);
7359 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7361 MonoClass *klass = mono_class_from_mono_type (type->type);
7363 gpointer iter = NULL;
7364 MONO_ARCH_SAVE_REGS;
7366 while ((m = mono_class_get_methods (klass, &iter)))
7370 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7372 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7373 gint32 const **exponents,
7374 gunichar2 const **digitLowerTable,
7375 gunichar2 const **digitUpperTable,
7376 gint64 const **tenPowersList,
7377 gint32 const **decHexDigits)
7379 *mantissas = Formatter_MantissaBitsTable;
7380 *exponents = Formatter_TensExponentTable;
7381 *digitLowerTable = Formatter_DigitLowerTable;
7382 *digitUpperTable = Formatter_DigitUpperTable;
7383 *tenPowersList = Formatter_TenPowersList;
7384 *decHexDigits = Formatter_DecHexDigits;
7387 /* These parameters are "readonly" in corlib/System/Char.cs */
7389 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7390 guint8 const **numeric_data,
7391 gdouble const **numeric_data_values,
7392 guint16 const **to_lower_data_low,
7393 guint16 const **to_lower_data_high,
7394 guint16 const **to_upper_data_low,
7395 guint16 const **to_upper_data_high)
7397 *category_data = CategoryData;
7398 *numeric_data = NumericData;
7399 *numeric_data_values = NumericDataValues;
7400 *to_lower_data_low = ToLowerDataLow;
7401 *to_lower_data_high = ToLowerDataHigh;
7402 *to_upper_data_low = ToUpperDataLow;
7403 *to_upper_data_high = ToUpperDataHigh;
7407 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7409 return method->method->token;
7413 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7414 * and avoid useless allocations.
7417 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7421 for (i = 0; i < type->num_mods; ++i) {
7422 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7427 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7429 for (i = 0; i < type->num_mods; ++i) {
7430 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7431 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7432 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7440 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7442 MonoType *type = param->ClassImpl->type;
7443 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7444 MonoImage *image = method->method->klass->image;
7445 int pos = param->PositionImpl;
7446 MonoMethodSignature *sig = mono_method_signature (method->method);
7450 type = sig->params [pos];
7452 return type_array_from_modifiers (image, type, optional);
7456 get_property_type (MonoProperty *prop)
7458 MonoMethodSignature *sig;
7460 sig = mono_method_signature (prop->get);
7462 } else if (prop->set) {
7463 sig = mono_method_signature (prop->set);
7464 return sig->params [sig->param_count - 1];
7470 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7472 MonoType *type = get_property_type (property->property);
7473 MonoImage *image = property->klass->image;
7477 return type_array_from_modifiers (image, type, optional);
7481 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7483 MonoCustomAttrInfo *cinfo;
7486 cinfo = mono_reflection_get_custom_attrs_info (obj);
7489 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7491 mono_custom_attrs_free (cinfo);
7496 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7498 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7500 if (mono_loader_get_last_error ()) {
7501 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7502 g_assert_not_reached ();
7509 GCHandle_CheckCurrentDomain (guint32 gchandle)
7511 return mono_gchandle_is_in_domain (gchandle, mono_domain_get ());
7515 ves_icall_Mono_Runtime_GetDisplayName (void)
7517 static const char display_name_str [] = "Mono " VERSION;
7518 MonoString *display_name = mono_string_new (mono_domain_get (), display_name_str);
7519 return display_name;
7523 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7525 MonoString *message;
7529 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7530 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7533 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7535 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7543 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7544 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7545 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7546 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7547 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7548 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7549 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7550 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7554 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7559 gunichar2 last, prev_last, prev2_last;
7567 last = prev_last = 0, prev2_last = 0;
7568 for (i = 0; i < ilength; i++) {
7570 if (c >= sizeof (dbase64)) {
7571 exc = mono_exception_from_name_msg (mono_get_corlib (),
7572 "System", "FormatException",
7573 "Invalid character found.");
7574 mono_raise_exception (exc);
7575 } else if (isspace (c)) {
7578 prev2_last = prev_last;
7584 olength = ilength - ignored;
7586 if (allowWhitespaceOnly && olength == 0) {
7587 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7590 if ((olength & 3) != 0 || olength <= 0) {
7591 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7592 "FormatException", "Invalid length.");
7593 mono_raise_exception (exc);
7596 if (prev2_last == '=') {
7597 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7598 mono_raise_exception (exc);
7601 olength = (olength * 3) / 4;
7605 if (prev_last == '=')
7608 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7609 res_ptr = mono_array_addr (result, guchar, 0);
7610 for (i = 0; i < ilength; ) {
7613 for (k = 0; k < 4 && i < ilength;) {
7619 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7620 exc = mono_exception_from_name_msg (mono_get_corlib (),
7621 "System", "FormatException",
7622 "Invalid character found.");
7623 mono_raise_exception (exc);
7628 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7630 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7632 *res_ptr++ = (b [2] << 6) | b [3];
7634 while (i < ilength && isspace (start [i]))
7642 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7644 MONO_ARCH_SAVE_REGS;
7646 return base64_to_byte_array (mono_string_chars (str),
7647 mono_string_length (str), allowWhitespaceOnly);
7651 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7653 MONO_ARCH_SAVE_REGS;
7655 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7659 #define ICALL_TYPE(id,name,first)
7660 #define ICALL(id,name,func) Icall_ ## id,
7663 #include "metadata/icall-def.h"
7669 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7670 #define ICALL(id,name,func)
7672 #include "metadata/icall-def.h"
7678 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7679 #define ICALL(id,name,func)
7681 guint16 first_icall;
7684 static const IcallTypeDesc
7685 icall_type_descs [] = {
7686 #include "metadata/icall-def.h"
7690 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7693 #define ICALL_TYPE(id,name,first)
7696 #ifdef HAVE_ARRAY_ELEM_INIT
7697 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7698 #define MSGSTRFIELD1(line) str##line
7700 static const struct msgstrtn_t {
7701 #define ICALL(id,name,func)
7703 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7704 #include "metadata/icall-def.h"
7706 } icall_type_names_str = {
7707 #define ICALL_TYPE(id,name,first) (name),
7708 #include "metadata/icall-def.h"
7711 static const guint16 icall_type_names_idx [] = {
7712 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7713 #include "metadata/icall-def.h"
7716 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7718 static const struct msgstr_t {
7720 #define ICALL_TYPE(id,name,first)
7721 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7722 #include "metadata/icall-def.h"
7724 } icall_names_str = {
7725 #define ICALL(id,name,func) (name),
7726 #include "metadata/icall-def.h"
7729 static const guint16 icall_names_idx [] = {
7730 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7731 #include "metadata/icall-def.h"
7734 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7740 #define ICALL_TYPE(id,name,first) name,
7741 #define ICALL(id,name,func)
7742 static const char* const
7743 icall_type_names [] = {
7744 #include "metadata/icall-def.h"
7748 #define icall_type_name_get(id) (icall_type_names [(id)])
7752 #define ICALL_TYPE(id,name,first)
7753 #define ICALL(id,name,func) name,
7754 static const char* const
7756 #include "metadata/icall-def.h"
7759 #define icall_name_get(id) icall_names [(id)]
7761 #endif /* !HAVE_ARRAY_ELEM_INIT */
7765 #define ICALL_TYPE(id,name,first)
7766 #define ICALL(id,name,func) func,
7767 static const gconstpointer
7768 icall_functions [] = {
7769 #include "metadata/icall-def.h"
7773 static GHashTable *icall_hash = NULL;
7774 static GHashTable *jit_icall_hash_name = NULL;
7775 static GHashTable *jit_icall_hash_addr = NULL;
7778 mono_icall_init (void)
7782 /* check that tables are sorted: disable in release */
7785 const char *prev_class = NULL;
7786 const char *prev_method;
7788 for (i = 0; i < Icall_type_num; ++i) {
7789 const IcallTypeDesc *desc;
7792 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7793 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7794 prev_class = icall_type_name_get (i);
7795 desc = &icall_type_descs [i];
7796 num_icalls = icall_desc_num_icalls (desc);
7797 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7798 for (j = 0; j < num_icalls; ++j) {
7799 const char *methodn = icall_name_get (desc->first_icall + j);
7800 if (prev_method && strcmp (prev_method, methodn) >= 0)
7801 g_print ("method %s should come before method %s\n", methodn, prev_method);
7802 prev_method = methodn;
7807 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7811 mono_icall_cleanup (void)
7813 g_hash_table_destroy (icall_hash);
7814 g_hash_table_destroy (jit_icall_hash_name);
7815 g_hash_table_destroy (jit_icall_hash_addr);
7819 mono_add_internal_call (const char *name, gconstpointer method)
7821 mono_loader_lock ();
7823 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7825 mono_loader_unlock ();
7828 #ifdef HAVE_ARRAY_ELEM_INIT
7830 compare_method_imap (const void *key, const void *elem)
7832 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7833 return strcmp (key, method_name);
7837 find_method_icall (const IcallTypeDesc *imap, const char *name)
7839 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7842 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7846 compare_class_imap (const void *key, const void *elem)
7848 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7849 return strcmp (key, class_name);
7852 static const IcallTypeDesc*
7853 find_class_icalls (const char *name)
7855 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7858 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7863 compare_method_imap (const void *key, const void *elem)
7865 const char** method_name = (const char**)elem;
7866 return strcmp (key, *method_name);
7870 find_method_icall (const IcallTypeDesc *imap, const char *name)
7872 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7875 return (gpointer)icall_functions [(nameslot - icall_names)];
7879 compare_class_imap (const void *key, const void *elem)
7881 const char** class_name = (const char**)elem;
7882 return strcmp (key, *class_name);
7885 static const IcallTypeDesc*
7886 find_class_icalls (const char *name)
7888 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7891 return &icall_type_descs [nameslot - icall_type_names];
7897 * we should probably export this as an helper (handle nested types).
7898 * Returns the number of chars written in buf.
7901 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7903 int nspacelen, cnamelen;
7904 nspacelen = strlen (klass->name_space);
7905 cnamelen = strlen (klass->name);
7906 if (nspacelen + cnamelen + 2 > bufsize)
7909 memcpy (buf, klass->name_space, nspacelen);
7910 buf [nspacelen ++] = '.';
7912 memcpy (buf + nspacelen, klass->name, cnamelen);
7913 buf [nspacelen + cnamelen] = 0;
7914 return nspacelen + cnamelen;
7918 mono_lookup_internal_call (MonoMethod *method)
7923 int typelen = 0, mlen, siglen;
7925 const IcallTypeDesc *imap;
7927 g_assert (method != NULL);
7929 if (method->is_inflated)
7930 method = ((MonoMethodInflated *) method)->declaring;
7932 if (method->klass->nested_in) {
7933 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7937 mname [pos++] = '/';
7940 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7946 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7951 imap = find_class_icalls (mname);
7953 mname [typelen] = ':';
7954 mname [typelen + 1] = ':';
7956 mlen = strlen (method->name);
7957 memcpy (mname + typelen + 2, method->name, mlen);
7958 sigstart = mname + typelen + 2 + mlen;
7961 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7962 siglen = strlen (tmpsig);
7963 if (typelen + mlen + siglen + 6 > sizeof (mname))
7966 memcpy (sigstart + 1, tmpsig, siglen);
7967 sigstart [siglen + 1] = ')';
7968 sigstart [siglen + 2] = 0;
7971 mono_loader_lock ();
7973 res = g_hash_table_lookup (icall_hash, mname);
7975 mono_loader_unlock ();
7978 /* try without signature */
7980 res = g_hash_table_lookup (icall_hash, mname);
7982 mono_loader_unlock ();
7986 /* it wasn't found in the static call tables */
7988 mono_loader_unlock ();
7991 res = find_method_icall (imap, sigstart - mlen);
7993 mono_loader_unlock ();
7996 /* try _with_ signature */
7998 res = find_method_icall (imap, sigstart - mlen);
8000 mono_loader_unlock ();
8004 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8005 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8006 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8007 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8008 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");
8009 g_print ("If you see other errors or faults after this message they are probably related\n");
8010 g_print ("and you need to fix your mono install first.\n");
8012 mono_loader_unlock ();
8018 type_from_typename (char *typename)
8020 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8022 if (!strcmp (typename, "int"))
8023 klass = mono_defaults.int_class;
8024 else if (!strcmp (typename, "ptr"))
8025 klass = mono_defaults.int_class;
8026 else if (!strcmp (typename, "void"))
8027 klass = mono_defaults.void_class;
8028 else if (!strcmp (typename, "int32"))
8029 klass = mono_defaults.int32_class;
8030 else if (!strcmp (typename, "uint32"))
8031 klass = mono_defaults.uint32_class;
8032 else if (!strcmp (typename, "int8"))
8033 klass = mono_defaults.sbyte_class;
8034 else if (!strcmp (typename, "uint8"))
8035 klass = mono_defaults.byte_class;
8036 else if (!strcmp (typename, "int16"))
8037 klass = mono_defaults.int16_class;
8038 else if (!strcmp (typename, "uint16"))
8039 klass = mono_defaults.uint16_class;
8040 else if (!strcmp (typename, "long"))
8041 klass = mono_defaults.int64_class;
8042 else if (!strcmp (typename, "ulong"))
8043 klass = mono_defaults.uint64_class;
8044 else if (!strcmp (typename, "float"))
8045 klass = mono_defaults.single_class;
8046 else if (!strcmp (typename, "double"))
8047 klass = mono_defaults.double_class;
8048 else if (!strcmp (typename, "object"))
8049 klass = mono_defaults.object_class;
8050 else if (!strcmp (typename, "obj"))
8051 klass = mono_defaults.object_class;
8052 else if (!strcmp (typename, "string"))
8053 klass = mono_defaults.string_class;
8054 else if (!strcmp (typename, "bool"))
8055 klass = mono_defaults.boolean_class;
8056 else if (!strcmp (typename, "boolean"))
8057 klass = mono_defaults.boolean_class;
8059 g_error ("%s", typename);
8060 g_assert_not_reached ();
8062 return &klass->byval_arg;
8065 MonoMethodSignature*
8066 mono_create_icall_signature (const char *sigstr)
8071 MonoMethodSignature *res;
8073 mono_loader_lock ();
8074 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8076 mono_loader_unlock ();
8080 parts = g_strsplit (sigstr, " ", 256);
8089 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8092 #ifdef PLATFORM_WIN32
8094 * Under windows, the default pinvoke calling convention is STDCALL but
8097 res->call_convention = MONO_CALL_C;
8100 res->ret = type_from_typename (parts [0]);
8101 for (i = 1; i < len; ++i) {
8102 res->params [i - 1] = type_from_typename (parts [i]);
8107 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8109 mono_loader_unlock ();
8115 mono_find_jit_icall_by_name (const char *name)
8117 MonoJitICallInfo *info;
8118 g_assert (jit_icall_hash_name);
8120 mono_loader_lock ();
8121 info = g_hash_table_lookup (jit_icall_hash_name, name);
8122 mono_loader_unlock ();
8127 mono_find_jit_icall_by_addr (gconstpointer addr)
8129 MonoJitICallInfo *info;
8130 g_assert (jit_icall_hash_addr);
8132 mono_loader_lock ();
8133 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8134 mono_loader_unlock ();
8140 * mono_get_jit_icall_info:
8142 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8143 * caller should access it while holding the loader lock.
8146 mono_get_jit_icall_info (void)
8148 return jit_icall_hash_name;
8152 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8154 mono_loader_lock ();
8155 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8156 mono_loader_unlock ();
8160 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8162 MonoJitICallInfo *info;
8167 mono_loader_lock ();
8169 if (!jit_icall_hash_name) {
8170 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8171 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8174 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8175 g_warning ("jit icall already defined \"%s\"\n", name);
8176 g_assert_not_reached ();
8179 info = g_new0 (MonoJitICallInfo, 1);
8186 info->wrapper = func;
8188 info->wrapper = NULL;
8191 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8192 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8194 mono_loader_unlock ();