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>
75 #include <mono/utils/mono-string.h>
77 #if defined (PLATFORM_WIN32)
83 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
86 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
88 /* This is an implementation of a growable pointer array that avoids doing memory allocations for small sizes.
89 * It works by allocating an initial small array on stack and only going to malloc'd memory if needed.
97 #define MONO_PTR_ARRAY_MAX_ON_STACK (16)
99 #define mono_ptr_array_init(ARRAY, INITIAL_SIZE) do {\
101 (ARRAY).capacity = MAX (INITIAL_SIZE, MONO_PTR_ARRAY_MAX_ON_STACK); \
102 (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); \
105 #define mono_ptr_array_destroy(ARRAY) do {\
106 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
107 mono_gc_free_fixed ((ARRAY).data); \
110 #define mono_ptr_array_append(ARRAY, VALUE) do { \
111 if ((ARRAY).size >= (ARRAY).capacity) {\
112 void *__tmp = mono_gc_alloc_fixed (sizeof (void*) * (ARRAY).capacity * 2, NULL); \
113 memcpy (__tmp, (ARRAY).data, (ARRAY).capacity * sizeof (void*)); \
114 if ((ARRAY).capacity > MONO_PTR_ARRAY_MAX_ON_STACK) \
115 mono_gc_free_fixed ((ARRAY).data); \
116 (ARRAY).data = __tmp; \
117 (ARRAY).capacity *= 2;\
119 ((ARRAY).data [(ARRAY).size++] = VALUE); \
122 #define mono_ptr_array_set(ARRAY, IDX, VALUE) do { \
123 ((ARRAY).data [(IDX)] = VALUE); \
126 #define mono_ptr_array_get(ARRAY, IDX) ((ARRAY).data [(IDX)])
128 #define mono_ptr_array_size(ARRAY) ((ARRAY).size)
131 static inline MonoBoolean
132 is_generic_parameter (MonoType *type)
134 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
138 * We expect a pointer to a char, not a string
141 mono_double_ParseImpl (char *ptr, double *result)
143 gchar *endptr = NULL;
150 *result = strtod (ptr, &endptr);
154 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
155 EnterCriticalSection (&mono_strtod_mutex);
156 *result = mono_strtod (ptr, &endptr);
157 LeaveCriticalSection (&mono_strtod_mutex);
159 *result = mono_strtod (ptr, &endptr);
164 if (!*ptr || (endptr && *endptr))
171 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
180 ao = (MonoArray *)this;
181 ac = (MonoClass *)ao->obj.vtable->klass;
183 esize = mono_array_element_size (ac);
184 ea = (gpointer*)((char*)ao->vector + (pos * esize));
186 if (ac->element_class->valuetype)
187 return mono_value_box (this->vtable->domain, ac->element_class, ea);
193 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
201 MONO_CHECK_ARG_NULL (idxs);
203 io = (MonoArray *)idxs;
204 ic = (MonoClass *)io->obj.vtable->klass;
206 ao = (MonoArray *)this;
207 ac = (MonoClass *)ao->obj.vtable->klass;
209 g_assert (ic->rank == 1);
210 if (io->bounds != NULL || io->max_length != ac->rank)
211 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
213 ind = (gint32 *)io->vector;
215 if (ao->bounds == NULL) {
216 if (*ind < 0 || *ind >= ao->max_length)
217 mono_raise_exception (mono_get_exception_index_out_of_range ());
219 return ves_icall_System_Array_GetValueImpl (this, *ind);
222 for (i = 0; i < ac->rank; i++)
223 if ((ind [i] < ao->bounds [i].lower_bound) ||
224 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
225 mono_raise_exception (mono_get_exception_index_out_of_range ());
227 pos = ind [0] - ao->bounds [0].lower_bound;
228 for (i = 1; i < ac->rank; i++)
229 pos = pos*ao->bounds [i].length + ind [i] -
230 ao->bounds [i].lower_bound;
232 return ves_icall_System_Array_GetValueImpl (this, pos);
236 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
238 MonoClass *ac, *vc, *ec;
250 vc = value->vtable->klass;
254 ac = this->obj.vtable->klass;
255 ec = ac->element_class;
257 esize = mono_array_element_size (ac);
258 ea = (gpointer*)((char*)this->vector + (pos * esize));
259 va = (gpointer*)((char*)value + sizeof (MonoObject));
262 memset (ea, 0, esize);
266 #define NO_WIDENING_CONVERSION G_STMT_START{\
267 mono_raise_exception (mono_get_exception_argument ( \
268 "value", "not a widening conversion")); \
271 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
272 if (esize < vsize + (extra)) \
273 mono_raise_exception (mono_get_exception_argument ( \
274 "value", "not a widening conversion")); \
277 #define INVALID_CAST G_STMT_START{\
278 mono_raise_exception (mono_get_exception_invalid_cast ()); \
281 /* Check element (destination) type. */
282 switch (ec->byval_arg.type) {
283 case MONO_TYPE_STRING:
284 switch (vc->byval_arg.type) {
285 case MONO_TYPE_STRING:
291 case MONO_TYPE_BOOLEAN:
292 switch (vc->byval_arg.type) {
293 case MONO_TYPE_BOOLEAN:
306 NO_WIDENING_CONVERSION;
313 if (!ec->valuetype) {
314 if (!mono_object_isinst (value, ec))
316 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
320 if (mono_object_isinst (value, ec)) {
321 if (ec->has_references)
322 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
324 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
331 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
333 et = ec->byval_arg.type;
334 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
335 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
337 vt = vc->byval_arg.type;
338 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
339 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
341 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
347 case MONO_TYPE_CHAR: \
348 CHECK_WIDENING_CONVERSION(0); \
349 *(etype *) ea = (etype) u64; \
351 /* You can't assign a signed value to an unsigned array. */ \
356 /* You can't assign a floating point number to an integer array. */ \
359 NO_WIDENING_CONVERSION; \
363 #define ASSIGN_SIGNED(etype) G_STMT_START{\
369 CHECK_WIDENING_CONVERSION(0); \
370 *(etype *) ea = (etype) i64; \
372 /* You can assign an unsigned value to a signed array if the array's */ \
373 /* element size is larger than the value size. */ \
378 case MONO_TYPE_CHAR: \
379 CHECK_WIDENING_CONVERSION(1); \
380 *(etype *) ea = (etype) u64; \
382 /* You can't assign a floating point number to an integer array. */ \
385 NO_WIDENING_CONVERSION; \
389 #define ASSIGN_REAL(etype) G_STMT_START{\
393 CHECK_WIDENING_CONVERSION(0); \
394 *(etype *) ea = (etype) r64; \
396 /* All integer values fit into a floating point array, so we don't */ \
397 /* need to CHECK_WIDENING_CONVERSION here. */ \
402 *(etype *) ea = (etype) i64; \
408 case MONO_TYPE_CHAR: \
409 *(etype *) ea = (etype) u64; \
416 u64 = *(guint8 *) va;
419 u64 = *(guint16 *) va;
422 u64 = *(guint32 *) va;
425 u64 = *(guint64 *) va;
431 i64 = *(gint16 *) va;
434 i64 = *(gint32 *) va;
437 i64 = *(gint64 *) va;
440 r64 = *(gfloat *) va;
443 r64 = *(gdouble *) va;
446 u64 = *(guint16 *) va;
448 case MONO_TYPE_BOOLEAN:
449 /* Boolean is only compatible with itself. */
462 NO_WIDENING_CONVERSION;
469 /* If we can't do a direct copy, let's try a widening conversion. */
472 ASSIGN_UNSIGNED (guint16);
474 ASSIGN_UNSIGNED (guint8);
476 ASSIGN_UNSIGNED (guint16);
478 ASSIGN_UNSIGNED (guint32);
480 ASSIGN_UNSIGNED (guint64);
482 ASSIGN_SIGNED (gint8);
484 ASSIGN_SIGNED (gint16);
486 ASSIGN_SIGNED (gint32);
488 ASSIGN_SIGNED (gint64);
490 ASSIGN_REAL (gfloat);
492 ASSIGN_REAL (gdouble);
496 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
500 #undef NO_WIDENING_CONVERSION
501 #undef CHECK_WIDENING_CONVERSION
502 #undef ASSIGN_UNSIGNED
508 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
516 MONO_CHECK_ARG_NULL (idxs);
518 ic = idxs->obj.vtable->klass;
519 ac = this->obj.vtable->klass;
521 g_assert (ic->rank == 1);
522 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
523 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
525 ind = (gint32 *)idxs->vector;
527 if (this->bounds == NULL) {
528 if (*ind < 0 || *ind >= this->max_length)
529 mono_raise_exception (mono_get_exception_index_out_of_range ());
531 ves_icall_System_Array_SetValueImpl (this, value, *ind);
535 for (i = 0; i < ac->rank; i++)
536 if ((ind [i] < this->bounds [i].lower_bound) ||
537 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
538 mono_raise_exception (mono_get_exception_index_out_of_range ());
540 pos = ind [0] - this->bounds [0].lower_bound;
541 for (i = 1; i < ac->rank; i++)
542 pos = pos * this->bounds [i].length + ind [i] -
543 this->bounds [i].lower_bound;
545 ves_icall_System_Array_SetValueImpl (this, value, pos);
549 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
553 mono_array_size_t *sizes, i;
554 gboolean bounded = FALSE;
558 MONO_CHECK_ARG_NULL (type);
559 MONO_CHECK_ARG_NULL (lengths);
561 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
563 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
565 for (i = 0; i < mono_array_length (lengths); i++)
566 if (mono_array_get (lengths, gint32, i) < 0)
567 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
569 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
570 /* vectors are not the same as one dimensional arrays with no-zero bounds */
575 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
577 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
578 for (i = 0; i < aklass->rank; ++i) {
579 sizes [i] = mono_array_get (lengths, guint32, i);
581 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
583 sizes [i + aklass->rank] = 0;
586 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
592 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
596 mono_array_size_t *sizes, i;
597 gboolean bounded = FALSE;
601 MONO_CHECK_ARG_NULL (type);
602 MONO_CHECK_ARG_NULL (lengths);
604 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
606 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
608 for (i = 0; i < mono_array_length (lengths); i++)
609 if ((mono_array_get (lengths, gint64, i) < 0) ||
610 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
611 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
613 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
614 /* vectors are not the same as one dimensional arrays with no-zero bounds */
619 aklass = mono_bounded_array_class_get (mono_class_from_mono_type (type->type), mono_array_length (lengths), bounded);
621 sizes = alloca (aklass->rank * sizeof(mono_array_size_t) * 2);
622 for (i = 0; i < aklass->rank; ++i) {
623 sizes [i] = mono_array_get (lengths, guint64, i);
625 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
627 sizes [i + aklass->rank] = 0;
630 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, sizes + aklass->rank);
636 ves_icall_System_Array_GetRank (MonoObject *this)
640 return this->vtable->klass->rank;
644 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
646 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
647 mono_array_size_t length;
651 if ((dimension < 0) || (dimension >= rank))
652 mono_raise_exception (mono_get_exception_index_out_of_range ());
654 if (this->bounds == NULL)
655 length = this->max_length;
657 length = this->bounds [dimension].length;
659 #ifdef MONO_BIG_ARRAYS
660 if (length > G_MAXINT32)
661 mono_raise_exception (mono_get_exception_overflow ());
667 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
669 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
673 if ((dimension < 0) || (dimension >= rank))
674 mono_raise_exception (mono_get_exception_index_out_of_range ());
676 if (this->bounds == NULL)
677 return this->max_length;
679 return this->bounds [dimension].length;
683 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
685 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
689 if ((dimension < 0) || (dimension >= rank))
690 mono_raise_exception (mono_get_exception_index_out_of_range ());
692 if (this->bounds == NULL)
695 return this->bounds [dimension].lower_bound;
699 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
701 int sz = mono_array_element_size (mono_object_class (arr));
702 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
706 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
711 MonoClass *src_class;
712 MonoClass *dest_class;
717 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
720 if (source->bounds || dest->bounds)
723 if ((dest_idx + length > mono_array_length (dest)) ||
724 (source_idx + length > mono_array_length (source)))
727 src_class = source->obj.vtable->klass->element_class;
728 dest_class = dest->obj.vtable->klass->element_class;
731 * Handle common cases.
734 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
735 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
736 int has_refs = dest_class->has_references;
737 for (i = source_idx; i < source_idx + length; ++i) {
738 MonoObject *elem = mono_array_get (source, MonoObject*, i);
739 if (elem && !mono_object_isinst (elem, dest_class))
743 element_size = mono_array_element_size (dest->obj.vtable->klass);
744 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
745 for (i = 0; i < length; ++i) {
746 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
747 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
751 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
753 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
758 /* Check if we're copying a char[] <==> (u)short[] */
759 if (src_class != dest_class) {
760 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
763 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
765 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
766 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
767 for (i = source_idx; i < source_idx + length; ++i) {
768 MonoObject *elem = mono_array_get (source, MonoObject*, i);
769 if (elem && !mono_object_isinst (elem, dest_class))
776 if (dest_class->valuetype) {
777 element_size = mono_array_element_size (source->obj.vtable->klass);
778 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
779 if (dest_class->has_references) {
780 mono_value_copy_array (dest, dest_idx, source_addr, length);
782 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
783 memmove (dest_addr, source_addr, element_size * length);
786 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
793 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
802 ao = (MonoArray *)this;
803 ac = (MonoClass *)ao->obj.vtable->klass;
805 esize = mono_array_element_size (ac);
806 ea = (gpointer*)((char*)ao->vector + (pos * esize));
808 memcpy (value, ea, esize);
812 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
821 ao = (MonoArray *)this;
822 ac = (MonoClass *)ao->obj.vtable->klass;
823 ec = ac->element_class;
825 esize = mono_array_element_size (ac);
826 ea = (gpointer*)((char*)ao->vector + (pos * esize));
828 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
829 g_assert (esize == sizeof (gpointer));
830 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
832 g_assert (ec->inited);
833 if (ec->has_references)
834 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
835 memcpy (ea, value, esize);
840 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
842 MonoClass *klass = array->obj.vtable->klass;
843 guint32 size = mono_array_element_size (klass);
844 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
846 const char *field_data;
848 if (MONO_TYPE_IS_REFERENCE (type) ||
849 (type->type == MONO_TYPE_VALUETYPE &&
850 (!mono_type_get_class (type) ||
851 mono_type_get_class (type)->has_references))) {
852 MonoException *exc = mono_get_exception_argument("array",
853 "Cannot initialize array containing references");
854 mono_raise_exception (exc);
857 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
858 MonoException *exc = mono_get_exception_argument("field_handle",
859 "Field doesn't have an RVA");
860 mono_raise_exception (exc);
863 size *= array->max_length;
864 field_data = mono_field_get_data (field_handle);
866 if (size > mono_type_size (field_handle->type, &align)) {
867 MonoException *exc = mono_get_exception_argument("field_handle",
868 "Field not large enough to fill array");
869 mono_raise_exception (exc);
872 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
874 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
875 guint ## n *src = (guint ## n *) field_data; \
876 guint ## n *end = (guint ## n *)((char*)src + size); \
878 for (; src < end; data++, src++) { \
879 *data = read ## n (src); \
883 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
885 switch (type->type) {
902 memcpy (mono_array_addr (array, char, 0), field_data, size);
906 memcpy (mono_array_addr (array, char, 0), field_data, size);
908 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
911 double *data = (double*)mono_array_addr (array, double, 0);
913 for (i = 0; i < size; i++, data++) {
923 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
927 return offsetof (MonoString, chars);
931 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
935 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
938 return mono_object_clone (obj);
942 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
947 MONO_CHECK_ARG_NULL (handle);
949 klass = mono_class_from_mono_type (handle);
950 MONO_CHECK_ARG (handle, klass);
952 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
954 /* This will call the type constructor */
955 mono_runtime_class_init (vtable);
959 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
963 mono_image_check_for_module_cctor (image);
964 if (image->has_module_cctor) {
965 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
966 /*It's fine to raise the exception here*/
967 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
972 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
976 return mono_object_clone (this);
980 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
983 MonoObject **values = NULL;
987 MonoClassField* field;
992 klass = mono_object_class (this);
994 if (mono_class_num_fields (klass) == 0)
995 return mono_object_hash (this);
998 * Compute the starting value of the hashcode for fields of primitive
999 * types, and return the remaining fields in an array to the managed side.
1000 * This way, we can avoid costly reflection operations in managed code.
1003 while ((field = mono_class_get_fields (klass, &iter))) {
1004 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1006 if (mono_field_is_deleted (field))
1008 /* FIXME: Add more types */
1009 switch (field->type->type) {
1011 result ^= *(gint32*)((guint8*)this + field->offset);
1013 case MONO_TYPE_STRING: {
1015 s = *(MonoString**)((guint8*)this + field->offset);
1017 result ^= mono_string_hash (s);
1022 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1023 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1024 values [count++] = o;
1030 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1031 for (i = 0; i < count; ++i)
1032 mono_array_setref (*fields, i, values [i]);
1040 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1043 MonoObject **values = NULL;
1045 MonoClassField* field;
1049 MONO_ARCH_SAVE_REGS;
1051 MONO_CHECK_ARG_NULL (that);
1053 if (this->vtable != that->vtable)
1056 klass = mono_object_class (this);
1058 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1059 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1062 * Do the comparison for fields of primitive type and return a result if
1063 * possible. Otherwise, return the remaining fields in an array to the
1064 * managed side. This way, we can avoid costly reflection operations in
1069 while ((field = mono_class_get_fields (klass, &iter))) {
1070 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1072 if (mono_field_is_deleted (field))
1074 /* FIXME: Add more types */
1075 switch (field->type->type) {
1078 case MONO_TYPE_BOOLEAN:
1079 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1084 case MONO_TYPE_CHAR:
1085 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1090 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1095 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1099 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1103 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1108 case MONO_TYPE_STRING: {
1109 MonoString *s1, *s2;
1110 guint32 s1len, s2len;
1111 s1 = *(MonoString**)((guint8*)this + field->offset);
1112 s2 = *(MonoString**)((guint8*)that + field->offset);
1115 if ((s1 == NULL) || (s2 == NULL))
1117 s1len = mono_string_length (s1);
1118 s2len = mono_string_length (s2);
1122 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1128 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1129 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1130 values [count++] = o;
1131 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1132 values [count++] = o;
1135 if (klass->enumtype)
1136 /* enums only have one non-static field */
1142 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1143 for (i = 0; i < count; ++i)
1144 mono_array_setref (*fields, i, values [i]);
1151 static MonoReflectionType *
1152 ves_icall_System_Object_GetType (MonoObject *obj)
1154 MONO_ARCH_SAVE_REGS;
1156 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1157 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1159 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1163 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1165 MONO_ARCH_SAVE_REGS;
1167 mtype->type = &obj->vtable->klass->byval_arg;
1168 g_assert (mtype->type->type);
1172 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1174 MONO_ARCH_SAVE_REGS;
1176 MONO_CHECK_ARG_NULL (obj);
1178 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1182 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1183 MonoReflectionMethod *method,
1184 MonoArray *opt_param_types)
1186 MONO_ARCH_SAVE_REGS;
1188 MONO_CHECK_ARG_NULL (method);
1190 return mono_image_create_method_token (
1191 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1195 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1197 MONO_ARCH_SAVE_REGS;
1199 mono_image_create_pefile (mb, file);
1203 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1205 MONO_ARCH_SAVE_REGS;
1207 mono_image_build_metadata (mb);
1211 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1213 MONO_ARCH_SAVE_REGS;
1215 mono_image_register_token (mb->dynamic_image, token, obj);
1219 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1221 MonoMethod **dest = data;
1223 /* skip unmanaged frames */
1239 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1241 MonoMethod **dest = data;
1243 /* skip unmanaged frames */
1248 if (!strcmp (m->klass->name_space, "System.Reflection"))
1257 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1259 MonoMethod **dest = data;
1261 /* skip unmanaged frames */
1265 if (m->wrapper_type != MONO_WRAPPER_NONE)
1268 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1282 static MonoReflectionType *
1283 type_from_name (const char *str, MonoBoolean ignoreCase)
1285 MonoType *type = NULL;
1286 MonoAssembly *assembly = NULL;
1287 MonoTypeNameParse info;
1288 char *temp_str = g_strdup (str);
1289 gboolean type_resolve = FALSE;
1291 MONO_ARCH_SAVE_REGS;
1293 /* mono_reflection_parse_type() mangles the string */
1294 if (!mono_reflection_parse_type (temp_str, &info)) {
1295 mono_reflection_free_type_info (&info);
1300 if (info.assembly.name) {
1301 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1303 MonoMethod *m = mono_method_get_last_managed ();
1304 MonoMethod *dest = m;
1306 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1311 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1312 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1313 * to crash. This only seems to happen in some strange remoting
1314 * scenarios and I was unable to figure out what's happening there.
1315 * Dec 10, 2005 - Martin.
1319 assembly = dest->klass->image->assembly;
1321 g_warning (G_STRLOC);
1326 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1328 if (!info.assembly.name && !type) /* try mscorlib */
1329 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1331 mono_reflection_free_type_info (&info);
1337 return mono_type_get_object (mono_domain_get (), type);
1341 MonoReflectionType *
1342 mono_type_get (const char *str)
1344 char *copy = g_strdup (str);
1345 MonoReflectionType *type = type_from_name (copy, FALSE);
1352 static MonoReflectionType*
1353 ves_icall_type_from_name (MonoString *name,
1354 MonoBoolean throwOnError,
1355 MonoBoolean ignoreCase)
1357 char *str = mono_string_to_utf8 (name);
1358 MonoReflectionType *type;
1360 type = type_from_name (str, ignoreCase);
1363 MonoException *e = NULL;
1366 e = mono_get_exception_type_load (name, NULL);
1368 mono_loader_clear_error ();
1370 mono_raise_exception (e);
1377 static MonoReflectionType*
1378 ves_icall_type_from_handle (MonoType *handle)
1380 MonoDomain *domain = mono_domain_get ();
1381 MonoClass *klass = mono_class_from_mono_type (handle);
1383 MONO_ARCH_SAVE_REGS;
1385 mono_class_init (klass);
1386 return mono_type_get_object (domain, handle);
1390 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1392 MONO_ARCH_SAVE_REGS;
1394 if (c && type->type && c->type)
1395 return mono_metadata_type_equal (type->type, c->type);
1397 return (type == c) ? TRUE : FALSE;
1400 /* System.TypeCode */
1419 TYPECODE_STRING = 18
1423 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1425 int t = type->type->type;
1427 MONO_ARCH_SAVE_REGS;
1429 if (type->type->byref)
1430 return TYPECODE_OBJECT;
1434 case MONO_TYPE_VOID:
1435 return TYPECODE_OBJECT;
1436 case MONO_TYPE_BOOLEAN:
1437 return TYPECODE_BOOLEAN;
1439 return TYPECODE_BYTE;
1441 return TYPECODE_SBYTE;
1443 return TYPECODE_UINT16;
1445 return TYPECODE_INT16;
1446 case MONO_TYPE_CHAR:
1447 return TYPECODE_CHAR;
1451 return TYPECODE_OBJECT;
1453 return TYPECODE_UINT32;
1455 return TYPECODE_INT32;
1457 return TYPECODE_UINT64;
1459 return TYPECODE_INT64;
1461 return TYPECODE_SINGLE;
1463 return TYPECODE_DOUBLE;
1464 case MONO_TYPE_VALUETYPE:
1465 if (type->type->data.klass->enumtype) {
1466 t = mono_class_enum_basetype (type->type->data.klass)->type;
1469 MonoClass *k = type->type->data.klass;
1470 if (strcmp (k->name_space, "System") == 0) {
1471 if (strcmp (k->name, "Decimal") == 0)
1472 return TYPECODE_DECIMAL;
1473 else if (strcmp (k->name, "DateTime") == 0)
1474 return TYPECODE_DATETIME;
1477 return TYPECODE_OBJECT;
1478 case MONO_TYPE_STRING:
1479 return TYPECODE_STRING;
1480 case MONO_TYPE_SZARRAY:
1481 case MONO_TYPE_ARRAY:
1482 case MONO_TYPE_OBJECT:
1484 case MONO_TYPE_MVAR:
1485 case MONO_TYPE_TYPEDBYREF:
1486 return TYPECODE_OBJECT;
1487 case MONO_TYPE_CLASS:
1489 MonoClass *k = type->type->data.klass;
1490 if (strcmp (k->name_space, "System") == 0) {
1491 if (strcmp (k->name, "DBNull") == 0)
1492 return TYPECODE_DBNULL;
1495 return TYPECODE_OBJECT;
1496 case MONO_TYPE_GENERICINST:
1497 return TYPECODE_OBJECT;
1499 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1505 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1511 MONO_ARCH_SAVE_REGS;
1513 g_assert (type != NULL);
1515 domain = ((MonoObject *)type)->vtable->domain;
1517 if (!c) /* FIXME: dont know what do do here */
1520 klass = mono_class_from_mono_type (type->type);
1521 klassc = mono_class_from_mono_type (c->type);
1523 if (type->type->byref)
1524 return klassc == mono_defaults.object_class;
1526 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1530 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1536 MONO_ARCH_SAVE_REGS;
1538 g_assert (type != NULL);
1540 domain = ((MonoObject *)type)->vtable->domain;
1542 klass = mono_class_from_mono_type (type->type);
1543 klassc = mono_class_from_mono_type (c->type);
1545 if (type->type->byref && !c->type->byref)
1548 return mono_class_is_assignable_from (klass, klassc);
1552 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1554 MonoClass *klass = mono_class_from_mono_type (type->type);
1555 return mono_object_isinst (obj, klass) != NULL;
1559 ves_icall_get_attributes (MonoReflectionType *type)
1561 MonoClass *klass = mono_class_from_mono_type (type->type);
1563 MONO_ARCH_SAVE_REGS;
1565 return klass->flags;
1568 static MonoReflectionMarshal*
1569 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1571 MonoClass *klass = field->field->parent;
1572 MonoMarshalType *info;
1575 if (klass->generic_container ||
1576 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1579 info = mono_marshal_load_type_info (klass);
1581 for (i = 0; i < info->num_fields; ++i) {
1582 if (info->fields [i].field == field->field) {
1583 if (!info->fields [i].mspec)
1586 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1593 static MonoReflectionField*
1594 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1596 gboolean found = FALSE;
1603 klass = handle->parent;
1605 klass = mono_class_from_mono_type (type);
1607 /* Check that the field belongs to the class */
1608 for (k = klass; k; k = k->parent) {
1609 if (k == handle->parent) {
1616 /* The managed code will throw the exception */
1620 return mono_field_get_object (mono_domain_get (), klass, handle);
1623 static MonoReflectionField*
1624 ves_icall_System_Reflection_FieldInfo_internal_from_handle (MonoClassField *handle)
1626 MONO_ARCH_SAVE_REGS;
1630 return mono_field_get_object (mono_domain_get (), handle->parent, handle);
1634 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1636 MonoType *type = field->field->type;
1638 return type_array_from_modifiers (field->field->parent->image, type, optional);
1642 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1644 MonoDomain *domain = mono_domain_get ();
1645 MonoMethodSignature* sig;
1646 MONO_ARCH_SAVE_REGS;
1648 sig = mono_method_signature (method);
1650 g_assert (mono_loader_get_last_error ());
1651 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1654 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1655 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1656 info->attrs = method->flags;
1657 info->implattrs = method->iflags;
1658 if (sig->call_convention == MONO_CALL_DEFAULT)
1659 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1661 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1666 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1670 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1672 MonoDomain *domain = mono_domain_get ();
1674 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1677 static MonoReflectionMarshal*
1678 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1680 MonoDomain *domain = mono_domain_get ();
1681 MonoReflectionMarshal* res = NULL;
1682 MonoMarshalSpec **mspecs;
1685 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1686 mono_method_get_marshal_info (method, mspecs);
1689 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1691 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1693 mono_metadata_free_marshal_spec (mspecs [i]);
1700 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1702 return field->field->offset - sizeof (MonoObject);
1705 static MonoReflectionType*
1706 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1709 MONO_ARCH_SAVE_REGS;
1711 parent = declaring? field->field->parent: field->klass;
1713 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1717 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1720 MonoClassField *cf = field->field;
1724 MonoDomain *domain = mono_object_domain (field);
1726 gboolean is_static = FALSE;
1727 gboolean is_ref = FALSE;
1729 MONO_ARCH_SAVE_REGS;
1731 if (field->klass->image->assembly->ref_only)
1732 mono_raise_exception (mono_get_exception_invalid_operation (
1733 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1735 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1736 mono_security_core_clr_ensure_reflection_access_field (cf);
1738 mono_class_init (field->klass);
1740 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC)
1743 if (obj && !is_static) {
1744 /* Check that the field belongs to the object */
1745 gboolean found = FALSE;
1748 for (k = obj->vtable->klass; k; k = k->parent) {
1749 if (k == cf->parent) {
1756 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);
1757 MonoException *ex = mono_get_exception_argument (NULL, msg);
1759 mono_raise_exception (ex);
1763 t = mono_type_get_underlying_type (cf->type);
1765 case MONO_TYPE_STRING:
1766 case MONO_TYPE_OBJECT:
1767 case MONO_TYPE_CLASS:
1768 case MONO_TYPE_ARRAY:
1769 case MONO_TYPE_SZARRAY:
1774 case MONO_TYPE_BOOLEAN:
1777 case MONO_TYPE_CHAR:
1786 case MONO_TYPE_VALUETYPE:
1789 case MONO_TYPE_GENERICINST:
1790 if (mono_type_generic_inst_is_valuetype (t)) {
1797 g_error ("type 0x%x not handled in "
1798 "ves_icall_Monofield_GetValue", t->type);
1804 vtable = mono_class_vtable_full (domain, cf->parent, TRUE);
1805 if (!vtable->initialized && !(cf->type->attrs & FIELD_ATTRIBUTE_LITERAL))
1806 mono_runtime_class_init (vtable);
1811 mono_field_static_get_value (vtable, cf, &o);
1813 mono_field_get_value (obj, cf, &o);
1818 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1819 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1822 /* Convert the Nullable structure into a boxed vtype */
1824 buf = (guint8*)vtable->data + cf->offset;
1826 buf = (guint8*)obj + cf->offset;
1828 return mono_nullable_box (buf, nklass);
1831 /* boxed value type */
1832 klass = mono_class_from_mono_type (cf->type);
1833 o = mono_object_new (domain, klass);
1834 v = ((gchar *) o) + sizeof (MonoObject);
1836 mono_field_static_get_value (vtable, cf, v);
1838 mono_field_get_value (obj, cf, v);
1845 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1847 MonoClassField *cf = field->field;
1850 MONO_ARCH_SAVE_REGS;
1852 if (field->klass->image->assembly->ref_only)
1853 mono_raise_exception (mono_get_exception_invalid_operation (
1854 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1856 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1857 mono_security_core_clr_ensure_reflection_access_field (cf);
1859 v = (gchar *) value;
1860 if (!cf->type->byref) {
1861 switch (cf->type->type) {
1864 case MONO_TYPE_BOOLEAN:
1867 case MONO_TYPE_CHAR:
1876 case MONO_TYPE_VALUETYPE:
1878 v += sizeof (MonoObject);
1880 case MONO_TYPE_STRING:
1881 case MONO_TYPE_OBJECT:
1882 case MONO_TYPE_CLASS:
1883 case MONO_TYPE_ARRAY:
1884 case MONO_TYPE_SZARRAY:
1887 case MONO_TYPE_GENERICINST: {
1888 MonoGenericClass *gclass = cf->type->data.generic_class;
1889 g_assert (!gclass->context.class_inst->is_open);
1891 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1892 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1893 MonoObject *nullable;
1896 * Convert the boxed vtype into a Nullable structure.
1897 * This is complicated by the fact that Nullables have
1898 * a variable structure.
1900 nullable = mono_object_new (mono_domain_get (), nklass);
1902 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1904 v = mono_object_unbox (nullable);
1907 if (gclass->container_class->valuetype && (v != NULL))
1908 v += sizeof (MonoObject);
1912 g_error ("type 0x%x not handled in "
1913 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1918 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1919 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1920 if (!vtable->initialized)
1921 mono_runtime_class_init (vtable);
1922 mono_field_static_set_value (vtable, cf, v);
1924 mono_field_set_value (obj, cf, v);
1929 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1931 MonoObject *o = NULL;
1932 MonoClassField *field = this->field;
1934 MonoDomain *domain = mono_object_domain (this);
1936 MonoTypeEnum def_type;
1937 const char *def_value;
1939 MONO_ARCH_SAVE_REGS;
1941 mono_class_init (field->parent);
1943 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1944 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1946 if (field->parent->image->dynamic) {
1948 g_assert_not_reached ();
1951 def_value = mono_class_get_field_default_value (field, &def_type);
1956 case MONO_TYPE_BOOLEAN:
1959 case MONO_TYPE_CHAR:
1967 case MONO_TYPE_R8: {
1970 /* boxed value type */
1971 t = g_new0 (MonoType, 1);
1973 klass = mono_class_from_mono_type (t);
1975 o = mono_object_new (domain, klass);
1976 v = ((gchar *) o) + sizeof (MonoObject);
1977 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1980 case MONO_TYPE_STRING:
1981 case MONO_TYPE_CLASS:
1982 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1985 g_assert_not_reached ();
1991 static MonoReflectionType*
1992 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1994 MonoMethod *method = rmethod->method.method;
1996 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1999 /* From MonoProperty.cs */
2001 PInfo_Attributes = 1,
2002 PInfo_GetMethod = 1 << 1,
2003 PInfo_SetMethod = 1 << 2,
2004 PInfo_ReflectedType = 1 << 3,
2005 PInfo_DeclaringType = 1 << 4,
2010 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2012 MonoDomain *domain = mono_object_domain (property);
2014 MONO_ARCH_SAVE_REGS;
2016 if ((req_info & PInfo_ReflectedType) != 0)
2017 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2018 else if ((req_info & PInfo_DeclaringType) != 0)
2019 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
2021 if ((req_info & PInfo_Name) != 0)
2022 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2024 if ((req_info & PInfo_Attributes) != 0)
2025 info->attrs = property->property->attrs;
2027 if ((req_info & PInfo_GetMethod) != 0)
2028 MONO_STRUCT_SETREF (info, get, property->property->get ?
2029 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2031 if ((req_info & PInfo_SetMethod) != 0)
2032 MONO_STRUCT_SETREF (info, set, property->property->set ?
2033 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2035 * There may be other methods defined for properties, though, it seems they are not exposed
2036 * in the reflection API
2041 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2043 MonoDomain *domain = mono_object_domain (event);
2045 MONO_ARCH_SAVE_REGS;
2047 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2048 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2050 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2051 info->attrs = event->event->attrs;
2052 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2053 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2054 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2056 if (event->event->other) {
2058 while (event->event->other [n])
2060 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2062 for (i = 0; i < n; i++)
2063 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2068 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2070 MonoDomain *domain = mono_object_domain (type);
2072 GPtrArray *ifaces = NULL;
2074 MonoClass *class = mono_class_from_mono_type (type->type);
2077 MonoGenericContext *context = NULL;
2079 MONO_ARCH_SAVE_REGS;
2081 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2082 context = mono_class_get_context (class);
2083 class = class->generic_class->container_class;
2086 mono_class_setup_vtable (class);
2088 slots = mono_bitset_new (class->max_interface_id + 1, 0);
2090 for (parent = class; parent; parent = parent->parent) {
2091 GPtrArray *tmp_ifaces = mono_class_get_implemented_interfaces (parent);
2093 for (i = 0; i < tmp_ifaces->len; ++i) {
2094 MonoClass *ic = g_ptr_array_index (tmp_ifaces, i);
2096 if (mono_bitset_test (slots, ic->interface_id))
2099 mono_bitset_set (slots, ic->interface_id);
2101 ifaces = g_ptr_array_new ();
2102 g_ptr_array_add (ifaces, ic);
2104 g_ptr_array_free (tmp_ifaces, TRUE);
2107 mono_bitset_free (slots);
2110 return mono_array_new_cached (domain, mono_defaults.monotype_class, 0);
2112 intf = mono_array_new_cached (domain, mono_defaults.monotype_class, ifaces->len);
2113 for (i = 0; i < ifaces->len; ++i) {
2114 MonoClass *ic = g_ptr_array_index (ifaces, i);
2115 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2116 if (context && ic->generic_class && ic->generic_class->context.class_inst->is_open)
2117 inflated = ret = mono_class_inflate_generic_type (ret, context);
2119 mono_array_setref (intf, i, mono_type_get_object (domain, ret));
2121 mono_metadata_free_type (inflated);
2123 g_ptr_array_free (ifaces, TRUE);
2129 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2131 MonoClass *class = mono_class_from_mono_type (type->type);
2132 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2133 MonoReflectionMethod *member;
2136 int i = 0, len, ioffset;
2139 MONO_ARCH_SAVE_REGS;
2141 mono_class_setup_vtable (class);
2143 /* type doesn't implement iface: the exception is thrown in managed code */
2144 if (! MONO_CLASS_IMPLEMENTS_INTERFACE (class, iclass->interface_id))
2147 len = mono_class_num_methods (iclass);
2148 ioffset = mono_class_interface_offset (class, iclass);
2149 domain = mono_object_domain (type);
2150 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2151 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2154 while ((method = mono_class_get_methods (iclass, &iter))) {
2155 member = mono_method_get_object (domain, method, iclass);
2156 mono_array_setref (*methods, i, member);
2157 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2158 mono_array_setref (*targets, i, member);
2165 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2167 MonoClass *klass = mono_class_from_mono_type (type->type);
2169 if (klass->image->dynamic) {
2170 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2171 *packing = tb->packing_size;
2172 *size = tb->class_size;
2174 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2178 static MonoReflectionType*
2179 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2183 MONO_ARCH_SAVE_REGS;
2185 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2186 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2188 class = mono_class_from_mono_type (type->type);
2190 // GetElementType should only return a type for:
2191 // Array Pointer PassedByRef
2192 if (type->type->byref)
2193 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2194 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2195 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2196 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2197 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2202 static MonoReflectionType*
2203 ves_icall_get_type_parent (MonoReflectionType *type)
2205 MonoClass *class = mono_class_from_mono_type (type->type);
2207 MONO_ARCH_SAVE_REGS;
2209 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2213 ves_icall_type_ispointer (MonoReflectionType *type)
2215 MONO_ARCH_SAVE_REGS;
2217 return type->type->type == MONO_TYPE_PTR;
2221 ves_icall_type_isprimitive (MonoReflectionType *type)
2223 MONO_ARCH_SAVE_REGS;
2225 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)));
2229 ves_icall_type_isbyref (MonoReflectionType *type)
2231 MONO_ARCH_SAVE_REGS;
2233 return type->type->byref;
2237 ves_icall_type_iscomobject (MonoReflectionType *type)
2239 MonoClass *klass = mono_class_from_mono_type (type->type);
2240 MONO_ARCH_SAVE_REGS;
2242 return (klass && klass->is_com_object);
2245 static MonoReflectionModule*
2246 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2248 MonoClass *class = mono_class_from_mono_type (type->type);
2250 MONO_ARCH_SAVE_REGS;
2252 return mono_module_get_object (mono_object_domain (type), class->image);
2255 static MonoReflectionAssembly*
2256 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2258 MonoDomain *domain = mono_domain_get ();
2259 MonoClass *class = mono_class_from_mono_type (type->type);
2261 MONO_ARCH_SAVE_REGS;
2263 return mono_assembly_get_object (domain, class->image->assembly);
2266 static MonoReflectionType*
2267 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2269 MonoDomain *domain = mono_domain_get ();
2272 MONO_ARCH_SAVE_REGS;
2274 if (type->type->byref)
2276 if (type->type->type == MONO_TYPE_VAR)
2277 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2278 else if (type->type->type == MONO_TYPE_MVAR)
2279 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2281 class = mono_class_from_mono_type (type->type)->nested_in;
2283 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2286 static MonoReflectionType*
2287 ves_icall_MonoType_get_UnderlyingSystemType (MonoReflectionType *type)
2289 MonoDomain *domain = mono_domain_get ();
2290 MonoClass *class = mono_class_from_mono_type (type->type);
2292 MONO_ARCH_SAVE_REGS;
2294 if (class->enumtype && mono_class_enum_basetype (class)) /* types that are modified typebuilders may not have enum_basetype set */
2295 return mono_type_get_object (domain, mono_class_enum_basetype (class));
2296 else if (class->element_class)
2297 return mono_type_get_object (domain, &class->element_class->byval_arg);
2303 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2305 MonoDomain *domain = mono_domain_get ();
2306 MonoClass *class = mono_class_from_mono_type (type->type);
2308 MONO_ARCH_SAVE_REGS;
2310 if (type->type->byref) {
2311 char *n = g_strdup_printf ("%s&", class->name);
2312 MonoString *res = mono_string_new (domain, n);
2318 return mono_string_new (domain, class->name);
2323 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2325 MonoDomain *domain = mono_domain_get ();
2326 MonoClass *class = mono_class_from_mono_type (type->type);
2328 MONO_ARCH_SAVE_REGS;
2330 while (class->nested_in)
2331 class = class->nested_in;
2333 if (class->name_space [0] == '\0')
2336 return mono_string_new (domain, class->name_space);
2340 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2344 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2345 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2347 class = mono_class_from_mono_type (type->type);
2352 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2355 MonoClass *klass, *pklass;
2356 MonoDomain *domain = mono_object_domain (type);
2357 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2359 MONO_ARCH_SAVE_REGS;
2361 klass = mono_class_from_mono_type (type->type);
2363 if (klass->generic_container) {
2364 MonoGenericContainer *container = klass->generic_container;
2365 res = mono_array_new_specific (array_vtable, container->type_argc);
2366 for (i = 0; i < container->type_argc; ++i) {
2367 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2368 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2370 } else if (klass->generic_class) {
2371 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2372 res = mono_array_new_specific (array_vtable, inst->type_argc);
2373 for (i = 0; i < inst->type_argc; ++i)
2374 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2376 res = mono_array_new_specific (array_vtable, 0);
2382 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2385 MONO_ARCH_SAVE_REGS;
2387 if (!IS_MONOTYPE (type))
2390 if (type->type->byref)
2393 klass = mono_class_from_mono_type (type->type);
2395 return klass->generic_container != NULL;
2398 static MonoReflectionType*
2399 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2402 MONO_ARCH_SAVE_REGS;
2404 if (type->type->byref)
2407 klass = mono_class_from_mono_type (type->type);
2408 if (klass->generic_container) {
2409 return type; /* check this one */
2411 if (klass->generic_class) {
2412 MonoClass *generic_class = klass->generic_class->container_class;
2414 if (generic_class->wastypebuilder && generic_class->reflection_info)
2415 return generic_class->reflection_info;
2417 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2422 static MonoReflectionType*
2423 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2425 MonoType *geninst, **types;
2428 MONO_ARCH_SAVE_REGS;
2430 count = mono_array_length (type_array);
2431 types = g_new0 (MonoType *, count);
2433 for (i = 0; i < count; i++) {
2434 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2435 types [i] = t->type;
2438 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2443 return mono_type_get_object (mono_object_domain (type), geninst);
2447 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2450 MONO_ARCH_SAVE_REGS;
2452 if (type->type->byref)
2455 klass = mono_class_from_mono_type (type->type);
2456 return klass->generic_class != NULL;
2460 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2463 MONO_ARCH_SAVE_REGS;
2465 if (!IS_MONOTYPE (type))
2468 if (type->type->byref)
2471 klass = mono_class_from_mono_type (type->type);
2472 return klass->generic_class != NULL || klass->generic_container != NULL;
2476 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2478 MONO_ARCH_SAVE_REGS;
2480 if (!IS_MONOTYPE (type))
2483 if (is_generic_parameter (type->type))
2484 return mono_type_get_generic_param_num (type->type);
2488 static GenericParameterAttributes
2489 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2491 MONO_ARCH_SAVE_REGS;
2493 g_assert (IS_MONOTYPE (type));
2494 g_assert (is_generic_parameter (type->type));
2495 return mono_generic_param_info (type->type->data.generic_param)->flags;
2499 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2501 MonoGenericParamInfo *param_info;
2507 MONO_ARCH_SAVE_REGS;
2509 g_assert (IS_MONOTYPE (type));
2511 domain = mono_object_domain (type);
2512 param_info = mono_generic_param_info (type->type->data.generic_param);
2513 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2516 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2517 for (i = 0; i < count; i++)
2518 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2525 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2527 MONO_ARCH_SAVE_REGS;
2528 return is_generic_parameter (type->type);
2532 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2534 MONO_ARCH_SAVE_REGS;
2535 return is_generic_parameter (tb->type.type);
2539 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2540 MonoReflectionType *t)
2542 enumtype->type = t->type;
2545 static MonoReflectionMethod*
2546 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2547 MonoReflectionMethod* generic)
2554 MONO_ARCH_SAVE_REGS;
2556 domain = ((MonoObject *)type)->vtable->domain;
2558 klass = mono_class_from_mono_type (type->type);
2561 while ((method = mono_class_get_methods (klass, &iter))) {
2562 if (method->token == generic->method->token)
2563 return mono_method_get_object (domain, method, klass);
2571 static MonoReflectionMethod *
2572 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2575 MonoType *type = ref_type->type;
2577 MONO_ARCH_SAVE_REGS;
2579 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2580 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2581 if (type->type == MONO_TYPE_VAR)
2584 method = mono_type_get_generic_param_owner (type)->owner.method;
2586 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2589 static MonoReflectionDllImportAttribute*
2590 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2592 static MonoClass *DllImportAttributeClass = NULL;
2593 MonoDomain *domain = mono_domain_get ();
2594 MonoReflectionDllImportAttribute *attr;
2595 MonoImage *image = method->klass->image;
2596 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2597 MonoTableInfo *tables = image->tables;
2598 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2599 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2600 guint32 im_cols [MONO_IMPLMAP_SIZE];
2601 guint32 scope_token;
2602 const char *import = NULL;
2603 const char *scope = NULL;
2606 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2609 if (!DllImportAttributeClass) {
2610 DllImportAttributeClass =
2611 mono_class_from_name (mono_defaults.corlib,
2612 "System.Runtime.InteropServices", "DllImportAttribute");
2613 g_assert (DllImportAttributeClass);
2616 if (method->klass->image->dynamic) {
2617 MonoReflectionMethodAux *method_aux =
2618 g_hash_table_lookup (
2619 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2621 import = method_aux->dllentry;
2622 scope = method_aux->dll;
2625 if (!import || !scope) {
2626 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2631 if (piinfo->implmap_idx) {
2632 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2634 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2635 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2636 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2637 scope = mono_metadata_string_heap (image, scope_token);
2640 flags = piinfo->piflags;
2642 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2644 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2645 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2646 attr->call_conv = (flags & 0x700) >> 8;
2647 attr->charset = ((flags & 0x6) >> 1) + 1;
2648 if (attr->charset == 1)
2650 attr->exact_spelling = (flags & 0x1) != 0;
2651 attr->set_last_error = (flags & 0x40) != 0;
2652 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2653 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2654 attr->preserve_sig = FALSE;
2659 static MonoReflectionMethod *
2660 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2662 MonoMethodInflated *imethod;
2665 MONO_ARCH_SAVE_REGS;
2667 if (method->method->is_generic)
2670 if (!method->method->is_inflated)
2673 imethod = (MonoMethodInflated *) method->method;
2675 result = imethod->declaring;
2676 /* Not a generic method. */
2677 if (!result->is_generic)
2680 if (method->method->klass->image->dynamic) {
2681 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2682 MonoReflectionMethod *res;
2685 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2686 * the dynamic case as well ?
2688 mono_loader_lock ();
2689 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2690 mono_loader_unlock ();
2696 if (imethod->context.class_inst) {
2697 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2698 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2701 return mono_method_get_object (mono_object_domain (method), result, NULL);
2705 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2707 MONO_ARCH_SAVE_REGS;
2709 return mono_method_signature (method->method)->generic_param_count != 0;
2713 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2715 MONO_ARCH_SAVE_REGS;
2717 return method->method->is_generic;
2721 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2726 MONO_ARCH_SAVE_REGS;
2728 domain = mono_object_domain (method);
2730 if (method->method->is_inflated) {
2731 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2734 count = inst->type_argc;
2735 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2737 for (i = 0; i < count; i++)
2738 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2744 count = mono_method_signature (method->method)->generic_param_count;
2745 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2747 for (i = 0; i < count; i++) {
2748 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2749 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2750 MonoClass *pklass = mono_class_from_generic_parameter (
2751 param, method->method->klass->image, TRUE);
2752 mono_array_setref (res, i,
2753 mono_type_get_object (domain, &pklass->byval_arg));
2760 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2763 * Invoke from reflection is supposed to always be a virtual call (the API
2764 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2765 * greater flexibility.
2767 MonoMethod *m = method->method;
2771 MONO_ARCH_SAVE_REGS;
2775 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2776 mono_security_core_clr_ensure_reflection_access_method (m);
2778 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2780 if (!mono_object_isinst (this, m->klass)) {
2781 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2784 m = mono_object_get_virtual_method (this, m);
2785 /* must pass the pointer to the value for valuetype methods */
2786 if (m->klass->valuetype)
2787 obj = mono_object_unbox (this);
2788 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2789 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2794 pcount = params? mono_array_length (params): 0;
2795 if (pcount != mono_method_signature (m)->param_count) {
2796 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2800 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2801 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2805 if (m->klass->image->assembly->ref_only) {
2806 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2810 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2812 mono_array_size_t *lengths;
2813 mono_array_size_t *lower_bounds;
2814 pcount = mono_array_length (params);
2815 lengths = alloca (sizeof (mono_array_size_t) * pcount);
2816 for (i = 0; i < pcount; ++i)
2817 lengths [i] = *(mono_array_size_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2819 if (m->klass->rank == pcount) {
2820 /* Only lengths provided. */
2821 lower_bounds = NULL;
2823 g_assert (pcount == (m->klass->rank * 2));
2824 /* lower bounds are first. */
2825 lower_bounds = lengths;
2826 lengths += m->klass->rank;
2829 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2831 return mono_runtime_invoke_array (m, obj, params, NULL);
2835 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2837 MonoDomain *domain = mono_object_domain (method);
2838 MonoMethod *m = method->method;
2839 MonoMethodSignature *sig = mono_method_signature (m);
2840 MonoArray *out_args;
2842 int i, j, outarg_count = 0;
2844 MONO_ARCH_SAVE_REGS;
2846 if (m->klass == mono_defaults.object_class) {
2848 if (!strcmp (m->name, "FieldGetter")) {
2849 MonoClass *k = this->vtable->klass;
2853 /* If this is a proxy, then it must be a CBO */
2854 if (k == mono_defaults.transparent_proxy_class) {
2855 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2856 this = tp->rp->unwrapped_server;
2858 k = this->vtable->klass;
2861 name = mono_array_get (params, MonoString *, 1);
2862 str = mono_string_to_utf8 (name);
2865 MonoClassField* field = mono_class_get_field_from_name (k, str);
2867 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2868 if (field_klass->valuetype)
2869 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2871 result = *((gpointer *)((char *)this + field->offset));
2873 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2874 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2875 mono_array_setref (out_args, 0, result);
2883 g_assert_not_reached ();
2885 } else if (!strcmp (m->name, "FieldSetter")) {
2886 MonoClass *k = this->vtable->klass;
2892 /* If this is a proxy, then it must be a CBO */
2893 if (k == mono_defaults.transparent_proxy_class) {
2894 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2895 this = tp->rp->unwrapped_server;
2897 k = this->vtable->klass;
2900 name = mono_array_get (params, MonoString *, 1);
2901 str = mono_string_to_utf8 (name);
2904 MonoClassField* field = mono_class_get_field_from_name (k, str);
2906 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2907 MonoObject *val = mono_array_get (params, gpointer, 2);
2909 if (field_klass->valuetype) {
2910 size = mono_type_size (field->type, &align);
2912 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2914 memcpy ((char *)this + field->offset,
2915 ((char *)val) + sizeof (MonoObject), size);
2917 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2920 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2921 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2931 g_assert_not_reached ();
2936 for (i = 0; i < mono_array_length (params); i++) {
2937 if (sig->params [i]->byref)
2941 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2943 /* handle constructors only for objects already allocated */
2944 if (!strcmp (method->method->name, ".ctor"))
2947 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2948 g_assert (!method->method->klass->valuetype);
2949 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2951 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2952 if (sig->params [i]->byref) {
2954 arg = mono_array_get (params, gpointer, i);
2955 mono_array_setref (out_args, j, arg);
2960 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2966 read_enum_value (char *mem, int type)
2970 return *(guint8*)mem;
2972 return *(gint8*)mem;
2974 return *(guint16*)mem;
2976 return *(gint16*)mem;
2978 return *(guint32*)mem;
2980 return *(gint32*)mem;
2982 return *(guint64*)mem;
2984 return *(gint64*)mem;
2986 g_assert_not_reached ();
2992 write_enum_value (char *mem, int type, guint64 value)
2996 case MONO_TYPE_I1: {
2997 guint8 *p = (guint8*)mem;
3002 case MONO_TYPE_I2: {
3003 guint16 *p = (void*)mem;
3008 case MONO_TYPE_I4: {
3009 guint32 *p = (void*)mem;
3014 case MONO_TYPE_I8: {
3015 guint64 *p = (void*)mem;
3020 g_assert_not_reached ();
3026 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3029 MonoClass *enumc, *objc;
3033 MONO_ARCH_SAVE_REGS;
3035 MONO_CHECK_ARG_NULL (enumType);
3036 MONO_CHECK_ARG_NULL (value);
3038 domain = mono_object_domain (enumType);
3039 enumc = mono_class_from_mono_type (enumType->type);
3040 objc = value->vtable->klass;
3042 if (!enumc->enumtype)
3043 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3044 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3045 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."));
3047 res = mono_object_new (domain, enumc);
3048 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3049 write_enum_value ((char *)res + sizeof (MonoObject), mono_class_enum_basetype (enumc)->type, val);
3055 ves_icall_System_Enum_get_value (MonoObject *this)
3063 MONO_ARCH_SAVE_REGS;
3068 g_assert (this->vtable->klass->enumtype);
3070 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3071 res = mono_object_new (mono_object_domain (this), enumc);
3072 dst = (char *)res + sizeof (MonoObject);
3073 src = (char *)this + sizeof (MonoObject);
3074 size = mono_class_value_size (enumc, NULL);
3076 memcpy (dst, src, size);
3081 static MonoReflectionType *
3082 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3084 MONO_ARCH_SAVE_REGS;
3086 return mono_type_get_object (mono_object_domain (type), mono_class_enum_basetype (mono_class_from_mono_type (type->type)));
3090 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3092 gpointer tdata = (char *)this + sizeof (MonoObject);
3093 gpointer odata = (char *)other + sizeof (MonoObject);
3094 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3095 g_assert (basetype);
3097 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3098 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3099 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3102 return me > other ? 1 : -1; \
3105 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3106 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3107 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3110 return me - other; \
3113 switch (basetype->type) {
3115 COMPARE_ENUM_VALUES (guint8);
3117 COMPARE_ENUM_VALUES (gint8);
3118 case MONO_TYPE_CHAR:
3120 COMPARE_ENUM_VALUES_RANGE (guint16);
3122 COMPARE_ENUM_VALUES (gint16);
3124 COMPARE_ENUM_VALUES (guint32);
3126 COMPARE_ENUM_VALUES (gint32);
3128 COMPARE_ENUM_VALUES (guint64);
3130 COMPARE_ENUM_VALUES (gint64);
3132 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3134 #undef COMPARE_ENUM_VALUES_RANGE
3135 #undef COMPARE_ENUM_VALUES
3140 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3142 gpointer data = (char *)this + sizeof (MonoObject);
3143 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3144 g_assert (basetype);
3146 switch (basetype->type) {
3148 return *((gint8*)data);
3150 return *((guint8*)data);
3151 case MONO_TYPE_CHAR:
3153 return *((guint16*)data);
3156 return *((gint16*)data);
3158 return *((guint32*)data);
3160 return *((gint32*)data);
3162 case MONO_TYPE_I8: {
3163 gint64 value = *((gint64*)data);
3164 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3167 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3173 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3175 MonoDomain *domain = mono_object_domain (type);
3176 MonoClass *enumc = mono_class_from_mono_type (type->type);
3177 guint j = 0, nvalues, crow;
3179 MonoClassField *field;
3181 MONO_ARCH_SAVE_REGS;
3183 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3184 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3185 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3186 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3190 while ((field = mono_class_get_fields (enumc, &iter))) {
3193 MonoTypeEnum def_type;
3195 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3197 if (mono_field_is_deleted (field))
3199 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3201 p = mono_class_get_field_default_value (field, &def_type);
3202 len = mono_metadata_decode_blob_size (p, &p);
3203 switch (mono_class_enum_basetype (enumc)->type) {
3206 mono_array_set (info->values, gchar, j, *p);
3208 case MONO_TYPE_CHAR:
3211 mono_array_set (info->values, gint16, j, read16 (p));
3215 mono_array_set (info->values, gint32, j, read32 (p));
3219 mono_array_set (info->values, gint64, j, read64 (p));
3222 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3229 BFLAGS_IgnoreCase = 1,
3230 BFLAGS_DeclaredOnly = 2,
3231 BFLAGS_Instance = 4,
3233 BFLAGS_Public = 0x10,
3234 BFLAGS_NonPublic = 0x20,
3235 BFLAGS_FlattenHierarchy = 0x40,
3236 BFLAGS_InvokeMethod = 0x100,
3237 BFLAGS_CreateInstance = 0x200,
3238 BFLAGS_GetField = 0x400,
3239 BFLAGS_SetField = 0x800,
3240 BFLAGS_GetProperty = 0x1000,
3241 BFLAGS_SetProperty = 0x2000,
3242 BFLAGS_ExactBinding = 0x10000,
3243 BFLAGS_SuppressChangeType = 0x20000,
3244 BFLAGS_OptionalParamBinding = 0x40000
3247 static MonoReflectionField *
3248 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3251 MonoClass *startklass, *klass;
3253 MonoClassField *field;
3256 int (*compare_func) (const char *s1, const char *s2) = NULL;
3257 domain = ((MonoObject *)type)->vtable->domain;
3258 klass = startklass = mono_class_from_mono_type (type->type);
3260 MONO_ARCH_SAVE_REGS;
3263 mono_raise_exception (mono_get_exception_argument_null ("name"));
3264 if (type->type->byref)
3267 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3270 if (klass->exception_type != MONO_EXCEPTION_NONE)
3271 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3274 while ((field = mono_class_get_fields (klass, &iter))) {
3277 if (field->type == NULL)
3279 if (mono_field_is_deleted (field))
3281 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3282 if (bflags & BFLAGS_Public)
3284 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3285 if (bflags & BFLAGS_NonPublic) {
3292 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3293 if (bflags & BFLAGS_Static)
3294 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3297 if (bflags & BFLAGS_Instance)
3304 utf8_name = mono_string_to_utf8 (name);
3306 if (compare_func (mono_field_get_name (field), utf8_name)) {
3312 return mono_field_get_object (domain, klass, field);
3314 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3321 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3324 MonoClass *startklass, *klass, *refklass;
3329 MonoClassField *field;
3330 MonoPtrArray tmp_array;
3332 MONO_ARCH_SAVE_REGS;
3334 domain = ((MonoObject *)type)->vtable->domain;
3335 if (type->type->byref)
3336 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3337 klass = startklass = mono_class_from_mono_type (type->type);
3338 refklass = mono_class_from_mono_type (reftype->type);
3340 mono_ptr_array_init (tmp_array, 2);
3343 if (klass->exception_type != MONO_EXCEPTION_NONE)
3344 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3347 while ((field = mono_class_get_fields (klass, &iter))) {
3349 if (mono_field_is_deleted (field))
3351 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3352 if (bflags & BFLAGS_Public)
3354 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3355 if (bflags & BFLAGS_NonPublic) {
3362 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3363 if (bflags & BFLAGS_Static)
3364 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3367 if (bflags & BFLAGS_Instance)
3373 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3374 mono_ptr_array_append (tmp_array, member);
3376 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3379 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3381 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3382 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3384 mono_ptr_array_destroy (tmp_array);
3390 method_nonpublic (MonoMethod* method, gboolean start_klass)
3392 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3393 case METHOD_ATTRIBUTE_ASSEM:
3394 return (start_klass || mono_defaults.generic_ilist_class);
3395 case METHOD_ATTRIBUTE_PRIVATE:
3397 case METHOD_ATTRIBUTE_PUBLIC:
3405 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3407 static MonoClass *MethodInfo_array;
3409 MonoClass *startklass, *klass, *refklass;
3414 int i, len, match, nslots;
3415 /*FIXME, use MonoBitSet*/
3416 guint32 method_slots_default [8];
3417 guint32 *method_slots = NULL;
3418 gchar *mname = NULL;
3419 int (*compare_func) (const char *s1, const char *s2) = NULL;
3420 MonoVTable *array_vtable;
3422 MonoPtrArray tmp_array;
3424 MONO_ARCH_SAVE_REGS;
3426 mono_ptr_array_init (tmp_array, 4);
3428 if (!MethodInfo_array) {
3429 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3430 mono_memory_barrier ();
3431 MethodInfo_array = klass;
3434 domain = ((MonoObject *)type)->vtable->domain;
3435 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3436 if (type->type->byref)
3437 return mono_array_new_specific (array_vtable, 0);
3438 klass = startklass = mono_class_from_mono_type (type->type);
3439 refklass = mono_class_from_mono_type (reftype->type);
3442 mname = mono_string_to_utf8 (name);
3443 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3446 /* An optimization for calls made from Delegate:CreateDelegate () */
3447 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3448 method = mono_get_delegate_invoke (klass);
3449 if (mono_loader_get_last_error ())
3452 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3454 res = mono_array_new_specific (array_vtable, 1);
3455 mono_array_setref (res, 0, member);
3460 mono_class_setup_vtable (klass);
3461 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3464 if (is_generic_parameter (type->type))
3465 nslots = mono_class_get_vtable_size (klass->parent);
3467 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3468 if (nslots >= sizeof (method_slots_default) * 8) {
3469 method_slots = g_new0 (guint32, nslots / 32 + 1);
3471 method_slots = method_slots_default;
3472 memset (method_slots, 0, sizeof (method_slots_default));
3475 mono_class_setup_vtable (klass);
3476 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3480 while ((method = mono_class_get_methods (klass, &iter))) {
3482 if (method->slot != -1) {
3483 g_assert (method->slot < nslots);
3484 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3486 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3489 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3491 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3492 if (bflags & BFLAGS_Public)
3494 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3500 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3501 if (bflags & BFLAGS_Static)
3502 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3505 if (bflags & BFLAGS_Instance)
3513 if (compare_func (mname, method->name))
3519 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3521 mono_ptr_array_append (tmp_array, member);
3523 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3527 if (method_slots != method_slots_default)
3528 g_free (method_slots);
3530 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3532 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3533 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3535 mono_ptr_array_destroy (tmp_array);
3540 if (method_slots != method_slots_default)
3541 g_free (method_slots);
3542 mono_ptr_array_destroy (tmp_array);
3543 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3544 ex = mono_class_get_exception_for_failure (klass);
3546 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3547 mono_loader_clear_error ();
3549 mono_raise_exception (ex);
3554 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3557 static MonoClass *System_Reflection_ConstructorInfo;
3558 MonoClass *startklass, *klass, *refklass;
3563 gpointer iter = NULL;
3564 MonoPtrArray tmp_array;
3566 MONO_ARCH_SAVE_REGS;
3568 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3570 domain = ((MonoObject *)type)->vtable->domain;
3571 if (type->type->byref)
3572 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3573 klass = startklass = mono_class_from_mono_type (type->type);
3574 refklass = mono_class_from_mono_type (reftype->type);
3576 if (klass->exception_type != MONO_EXCEPTION_NONE)
3577 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3579 if (!System_Reflection_ConstructorInfo)
3580 System_Reflection_ConstructorInfo = mono_class_from_name (
3581 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3584 while ((method = mono_class_get_methods (klass, &iter))) {
3586 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3588 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3589 if (bflags & BFLAGS_Public)
3592 if (bflags & BFLAGS_NonPublic)
3598 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3599 if (bflags & BFLAGS_Static)
3600 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3603 if (bflags & BFLAGS_Instance)
3609 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3611 mono_ptr_array_append (tmp_array, member);
3614 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3616 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3617 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3619 mono_ptr_array_destroy (tmp_array);
3625 property_hash (gconstpointer data)
3627 MonoProperty *prop = (MonoProperty*)data;
3629 return g_str_hash (prop->name);
3633 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3635 // Properties are hide-by-name-and-signature
3636 if (!g_str_equal (prop1->name, prop2->name))
3639 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3641 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3647 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3652 return method_nonpublic (accessor, start_klass);
3656 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3659 static MonoClass *System_Reflection_PropertyInfo;
3660 MonoClass *startklass, *klass;
3666 gchar *propname = NULL;
3667 int (*compare_func) (const char *s1, const char *s2) = NULL;
3669 GHashTable *properties;
3670 MonoPtrArray tmp_array;
3672 MONO_ARCH_SAVE_REGS;
3674 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3676 if (!System_Reflection_PropertyInfo)
3677 System_Reflection_PropertyInfo = mono_class_from_name (
3678 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3680 domain = ((MonoObject *)type)->vtable->domain;
3681 if (type->type->byref)
3682 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3683 klass = startklass = mono_class_from_mono_type (type->type);
3685 propname = mono_string_to_utf8 (name);
3686 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3689 mono_class_setup_vtable (klass);
3691 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3693 mono_class_setup_vtable (klass);
3694 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3695 g_hash_table_destroy (properties);
3698 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3702 while ((prop = mono_class_get_properties (klass, &iter))) {
3708 flags = method->flags;
3711 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3712 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3713 if (bflags & BFLAGS_Public)
3715 } else if (bflags & BFLAGS_NonPublic) {
3716 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3717 property_accessor_nonpublic(prop->set, startklass == klass)) {
3724 if (flags & METHOD_ATTRIBUTE_STATIC) {
3725 if (bflags & BFLAGS_Static)
3726 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3729 if (bflags & BFLAGS_Instance)
3738 if (compare_func (propname, prop->name))
3742 if (g_hash_table_lookup (properties, prop))
3745 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3747 g_hash_table_insert (properties, prop, prop);
3749 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3752 g_hash_table_destroy (properties);
3755 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3756 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3757 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3759 mono_ptr_array_destroy (tmp_array);
3764 static MonoReflectionEvent *
3765 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3768 MonoClass *klass, *startklass;
3774 MONO_ARCH_SAVE_REGS;
3776 event_name = mono_string_to_utf8 (name);
3777 if (type->type->byref)
3779 klass = startklass = mono_class_from_mono_type (type->type);
3780 domain = mono_object_domain (type);
3783 if (klass->exception_type != MONO_EXCEPTION_NONE)
3784 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3787 while ((event = mono_class_get_events (klass, &iter))) {
3788 if (strcmp (event->name, event_name))
3791 method = event->add;
3793 method = event->remove;
3795 method = event->raise;
3797 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3798 if (!(bflags & BFLAGS_Public))
3801 if (!(bflags & BFLAGS_NonPublic))
3803 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3807 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3808 if (!(bflags & BFLAGS_Static))
3810 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3813 if (!(bflags & BFLAGS_Instance))
3817 if (!(bflags & BFLAGS_NonPublic))
3820 g_free (event_name);
3821 return mono_event_get_object (domain, startklass, event);
3824 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3827 g_free (event_name);
3832 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3835 static MonoClass *System_Reflection_EventInfo;
3836 MonoClass *startklass, *klass;
3843 MonoPtrArray tmp_array;
3845 MONO_ARCH_SAVE_REGS;
3847 mono_ptr_array_init (tmp_array, 4);
3849 if (!System_Reflection_EventInfo)
3850 System_Reflection_EventInfo = mono_class_from_name (
3851 mono_defaults.corlib, "System.Reflection", "EventInfo");
3853 domain = mono_object_domain (type);
3854 if (type->type->byref)
3855 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3856 klass = startklass = mono_class_from_mono_type (type->type);
3859 if (klass->exception_type != MONO_EXCEPTION_NONE)
3860 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3863 while ((event = mono_class_get_events (klass, &iter))) {
3865 method = event->add;
3867 method = event->remove;
3869 method = event->raise;
3871 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3872 if (bflags & BFLAGS_Public)
3874 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3875 if (bflags & BFLAGS_NonPublic)
3880 if (bflags & BFLAGS_NonPublic)
3886 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3887 if (bflags & BFLAGS_Static)
3888 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3891 if (bflags & BFLAGS_Instance)
3896 if (bflags & BFLAGS_Instance)
3900 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3902 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3905 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3907 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3908 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3910 mono_ptr_array_destroy (tmp_array);
3915 static MonoReflectionType *
3916 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3924 MONO_ARCH_SAVE_REGS;
3927 mono_raise_exception (mono_get_exception_argument_null ("name"));
3929 domain = ((MonoObject *)type)->vtable->domain;
3930 if (type->type->byref)
3932 klass = mono_class_from_mono_type (type->type);
3933 str = mono_string_to_utf8 (name);
3936 if (klass->exception_type != MONO_EXCEPTION_NONE)
3937 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3940 * If a nested type is generic, return its generic type definition.
3941 * Note that this means that the return value is essentially a
3942 * nested type of the generic type definition of @klass.
3944 * A note in MSDN claims that a generic type definition can have
3945 * nested types that aren't generic. In any case, the container of that
3946 * nested type would be the generic type definition.
3948 if (klass->generic_class)
3949 klass = klass->generic_class->container_class;
3952 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3954 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3955 if (bflags & BFLAGS_Public)
3958 if (bflags & BFLAGS_NonPublic)
3963 if (strcmp (nested->name, str) == 0){
3965 return mono_type_get_object (domain, &nested->byval_arg);
3968 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3975 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
3984 MonoPtrArray tmp_array;
3986 MONO_ARCH_SAVE_REGS;
3988 domain = ((MonoObject *)type)->vtable->domain;
3989 if (type->type->byref)
3990 return mono_array_new (domain, mono_defaults.monotype_class, 0);
3991 klass = mono_class_from_mono_type (type->type);
3992 if (klass->exception_type != MONO_EXCEPTION_NONE)
3993 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3996 * If a nested type is generic, return its generic type definition.
3997 * Note that this means that the return value is essentially the set
3998 * of nested types of the generic type definition of @klass.
4000 * A note in MSDN claims that a generic type definition can have
4001 * nested types that aren't generic. In any case, the container of that
4002 * nested type would be the generic type definition.
4004 if (klass->generic_class)
4005 klass = klass->generic_class->container_class;
4007 mono_ptr_array_init (tmp_array, 1);
4009 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4011 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4012 if (bflags & BFLAGS_Public)
4015 if (bflags & BFLAGS_NonPublic)
4020 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4021 mono_ptr_array_append (tmp_array, member);
4024 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4026 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4027 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4029 mono_ptr_array_destroy (tmp_array);
4034 static MonoReflectionType*
4035 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4038 MonoType *type = NULL;
4039 MonoTypeNameParse info;
4040 gboolean type_resolve;
4042 MONO_ARCH_SAVE_REGS;
4044 /* On MS.NET, this does not fire a TypeResolve event */
4045 type_resolve = TRUE;
4046 str = mono_string_to_utf8 (name);
4047 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4048 if (!mono_reflection_parse_type (str, &info)) {
4050 mono_reflection_free_type_info (&info);
4051 if (throwOnError) /* uhm: this is a parse error, though... */
4052 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4053 /*g_print ("failed parse\n");*/
4057 if (info.assembly.name) {
4059 mono_reflection_free_type_info (&info);
4061 /* 1.0 and 2.0 throw different exceptions */
4062 if (mono_defaults.generic_ilist_class)
4063 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4065 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4070 if (module != NULL) {
4072 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4077 if (assembly->assembly->dynamic) {
4078 /* Enumerate all modules */
4079 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4083 if (abuilder->modules) {
4084 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4085 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4086 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4092 if (!type && abuilder->loaded_modules) {
4093 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4094 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4095 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4102 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4104 mono_reflection_free_type_info (&info);
4106 MonoException *e = NULL;
4109 e = mono_get_exception_type_load (name, NULL);
4111 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4112 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4114 mono_loader_clear_error ();
4117 mono_raise_exception (e);
4122 if (type->type == MONO_TYPE_CLASS) {
4123 MonoClass *klass = mono_type_get_class (type);
4125 if (mono_is_security_manager_active () && !klass->exception_type)
4126 /* Some security problems are detected during generic vtable construction */
4127 mono_class_setup_vtable (klass);
4128 /* need to report exceptions ? */
4129 if (throwOnError && klass->exception_type) {
4130 /* report SecurityException (or others) that occured when loading the assembly */
4131 MonoException *exc = mono_class_get_exception_for_failure (klass);
4132 mono_loader_clear_error ();
4133 mono_raise_exception (exc);
4134 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4139 /* g_print ("got it\n"); */
4140 return mono_type_get_object (mono_object_domain (assembly), type);
4144 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4147 gchar *shadow_ini_file;
4150 /* Check for shadow-copied assembly */
4151 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4152 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4154 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4155 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4161 g_free (shadow_ini_file);
4162 if (content != NULL) {
4165 *filename = content;
4173 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4175 MonoDomain *domain = mono_object_domain (assembly);
4176 MonoAssembly *mass = assembly->assembly;
4177 MonoString *res = NULL;
4182 MONO_ARCH_SAVE_REGS;
4184 if (g_path_is_absolute (mass->image->name)) {
4185 absolute = g_strdup (mass->image->name);
4186 dirname = g_path_get_dirname (absolute);
4188 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4189 dirname = g_strdup (mass->basedir);
4192 replace_shadow_path (domain, dirname, &absolute);
4197 for (i = strlen (absolute) - 1; i >= 0; i--)
4198 if (absolute [i] == '\\')
4203 uri = g_filename_to_uri (absolute, NULL, NULL);
4205 const char *prepend = "file://";
4207 if (*absolute == '/' && *(absolute + 1) == '/') {
4210 prepend = "file:///";
4213 uri = g_strconcat (prepend, absolute, NULL);
4217 res = mono_string_new (domain, uri);
4225 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4227 MonoAssembly *mass = assembly->assembly;
4229 MONO_ARCH_SAVE_REGS;
4231 return mass->in_gac;
4234 static MonoReflectionAssembly*
4235 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4239 MonoImageOpenStatus status;
4241 MONO_ARCH_SAVE_REGS;
4243 name = mono_string_to_utf8 (mname);
4244 res = mono_assembly_load_with_partial_name (name, &status);
4250 return mono_assembly_get_object (mono_domain_get (), res);
4254 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4256 MonoDomain *domain = mono_object_domain (assembly);
4259 MONO_ARCH_SAVE_REGS;
4261 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4267 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4269 MONO_ARCH_SAVE_REGS;
4271 return assembly->assembly->ref_only;
4275 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4277 MonoDomain *domain = mono_object_domain (assembly);
4279 MONO_ARCH_SAVE_REGS;
4281 return mono_string_new (domain, assembly->assembly->image->version);
4284 static MonoReflectionMethod*
4285 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4287 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4289 MONO_ARCH_SAVE_REGS;
4293 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4296 static MonoReflectionModule*
4297 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4299 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4303 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4305 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4306 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4310 MONO_ARCH_SAVE_REGS;
4312 for (i = 0; i < table->rows; ++i) {
4313 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4314 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4320 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4322 static MonoClass *System_Version = NULL;
4323 static MonoMethod *create_version = NULL;
4327 if (!System_Version) {
4328 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4329 g_assert (System_Version);
4332 if (!create_version) {
4333 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4334 create_version = mono_method_desc_search_in_class (desc, System_Version);
4335 g_assert (create_version);
4336 mono_method_desc_free (desc);
4342 args [3] = &revision;
4343 result = mono_object_new (domain, System_Version);
4344 mono_runtime_invoke (create_version, result, args, NULL);
4350 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4352 static MonoClass *System_Reflection_AssemblyName;
4354 MonoDomain *domain = mono_object_domain (assembly);
4356 static MonoMethod *create_culture = NULL;
4357 MonoImage *image = assembly->assembly->image;
4360 MONO_ARCH_SAVE_REGS;
4362 if (!System_Reflection_AssemblyName)
4363 System_Reflection_AssemblyName = mono_class_from_name (
4364 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4366 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4369 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4371 if (count > 0 && !create_culture) {
4372 MonoMethodDesc *desc = mono_method_desc_new (
4373 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4374 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4375 g_assert (create_culture);
4376 mono_method_desc_free (desc);
4379 for (i = 0; i < count; i++) {
4380 MonoReflectionAssemblyName *aname;
4381 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4383 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4385 aname = (MonoReflectionAssemblyName *) mono_object_new (
4386 domain, System_Reflection_AssemblyName);
4388 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4390 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4391 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4392 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4393 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4394 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4395 aname->versioncompat = 1; /* SameMachine (default) */
4396 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4397 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4399 if (create_culture) {
4401 MonoBoolean assembly_ref = 1;
4402 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4403 args [1] = &assembly_ref;
4404 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4407 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4408 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4409 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4411 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4412 /* public key token isn't copied - the class library will
4413 automatically generate it from the public key if required */
4414 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4415 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4417 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4418 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4421 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4424 /* note: this function doesn't return the codebase on purpose (i.e. it can
4425 be used under partial trust as path information isn't present). */
4427 mono_array_setref (result, i, aname);
4438 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4440 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4442 mono_array_setref (info->res, info->idx, name);
4447 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4449 MonoImage *img = assembly->assembly->image;
4454 MONO_ARCH_SAVE_REGS;
4456 mono_image_lock (img);
4457 mono_image_init_name_cache (img);
4460 len = g_hash_table_size (img->name_cache);
4461 mono_image_unlock (img);
4463 /*we can't create objects holding the image lock */
4464 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4466 mono_image_lock (img);
4467 /*len might have changed, create a new array*/
4468 if (len != g_hash_table_size (img->name_cache))
4473 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4474 mono_image_unlock (img);
4479 /* move this in some file in mono/util/ */
4481 g_concat_dir_and_file (const char *dir, const char *file)
4483 g_return_val_if_fail (dir != NULL, NULL);
4484 g_return_val_if_fail (file != NULL, NULL);
4487 * If the directory name doesn't have a / on the end, we need
4488 * to add one so we get a proper path to the file
4490 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4491 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4493 return g_strconcat (dir, file, NULL);
4497 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4499 char *n = mono_string_to_utf8 (name);
4500 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4502 guint32 cols [MONO_MANIFEST_SIZE];
4503 guint32 impl, file_idx;
4507 MONO_ARCH_SAVE_REGS;
4509 for (i = 0; i < table->rows; ++i) {
4510 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4511 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4512 if (strcmp (val, n) == 0)
4516 if (i == table->rows)
4519 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4522 * this code should only be called after obtaining the
4523 * ResourceInfo and handling the other cases.
4525 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4526 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4528 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4533 module = assembly->assembly->image;
4535 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4537 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4541 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4543 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4545 guint32 cols [MONO_MANIFEST_SIZE];
4546 guint32 file_cols [MONO_FILE_SIZE];
4550 MONO_ARCH_SAVE_REGS;
4552 n = mono_string_to_utf8 (name);
4553 for (i = 0; i < table->rows; ++i) {
4554 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4555 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4556 if (strcmp (val, n) == 0)
4560 if (i == table->rows)
4563 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4564 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4567 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4568 case MONO_IMPLEMENTATION_FILE:
4569 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4570 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4571 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4572 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4573 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4574 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4577 info->location = RESOURCE_LOCATION_EMBEDDED;
4580 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4581 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4582 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4583 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4584 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4585 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4587 mono_raise_exception (ex);
4589 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4591 /* Obtain info recursively */
4592 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4593 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4596 case MONO_IMPLEMENTATION_EXP_TYPE:
4597 g_assert_not_reached ();
4606 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4608 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4609 MonoArray *result = NULL;
4614 MONO_ARCH_SAVE_REGS;
4616 /* check hash if needed */
4618 n = mono_string_to_utf8 (name);
4619 for (i = 0; i < table->rows; ++i) {
4620 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4621 if (strcmp (val, n) == 0) {
4624 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4625 fn = mono_string_new (mono_object_domain (assembly), n);
4627 return (MonoObject*)fn;
4635 for (i = 0; i < table->rows; ++i) {
4636 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4640 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4643 for (i = 0; i < table->rows; ++i) {
4644 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4645 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4646 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4647 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4652 return (MonoObject*)result;
4656 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4658 MonoDomain *domain = mono_domain_get();
4661 int i, j, file_count = 0;
4662 MonoImage **modules;
4663 guint32 module_count, real_module_count;
4664 MonoTableInfo *table;
4665 guint32 cols [MONO_FILE_SIZE];
4666 MonoImage *image = assembly->assembly->image;
4668 g_assert (image != NULL);
4669 g_assert (!assembly->assembly->dynamic);
4671 table = &image->tables [MONO_TABLE_FILE];
4672 file_count = table->rows;
4674 modules = image->modules;
4675 module_count = image->module_count;
4677 real_module_count = 0;
4678 for (i = 0; i < module_count; ++i)
4680 real_module_count ++;
4682 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4683 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4685 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4687 for (i = 0; i < module_count; ++i)
4689 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4693 for (i = 0; i < file_count; ++i, ++j) {
4694 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4695 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4696 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4698 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4700 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4701 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4703 mono_array_setref (res, j, mono_module_get_object (domain, m));
4710 static MonoReflectionMethod*
4711 ves_icall_GetCurrentMethod (void)
4713 MonoMethod *m = mono_method_get_last_managed ();
4715 MONO_ARCH_SAVE_REGS;
4717 return mono_method_get_object (mono_domain_get (), m, NULL);
4722 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4725 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4726 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4727 //method is inflated, we should inflate it on the other class
4728 MonoGenericContext ctx;
4729 ctx.method_inst = inflated->context.method_inst;
4730 ctx.class_inst = inflated->context.class_inst;
4731 if (klass->generic_class)
4732 ctx.class_inst = klass->generic_class->context.class_inst;
4733 else if (klass->generic_container)
4734 ctx.class_inst = klass->generic_container->context.class_inst;
4735 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4738 mono_class_setup_methods (method->klass);
4739 for (i = 0; i < method->klass->method.count; ++i) {
4740 if (method->klass->methods [i] == method) {
4745 mono_class_setup_methods (klass);
4746 g_assert (offset >= 0 && offset < klass->method.count);
4747 return klass->methods [offset];
4750 static MonoReflectionMethod*
4751 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4755 klass = mono_class_from_mono_type (type);
4756 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4758 if (method->klass != klass)
4759 method = mono_method_get_equivalent_method (method, klass);
4761 klass = method->klass;
4762 return mono_method_get_object (mono_domain_get (), method, klass);
4765 static MonoReflectionMethod*
4766 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4768 return mono_method_get_object (mono_domain_get (), method, NULL);
4771 static MonoReflectionMethodBody*
4772 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4774 return mono_method_body_get_object (mono_domain_get (), method);
4777 static MonoReflectionAssembly*
4778 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4780 MonoMethod *dest = NULL;
4782 MONO_ARCH_SAVE_REGS;
4784 mono_stack_walk_no_il (get_executing, &dest);
4785 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4789 static MonoReflectionAssembly*
4790 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4792 MonoDomain* domain = mono_domain_get ();
4794 MONO_ARCH_SAVE_REGS;
4796 if (!domain->entry_assembly)
4799 return mono_assembly_get_object (domain, domain->entry_assembly);
4802 static MonoReflectionAssembly*
4803 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4808 MONO_ARCH_SAVE_REGS;
4811 mono_stack_walk_no_il (get_executing, &dest);
4813 mono_stack_walk_no_il (get_caller, &dest);
4816 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4820 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4821 gboolean assembly_qualified)
4823 MonoDomain *domain = mono_object_domain (object);
4824 MonoTypeNameFormat format;
4828 MONO_ARCH_SAVE_REGS;
4830 format = assembly_qualified ?
4831 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4832 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4834 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4836 name = mono_type_get_name_full (object->type, format);
4840 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4845 res = mono_string_new (domain, name);
4852 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4854 static MonoMethod *create_culture = NULL;
4857 const char *pkey_ptr;
4859 MonoBoolean assembly_ref = 0;
4861 MONO_ARCH_SAVE_REGS;
4863 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4864 aname->major = name->major;
4865 aname->minor = name->minor;
4866 aname->build = name->build;
4867 aname->flags = name->flags;
4868 aname->revision = name->revision;
4869 aname->hashalg = name->hash_alg;
4870 aname->versioncompat = 1; /* SameMachine (default) */
4872 if (by_default_version)
4873 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4876 if (absolute != NULL && *absolute != '\0') {
4877 const gchar *prepend = "file://";
4880 codebase = g_strdup (absolute);
4885 for (i = strlen (codebase) - 1; i >= 0; i--)
4886 if (codebase [i] == '\\')
4889 if (*codebase == '/' && *(codebase + 1) == '/') {
4892 prepend = "file:///";
4896 result = g_strconcat (prepend, codebase, NULL);
4902 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4906 if (!create_culture) {
4907 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4908 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4909 g_assert (create_culture);
4910 mono_method_desc_free (desc);
4913 if (name->culture) {
4914 args [0] = mono_string_new (domain, name->culture);
4915 args [1] = &assembly_ref;
4916 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4919 if (name->public_key) {
4920 pkey_ptr = (char*)name->public_key;
4921 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4923 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4924 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4925 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4926 } else if (default_publickey) {
4927 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4928 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4931 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4932 if (name->public_key_token [0]) {
4936 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4937 p = mono_array_addr (aname->keyToken, char, 0);
4939 for (i = 0, j = 0; i < 8; i++) {
4940 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4941 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4944 } else if (default_token) {
4945 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4950 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4952 MonoDomain *domain = mono_object_domain (assembly);
4953 MonoAssembly *mass = assembly->assembly;
4957 name = g_strdup_printf (
4958 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4960 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4961 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4962 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4963 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4965 res = mono_string_new (domain, name);
4972 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
4975 MonoAssembly *mass = assembly->assembly;
4977 MONO_ARCH_SAVE_REGS;
4979 if (g_path_is_absolute (mass->image->name)) {
4980 fill_reflection_assembly_name (mono_object_domain (assembly),
4981 aname, &mass->aname, mass->image->name, TRUE,
4982 TRUE, mono_framework_version () >= 2);
4985 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4987 fill_reflection_assembly_name (mono_object_domain (assembly),
4988 aname, &mass->aname, absolute, TRUE, TRUE,
4989 mono_framework_version () >= 2);
4995 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
4998 MonoImageOpenStatus status = MONO_IMAGE_OK;
5001 MonoAssemblyName name;
5004 MONO_ARCH_SAVE_REGS;
5006 filename = mono_string_to_utf8 (fname);
5008 dirname = g_path_get_dirname (filename);
5009 replace_shadow_path (mono_domain_get (), dirname, &filename);
5012 image = mono_image_open (filename, &status);
5018 if (status == MONO_IMAGE_IMAGE_INVALID)
5019 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5021 exc = mono_get_exception_file_not_found2 (NULL, fname);
5022 mono_raise_exception (exc);
5025 res = mono_assembly_fill_assembly_name (image, &name);
5027 mono_image_close (image);
5029 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5032 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5033 TRUE, mono_framework_version () == 1,
5034 mono_framework_version () >= 2);
5037 mono_image_close (image);
5041 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5042 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5044 MonoBoolean result = FALSE;
5045 MonoDeclSecurityEntry entry;
5047 /* SecurityAction.RequestMinimum */
5048 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5049 *minimum = entry.blob;
5050 *minLength = entry.size;
5053 /* SecurityAction.RequestOptional */
5054 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5055 *optional = entry.blob;
5056 *optLength = entry.size;
5059 /* SecurityAction.RequestRefuse */
5060 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5061 *refused = entry.blob;
5062 *refLength = entry.size;
5070 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5074 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5076 guint32 attrs, visibility;
5078 /* we start the count from 1 because we skip the special type <Module> */
5081 for (i = 1; i < tdef->rows; ++i) {
5082 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5083 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5084 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5088 count = tdef->rows - 1;
5090 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5091 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5093 for (i = 1; i < tdef->rows; ++i) {
5094 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5095 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5096 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5097 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5099 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5101 MonoLoaderError *error;
5104 error = mono_loader_get_last_error ();
5105 g_assert (error != NULL);
5107 ex = mono_loader_error_prepare_exception (error);
5108 mono_array_setref (*exceptions, count, ex);
5110 if (mono_loader_get_last_error ())
5111 mono_loader_clear_error ();
5120 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5122 MonoArray *res = NULL;
5123 MonoArray *exceptions = NULL;
5124 MonoImage *image = NULL;
5125 MonoTableInfo *table = NULL;
5128 int i, len, ex_count;
5130 MONO_ARCH_SAVE_REGS;
5132 domain = mono_object_domain (assembly);
5134 g_assert (!assembly->assembly->dynamic);
5135 image = assembly->assembly->image;
5136 table = &image->tables [MONO_TABLE_FILE];
5137 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5139 /* Append data from all modules in the assembly */
5140 for (i = 0; i < table->rows; ++i) {
5141 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5142 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5145 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5146 /* Append the new types to the end of the array */
5147 if (mono_array_length (res2) > 0) {
5149 MonoArray *res3, *ex3;
5151 len1 = mono_array_length (res);
5152 len2 = mono_array_length (res2);
5154 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5155 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5156 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5159 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5160 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5161 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5168 /* the ReflectionTypeLoadException must have all the types (Types property),
5169 * NULL replacing types which throws an exception. The LoaderException must
5170 * contain all exceptions for NULL items.
5173 len = mono_array_length (res);
5176 for (i = 0; i < len; i++) {
5177 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5181 klass = mono_type_get_class (t->type);
5182 if ((klass != NULL) && klass->exception_type) {
5183 /* keep the class in the list */
5184 list = g_list_append (list, klass);
5185 /* and replace Type with NULL */
5186 mono_array_setref (res, i, NULL);
5193 if (list || ex_count) {
5195 MonoException *exc = NULL;
5196 MonoArray *exl = NULL;
5197 int j, length = g_list_length (list) + ex_count;
5199 mono_loader_clear_error ();
5201 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5202 /* Types for which mono_class_get () succeeded */
5203 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5204 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5205 mono_array_setref (exl, i, exc);
5207 /* Types for which it don't */
5208 for (j = 0; j < mono_array_length (exceptions); ++j) {
5209 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5211 g_assert (i < length);
5212 mono_array_setref (exl, i, exc);
5219 exc = mono_get_exception_reflection_type_load (res, exl);
5220 mono_loader_clear_error ();
5221 mono_raise_exception (exc);
5228 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5230 MonoAssemblyName aname;
5231 MonoDomain *domain = mono_object_domain (name);
5233 gboolean is_version_defined;
5234 gboolean is_token_defined;
5236 aname.public_key = NULL;
5237 val = mono_string_to_utf8 (assname);
5238 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5239 g_free ((guint8*) aname.public_key);
5244 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5245 FALSE, is_token_defined);
5247 mono_assembly_name_free (&aname);
5248 g_free ((guint8*) aname.public_key);
5254 static MonoReflectionType*
5255 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5257 MonoDomain *domain = mono_object_domain (module);
5260 MONO_ARCH_SAVE_REGS;
5262 g_assert (module->image);
5264 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5265 /* These images do not have a global type */
5268 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5269 return mono_type_get_object (domain, &klass->byval_arg);
5273 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5275 /*if (module->image)
5276 mono_image_close (module->image);*/
5280 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5282 MonoDomain *domain = mono_object_domain (module);
5284 MONO_ARCH_SAVE_REGS;
5286 g_assert (module->image);
5287 return mono_string_new (domain, module->image->guid);
5291 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5293 #ifdef PLATFORM_WIN32
5294 if (module->image && module->image->is_module_handle)
5295 return module->image->raw_data;
5298 return (gpointer) (-1);
5302 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5304 if (image->dynamic) {
5305 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5306 *pe_kind = dyn->pe_kind;
5307 *machine = dyn->machine;
5310 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5311 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5316 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5318 return (image->md_version_major << 16) | (image->md_version_minor);
5322 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5324 MonoArray *exceptions;
5327 MONO_ARCH_SAVE_REGS;
5330 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5332 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5333 for (i = 0; i < mono_array_length (exceptions); ++i) {
5334 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5336 mono_raise_exception (ex);
5343 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5345 guint32 cols [MONO_MEMBERREF_SIZE];
5347 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5348 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5349 mono_metadata_decode_blob_size (sig, &sig);
5350 return (*sig != 0x6);
5354 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5357 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5358 mono_array_addr (type_args, MonoType*, 0));
5360 context->class_inst = NULL;
5362 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5363 mono_array_addr (method_args, MonoType*, 0));
5365 context->method_inst = NULL;
5369 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5372 int table = mono_metadata_token_table (token);
5373 int index = mono_metadata_token_index (token);
5374 MonoGenericContext context;
5376 *error = ResolveTokenError_Other;
5378 /* Validate token */
5379 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5380 (table != MONO_TABLE_TYPESPEC)) {
5381 *error = ResolveTokenError_BadTable;
5385 if (image->dynamic) {
5386 if (type_args || method_args)
5387 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5388 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5391 return &klass->byval_arg;
5394 if ((index <= 0) || (index > image->tables [table].rows)) {
5395 *error = ResolveTokenError_OutOfRange;
5399 init_generic_context_from_args (&context, type_args, method_args);
5400 klass = mono_class_get_full (image, token, &context);
5402 if (mono_loader_get_last_error ())
5403 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5406 return &klass->byval_arg;
5412 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5414 int table = mono_metadata_token_table (token);
5415 int index = mono_metadata_token_index (token);
5416 MonoGenericContext context;
5419 *error = ResolveTokenError_Other;
5421 /* Validate token */
5422 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5423 (table != MONO_TABLE_MEMBERREF)) {
5424 *error = ResolveTokenError_BadTable;
5428 if (image->dynamic) {
5429 if (type_args || method_args)
5430 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5431 /* FIXME: validate memberref token type */
5432 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5435 if ((index <= 0) || (index > image->tables [table].rows)) {
5436 *error = ResolveTokenError_OutOfRange;
5439 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5440 *error = ResolveTokenError_BadTable;
5444 init_generic_context_from_args (&context, type_args, method_args);
5445 method = mono_get_method_full (image, token, NULL, &context);
5447 if (mono_loader_get_last_error ())
5448 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5454 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5456 int index = mono_metadata_token_index (token);
5458 *error = ResolveTokenError_Other;
5460 /* Validate token */
5461 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5462 *error = ResolveTokenError_BadTable;
5467 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5469 if ((index <= 0) || (index >= image->heap_us.size)) {
5470 *error = ResolveTokenError_OutOfRange;
5474 /* FIXME: What to do if the index points into the middle of a string ? */
5476 return mono_ldstr (mono_domain_get (), image, index);
5479 static MonoClassField*
5480 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5483 int table = mono_metadata_token_table (token);
5484 int index = mono_metadata_token_index (token);
5485 MonoGenericContext context;
5486 MonoClassField *field;
5488 *error = ResolveTokenError_Other;
5490 /* Validate token */
5491 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5492 *error = ResolveTokenError_BadTable;
5496 if (image->dynamic) {
5497 if (type_args || method_args)
5498 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5499 /* FIXME: validate memberref token type */
5500 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5503 if ((index <= 0) || (index > image->tables [table].rows)) {
5504 *error = ResolveTokenError_OutOfRange;
5507 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5508 *error = ResolveTokenError_BadTable;
5512 init_generic_context_from_args (&context, type_args, method_args);
5513 field = mono_field_from_token (image, token, &klass, &context);
5515 if (mono_loader_get_last_error ())
5516 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5523 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5525 int table = mono_metadata_token_table (token);
5527 *error = ResolveTokenError_Other;
5530 case MONO_TABLE_TYPEDEF:
5531 case MONO_TABLE_TYPEREF:
5532 case MONO_TABLE_TYPESPEC: {
5533 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5535 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5539 case MONO_TABLE_METHOD:
5540 case MONO_TABLE_METHODSPEC: {
5541 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5543 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5547 case MONO_TABLE_FIELD: {
5548 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5550 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5554 case MONO_TABLE_MEMBERREF:
5555 if (mono_metadata_memberref_is_method (image, token)) {
5556 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5558 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5563 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5565 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5572 *error = ResolveTokenError_BadTable;
5579 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5581 int table = mono_metadata_token_table (token);
5582 int idx = mono_metadata_token_index (token);
5583 MonoTableInfo *tables = image->tables;
5588 *error = ResolveTokenError_OutOfRange;
5590 /* FIXME: Support other tables ? */
5591 if (table != MONO_TABLE_STANDALONESIG)
5597 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5600 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5602 ptr = mono_metadata_blob_heap (image, sig);
5603 len = mono_metadata_decode_blob_size (ptr, &ptr);
5605 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5606 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5610 static MonoReflectionType*
5611 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5614 int isbyref = 0, rank;
5615 char *str = mono_string_to_utf8 (smodifiers);
5618 MONO_ARCH_SAVE_REGS;
5620 klass = mono_class_from_mono_type (tb->type.type);
5622 /* logic taken from mono_reflection_parse_type(): keep in sync */
5626 if (isbyref) { /* only one level allowed by the spec */
5633 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5636 klass = mono_ptr_class_get (&klass->byval_arg);
5637 mono_class_init (klass);
5648 else if (*p != '*') { /* '*' means unknown lower bound */
5659 klass = mono_array_class_get (klass, rank);
5660 mono_class_init (klass);
5667 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5671 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5676 MONO_ARCH_SAVE_REGS;
5679 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5684 static MonoReflectionType *
5685 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5687 MonoClass *klass, *aklass;
5689 MONO_ARCH_SAVE_REGS;
5691 klass = mono_class_from_mono_type (type->type);
5692 if (rank == 0) //single dimentional array
5693 aklass = mono_array_class_get (klass, 1);
5695 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5697 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5700 static MonoReflectionType *
5701 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5705 MONO_ARCH_SAVE_REGS;
5707 klass = mono_class_from_mono_type (type->type);
5709 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5712 static MonoReflectionType *
5713 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5717 MONO_ARCH_SAVE_REGS;
5719 pklass = mono_ptr_class_get (type->type);
5721 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5725 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5726 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5728 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5729 MonoObject *delegate;
5731 MonoMethod *method = info->method;
5733 MONO_ARCH_SAVE_REGS;
5735 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5737 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5738 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5742 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5744 if (method->dynamic) {
5745 /* Creating a trampoline would leak memory */
5746 func = mono_compile_method (method);
5748 func = mono_create_ftnptr (mono_domain_get (),
5749 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5752 mono_delegate_ctor_with_method (delegate, target, func, method);
5758 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5760 /* Reset the invoke impl to the default one */
5761 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5765 * Magic number to convert a time which is relative to
5766 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5768 #define EPOCH_ADJUST ((guint64)62135596800LL)
5771 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5773 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5775 #ifdef PLATFORM_WIN32
5776 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5778 convert_to_absolute_date(SYSTEMTIME *date)
5780 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5781 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5782 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5783 /* from the calendar FAQ */
5784 int a = (14 - date->wMonth) / 12;
5785 int y = date->wYear - a;
5786 int m = date->wMonth + 12 * a - 2;
5787 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5789 /* d is now the day of the week for the first of the month (0 == Sunday) */
5791 int day_of_week = date->wDayOfWeek;
5793 /* set day_in_month to the first day in the month which falls on day_of_week */
5794 int day_in_month = 1 + (day_of_week - d);
5795 if (day_in_month <= 0)
5798 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5799 date->wDay = day_in_month + (date->wDay - 1) * 7;
5800 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5805 #ifndef PLATFORM_WIN32
5807 * Return's the offset from GMT of a local time.
5809 * tm is a local time
5810 * t is the same local time as seconds.
5813 gmt_offset(struct tm *tm, time_t t)
5815 #if defined (HAVE_TM_GMTOFF)
5816 return tm->tm_gmtoff;
5821 g.tm_isdst = tm->tm_isdst;
5823 return (int)difftime(t, t2);
5828 * This is heavily based on zdump.c from glibc 2.2.
5830 * * data[0]: start of daylight saving time (in DateTime ticks).
5831 * * data[1]: end of daylight saving time (in DateTime ticks).
5832 * * data[2]: utcoffset (in TimeSpan ticks).
5833 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5834 * * name[0]: name of this timezone when not daylight saving.
5835 * * name[1]: name of this timezone when daylight saving.
5837 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5838 * the class library allows years between 1 and 9999.
5840 * Returns true on success and zero on failure.
5843 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5845 #ifndef PLATFORM_WIN32
5846 MonoDomain *domain = mono_domain_get ();
5847 struct tm start, tt;
5851 int is_daylight = 0, day;
5854 MONO_ARCH_SAVE_REGS;
5856 MONO_CHECK_ARG_NULL (data);
5857 MONO_CHECK_ARG_NULL (names);
5859 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5860 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5863 * no info is better than crashing: we'll need our own tz data
5864 * to make this work properly, anyway. The range is probably
5865 * reduced to 1970 .. 2037 because that is what mktime is
5866 * guaranteed to support (we get into an infinite loop
5870 memset (&start, 0, sizeof (start));
5873 start.tm_year = year-1900;
5875 t = mktime (&start);
5877 if ((year < 1970) || (year > 2037) || (t == -1)) {
5879 tt = *localtime (&t);
5880 strftime (tzone, sizeof (tzone), "%Z", &tt);
5881 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5882 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5886 gmtoff = gmt_offset (&start, t);
5888 /* For each day of the year, calculate the tm_gmtoff. */
5889 for (day = 0; day < 365; day++) {
5892 tt = *localtime (&t);
5894 /* Daylight saving starts or ends here. */
5895 if (gmt_offset (&tt, t) != gmtoff) {
5899 /* Try to find the exact hour when daylight saving starts/ends. */
5903 tt1 = *localtime (&t1);
5904 } while (gmt_offset (&tt1, t1) != gmtoff);
5906 /* Try to find the exact minute when daylight saving starts/ends. */
5909 tt1 = *localtime (&t1);
5910 } while (gmt_offset (&tt1, t1) == gmtoff);
5912 strftime (tzone, sizeof (tzone), "%Z", &tt);
5914 /* Write data, if we're already in daylight saving, we're done. */
5916 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5917 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5920 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5921 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5925 /* This is only set once when we enter daylight saving. */
5926 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5927 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5929 gmtoff = gmt_offset (&tt, t);
5934 strftime (tzone, sizeof (tzone), "%Z", &tt);
5935 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5936 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5937 mono_array_set ((*data), gint64, 0, 0);
5938 mono_array_set ((*data), gint64, 1, 0);
5939 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5940 mono_array_set ((*data), gint64, 3, 0);
5945 MonoDomain *domain = mono_domain_get ();
5946 TIME_ZONE_INFORMATION tz_info;
5951 tz_id = GetTimeZoneInformation (&tz_info);
5952 if (tz_id == TIME_ZONE_ID_INVALID)
5955 MONO_CHECK_ARG_NULL (data);
5956 MONO_CHECK_ARG_NULL (names);
5958 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
5959 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
5961 for (i = 0; i < 32; ++i)
5962 if (!tz_info.DaylightName [i])
5964 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5965 for (i = 0; i < 32; ++i)
5966 if (!tz_info.StandardName [i])
5968 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
5970 if ((year <= 1601) || (year > 30827)) {
5972 * According to MSDN, the MS time functions can't handle dates outside
5978 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
5979 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
5980 tz_info.StandardDate.wYear = year;
5981 convert_to_absolute_date(&tz_info.StandardDate);
5982 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
5987 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5988 tz_info.DaylightDate.wYear = year;
5989 convert_to_absolute_date(&tz_info.DaylightDate);
5990 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
5995 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
5997 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
5998 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6005 ves_icall_System_Object_obj_address (MonoObject *this)
6007 MONO_ARCH_SAVE_REGS;
6014 static inline gint32
6015 mono_array_get_byte_length (MonoArray *array)
6021 klass = array->obj.vtable->klass;
6023 if (array->bounds == NULL)
6024 length = array->max_length;
6027 for (i = 0; i < klass->rank; ++ i)
6028 length *= array->bounds [i].length;
6031 switch (klass->element_class->byval_arg.type) {
6034 case MONO_TYPE_BOOLEAN:
6038 case MONO_TYPE_CHAR:
6046 return length * sizeof (gpointer);
6057 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6059 MONO_ARCH_SAVE_REGS;
6061 return mono_array_get_byte_length (array);
6065 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6067 MONO_ARCH_SAVE_REGS;
6069 return mono_array_get (array, gint8, idx);
6073 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6075 MONO_ARCH_SAVE_REGS;
6077 mono_array_set (array, gint8, idx, value);
6081 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6083 guint8 *src_buf, *dest_buf;
6085 MONO_ARCH_SAVE_REGS;
6087 /* watch out for integer overflow */
6088 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6091 src_buf = (guint8 *)src->vector + src_offset;
6092 dest_buf = (guint8 *)dest->vector + dest_offset;
6095 memcpy (dest_buf, src_buf, count);
6097 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6103 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6105 MonoDomain *domain = mono_object_domain (this);
6107 MonoRealProxy *rp = ((MonoRealProxy *)this);
6108 MonoTransparentProxy *tp;
6112 MONO_ARCH_SAVE_REGS;
6114 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6115 tp = (MonoTransparentProxy*) res;
6117 MONO_OBJECT_SETREF (tp, rp, rp);
6118 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6119 klass = mono_class_from_mono_type (type);
6121 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6122 tp->remote_class = mono_remote_class (domain, class_name, klass);
6124 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6128 static MonoReflectionType *
6129 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6131 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6134 /* System.Environment */
6137 ves_icall_System_Environment_get_UserName (void)
6139 MONO_ARCH_SAVE_REGS;
6141 /* using glib is more portable */
6142 return mono_string_new (mono_domain_get (), g_get_user_name ());
6147 ves_icall_System_Environment_get_MachineName (void)
6149 #if defined (PLATFORM_WIN32)
6154 len = MAX_COMPUTERNAME_LENGTH + 1;
6155 buf = g_new (gunichar2, len);
6158 if (GetComputerName (buf, (PDWORD) &len))
6159 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6163 #elif !defined(DISABLE_SOCKETS)
6167 if (gethostname (buf, sizeof (buf)) == 0)
6168 result = mono_string_new (mono_domain_get (), buf);
6174 return mono_string_new (mono_domain_get (), "mono");
6179 ves_icall_System_Environment_get_Platform (void)
6181 #if defined (PLATFORM_WIN32)
6184 #elif defined(__MACH__)
6186 if (mono_framework_version () < 2)
6190 // For compatibility with our client code, this will be 4 for a while.
6191 // We will eventually move to 6 to match .NET, but it requires all client
6192 // code to be updated and the documentation everywhere to be updated
6198 if (mono_framework_version () < 2)
6205 ves_icall_System_Environment_get_NewLine (void)
6207 MONO_ARCH_SAVE_REGS;
6209 #if defined (PLATFORM_WIN32)
6210 return mono_string_new (mono_domain_get (), "\r\n");
6212 return mono_string_new (mono_domain_get (), "\n");
6217 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6222 MONO_ARCH_SAVE_REGS;
6227 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6228 value = g_getenv (utf8_name);
6235 return mono_string_new (mono_domain_get (), value);
6239 * There is no standard way to get at environ.
6242 #ifndef __MINGW32_VERSION
6244 /* Apple defines this in crt_externs.h but doesn't provide that header for
6245 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6246 * in fact exist on all implementations (so far)
6248 gchar ***_NSGetEnviron(void);
6249 #define environ (*_NSGetEnviron())
6258 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6260 #ifdef PLATFORM_WIN32
6269 env_strings = GetEnvironmentStrings();
6272 env_string = env_strings;
6273 while (*env_string != '\0') {
6274 /* weird case that MS seems to skip */
6275 if (*env_string != '=')
6277 while (*env_string != '\0')
6283 domain = mono_domain_get ();
6284 names = mono_array_new (domain, mono_defaults.string_class, n);
6288 env_string = env_strings;
6289 while (*env_string != '\0') {
6290 /* weird case that MS seems to skip */
6291 if (*env_string != '=') {
6292 equal_str = wcschr(env_string, '=');
6293 g_assert(equal_str);
6294 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6295 mono_array_setref (names, n, str);
6298 while (*env_string != '\0')
6303 FreeEnvironmentStrings (env_strings);
6315 MONO_ARCH_SAVE_REGS;
6318 for (e = environ; *e != 0; ++ e)
6321 domain = mono_domain_get ();
6322 names = mono_array_new (domain, mono_defaults.string_class, n);
6325 for (e = environ; *e != 0; ++ e) {
6326 parts = g_strsplit (*e, "=", 2);
6328 str = mono_string_new (domain, *parts);
6329 mono_array_setref (names, n, str);
6342 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6344 #if !GLIB_CHECK_VERSION(2,4,0)
6345 #define g_setenv(a,b,c) setenv(a,b,c)
6346 #define g_unsetenv(a) unsetenv(a)
6350 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6352 #ifdef PLATFORM_WIN32
6353 gunichar2 *utf16_name, *utf16_value;
6355 gchar *utf8_name, *utf8_value;
6358 MONO_ARCH_SAVE_REGS;
6360 #ifdef PLATFORM_WIN32
6361 utf16_name = mono_string_to_utf16 (name);
6362 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6363 SetEnvironmentVariable (utf16_name, NULL);
6364 g_free (utf16_name);
6368 utf16_value = mono_string_to_utf16 (value);
6370 SetEnvironmentVariable (utf16_name, utf16_value);
6372 g_free (utf16_name);
6373 g_free (utf16_value);
6375 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6377 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6378 g_unsetenv (utf8_name);
6383 utf8_value = mono_string_to_utf8 (value);
6384 g_setenv (utf8_name, utf8_value, TRUE);
6387 g_free (utf8_value);
6392 ves_icall_System_Environment_Exit (int result)
6394 MONO_ARCH_SAVE_REGS;
6396 mono_threads_set_shutting_down ();
6398 mono_runtime_set_shutting_down ();
6400 /* Suspend all managed threads since the runtime is going away */
6401 mono_thread_suspend_all_other_threads ();
6403 mono_runtime_quit ();
6405 /* we may need to do some cleanup here... */
6410 ves_icall_System_Environment_GetGacPath (void)
6412 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6416 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6418 #if defined (PLATFORM_WIN32)
6419 #ifndef CSIDL_FLAG_CREATE
6420 #define CSIDL_FLAG_CREATE 0x8000
6423 WCHAR path [MAX_PATH];
6424 /* Create directory if no existing */
6425 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6429 return mono_string_new_utf16 (mono_domain_get (), path, len);
6432 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6434 return mono_string_new (mono_domain_get (), "");
6438 ves_icall_System_Environment_GetLogicalDrives (void)
6440 gunichar2 buf [128], *ptr, *dname;
6442 guint initial_size = 127, size = 128;
6445 MonoString *drivestr;
6446 MonoDomain *domain = mono_domain_get ();
6449 MONO_ARCH_SAVE_REGS;
6454 while (size > initial_size) {
6455 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6456 if (size > initial_size) {
6459 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6460 initial_size = size;
6474 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6479 while (*u16) { u16++; len ++; }
6480 drivestr = mono_string_new_utf16 (domain, dname, len);
6481 mono_array_setref (result, ndrives++, drivestr);
6492 ves_icall_System_Environment_InternalGetHome (void)
6494 MONO_ARCH_SAVE_REGS;
6496 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6499 static const char *encodings [] = {
6501 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6502 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6503 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6505 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6506 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6507 "x_unicode_2_0_utf_7",
6509 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6510 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6512 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6515 "unicodefffe", "utf_16be",
6522 * Returns the internal codepage, if the value of "int_code_page" is
6523 * 1 at entry, and we can not compute a suitable code page number,
6524 * returns the code page as a string
6527 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6532 char *codepage = NULL;
6534 int want_name = *int_code_page;
6537 *int_code_page = -1;
6538 MONO_ARCH_SAVE_REGS;
6540 g_get_charset (&cset);
6541 c = codepage = strdup (cset);
6542 for (c = codepage; *c; c++){
6543 if (isascii (*c) && isalpha (*c))
6548 /* g_print ("charset: %s\n", cset); */
6550 /* handle some common aliases */
6553 for (i = 0; p != 0; ){
6554 if ((gssize) p < 7){
6556 p = encodings [++i];
6559 if (strcmp (p, codepage) == 0){
6560 *int_code_page = code;
6563 p = encodings [++i];
6566 if (strstr (codepage, "utf_8") != NULL)
6567 *int_code_page |= 0x10000000;
6570 if (want_name && *int_code_page == -1)
6571 return mono_string_new (mono_domain_get (), cset);
6577 ves_icall_System_Environment_get_HasShutdownStarted (void)
6579 if (mono_runtime_is_shutting_down ())
6582 if (mono_domain_is_unloading (mono_domain_get ()))
6589 ves_icall_System_Environment_BroadcastSettingChange (void)
6591 #ifdef PLATFORM_WIN32
6592 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6597 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6598 MonoReflectionMethod *method,
6599 MonoArray *out_args)
6601 MONO_ARCH_SAVE_REGS;
6603 mono_message_init (mono_object_domain (this), this, method, out_args);
6607 ves_icall_IsTransparentProxy (MonoObject *proxy)
6609 MONO_ARCH_SAVE_REGS;
6614 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6620 static MonoReflectionMethod *
6621 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6622 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6626 MonoMethod **vtable;
6627 MonoMethod *res = NULL;
6629 MONO_CHECK_ARG_NULL (rtype);
6630 MONO_CHECK_ARG_NULL (rmethod);
6632 method = rmethod->method;
6633 klass = mono_class_from_mono_type (rtype->type);
6635 if (MONO_CLASS_IS_INTERFACE (klass))
6638 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6641 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6642 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6648 mono_class_setup_vtable (klass);
6649 vtable = klass->vtable;
6651 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6652 int offs = mono_class_interface_offset (klass, method->klass);
6654 res = vtable [offs + method->slot];
6656 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6659 if (method->slot != -1)
6660 res = vtable [method->slot];
6666 return mono_method_get_object (mono_domain_get (), res, NULL);
6670 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6675 MONO_ARCH_SAVE_REGS;
6677 klass = mono_class_from_mono_type (type->type);
6678 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6680 if (enable) vtable->remote = 1;
6681 else vtable->remote = 0;
6685 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6690 MONO_ARCH_SAVE_REGS;
6692 domain = mono_object_domain (type);
6693 klass = mono_class_from_mono_type (type->type);
6695 if (klass->rank >= 1) {
6696 g_assert (klass->rank == 1);
6697 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6699 /* Bypass remoting object creation check */
6700 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6705 ves_icall_System_IO_get_temp_path (void)
6707 MONO_ARCH_SAVE_REGS;
6709 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6712 #ifndef PLATFORM_NO_DRIVEINFO
6714 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6715 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6719 ULARGE_INTEGER wapi_free_bytes_avail;
6720 ULARGE_INTEGER wapi_total_number_of_bytes;
6721 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6723 MONO_ARCH_SAVE_REGS;
6725 *error = ERROR_SUCCESS;
6726 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6727 &wapi_total_number_of_free_bytes);
6730 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6731 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6732 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6734 *free_bytes_avail = 0;
6735 *total_number_of_bytes = 0;
6736 *total_number_of_free_bytes = 0;
6737 *error = GetLastError ();
6744 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6746 MONO_ARCH_SAVE_REGS;
6748 return GetDriveType (mono_string_chars (root_path_name));
6753 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6755 MONO_ARCH_SAVE_REGS;
6757 return mono_compile_method (method);
6761 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6766 MONO_ARCH_SAVE_REGS;
6768 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6770 #if defined (PLATFORM_WIN32)
6771 /* Avoid mixing '/' and '\\' */
6774 for (i = strlen (path) - 1; i >= 0; i--)
6775 if (path [i] == '/')
6779 mcpath = mono_string_new (mono_domain_get (), path);
6786 get_bundled_machine_config (void)
6788 const gchar *machine_config;
6790 MONO_ARCH_SAVE_REGS;
6792 machine_config = mono_get_machine_config ();
6794 if (!machine_config)
6797 return mono_string_new (mono_domain_get (), machine_config);
6801 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6806 MONO_ARCH_SAVE_REGS;
6808 path = g_path_get_dirname (mono_get_config_dir ());
6810 #if defined (PLATFORM_WIN32)
6811 /* Avoid mixing '/' and '\\' */
6814 for (i = strlen (path) - 1; i >= 0; i--)
6815 if (path [i] == '/')
6819 ipath = mono_string_new (mono_domain_get (), path);
6826 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6828 MonoPEResourceDataEntry *entry;
6831 MONO_ARCH_SAVE_REGS;
6833 if (!assembly || !result || !size)
6838 image = assembly->assembly->image;
6839 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6843 *result = mono_image_rva_map (image, entry->rde_data_offset);
6848 *size = entry->rde_size;
6854 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6856 return mono_debug_using_mono_debugger ();
6860 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6862 #if defined (PLATFORM_WIN32)
6863 OutputDebugString (mono_string_chars (message));
6865 g_warning ("WriteWindowsDebugString called and PLATFORM_WIN32 not defined!\n");
6869 /* Only used for value types */
6871 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6876 MONO_ARCH_SAVE_REGS;
6878 domain = mono_object_domain (type);
6879 klass = mono_class_from_mono_type (type->type);
6881 if (mono_class_is_nullable (klass))
6882 /* No arguments -> null */
6885 return mono_object_new (domain, klass);
6888 static MonoReflectionMethod *
6889 ves_icall_MonoMethod_get_base_definition (MonoReflectionMethod *m)
6891 MonoClass *klass, *parent;
6892 MonoMethod *method = m->method;
6893 MonoMethod *result = NULL;
6895 MONO_ARCH_SAVE_REGS;
6897 if (method->klass == NULL)
6900 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6901 MONO_CLASS_IS_INTERFACE (method->klass) ||
6902 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6905 klass = method->klass;
6906 if (klass->generic_class)
6907 klass = klass->generic_class->container_class;
6909 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6910 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6911 mono_class_setup_vtable (parent);
6912 if (parent->vtable_size <= method->slot)
6917 if (klass == method->klass)
6920 result = klass->vtable [method->slot];
6921 if (result == NULL) {
6922 /* It is an abstract method */
6923 gpointer iter = NULL;
6924 while ((result = mono_class_get_methods (klass, &iter)))
6925 if (result->slot == method->slot)
6932 return mono_method_get_object (mono_domain_get (), result, NULL);
6936 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6938 MonoMethod *method = m->method;
6940 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6945 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6947 MONO_ARCH_SAVE_REGS;
6949 iter->sig = *(MonoMethodSignature**)argsp;
6951 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
6952 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
6955 /* FIXME: it's not documented what start is exactly... */
6959 iter->args = argsp + sizeof (gpointer);
6960 #ifndef MONO_ARCH_REGPARMS
6962 guint32 i, arg_size;
6964 for (i = 0; i < iter->sig->sentinelpos; ++i) {
6965 arg_size = mono_type_stack_size (iter->sig->params [i], &align);
6966 iter->args = (char*)iter->args + arg_size;
6971 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
6973 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
6977 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
6979 guint32 i, arg_size;
6982 MONO_ARCH_SAVE_REGS;
6984 i = iter->sig->sentinelpos + iter->next_arg;
6986 g_assert (i < iter->sig->param_count);
6988 res.type = iter->sig->params [i];
6989 res.klass = mono_class_from_mono_type (res.type);
6990 res.value = iter->args;
6991 arg_size = mono_type_stack_size (res.type, &align);
6992 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
6993 if (arg_size <= sizeof (gpointer)) {
6995 int padding = arg_size - mono_type_size (res.type, &dummy);
6996 res.value = (guint8*)res.value + padding;
6999 iter->args = (char*)iter->args + arg_size;
7002 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7008 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7010 guint32 i, arg_size;
7013 MONO_ARCH_SAVE_REGS;
7015 i = iter->sig->sentinelpos + iter->next_arg;
7017 g_assert (i < iter->sig->param_count);
7019 while (i < iter->sig->param_count) {
7020 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7022 res.type = iter->sig->params [i];
7023 res.klass = mono_class_from_mono_type (res.type);
7024 /* FIXME: endianess issue... */
7025 res.value = iter->args;
7026 arg_size = mono_type_stack_size (res.type, &align);
7027 iter->args = (char*)iter->args + arg_size;
7029 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7032 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7041 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7044 MONO_ARCH_SAVE_REGS;
7046 i = iter->sig->sentinelpos + iter->next_arg;
7048 g_assert (i < iter->sig->param_count);
7050 return iter->sig->params [i];
7054 mono_TypedReference_ToObject (MonoTypedRef tref)
7056 MONO_ARCH_SAVE_REGS;
7058 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7059 MonoObject** objp = tref.value;
7063 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7067 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7069 MONO_ARCH_SAVE_REGS;
7071 if (MONO_TYPE_IS_REFERENCE (type)) {
7072 MonoObject** objp = value;
7076 return mono_value_box (mono_domain_get (), klass, value);
7080 prelink_method (MonoMethod *method)
7082 const char *exc_class, *exc_arg;
7083 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7085 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7087 mono_raise_exception(
7088 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7090 /* create the wrapper, too? */
7094 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7096 MONO_ARCH_SAVE_REGS;
7097 prelink_method (method->method);
7101 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7103 MonoClass *klass = mono_class_from_mono_type (type->type);
7105 gpointer iter = NULL;
7106 MONO_ARCH_SAVE_REGS;
7108 while ((m = mono_class_get_methods (klass, &iter)))
7112 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7114 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7115 gint32 const **exponents,
7116 gunichar2 const **digitLowerTable,
7117 gunichar2 const **digitUpperTable,
7118 gint64 const **tenPowersList,
7119 gint32 const **decHexDigits)
7121 *mantissas = Formatter_MantissaBitsTable;
7122 *exponents = Formatter_TensExponentTable;
7123 *digitLowerTable = Formatter_DigitLowerTable;
7124 *digitUpperTable = Formatter_DigitUpperTable;
7125 *tenPowersList = Formatter_TenPowersList;
7126 *decHexDigits = Formatter_DecHexDigits;
7129 /* These parameters are "readonly" in corlib/System/Char.cs */
7131 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7132 guint8 const **numeric_data,
7133 gdouble const **numeric_data_values,
7134 guint16 const **to_lower_data_low,
7135 guint16 const **to_lower_data_high,
7136 guint16 const **to_upper_data_low,
7137 guint16 const **to_upper_data_high)
7139 *category_data = CategoryData;
7140 *numeric_data = NumericData;
7141 *numeric_data_values = NumericDataValues;
7142 *to_lower_data_low = ToLowerDataLow;
7143 *to_lower_data_high = ToLowerDataHigh;
7144 *to_upper_data_low = ToUpperDataLow;
7145 *to_upper_data_high = ToUpperDataHigh;
7149 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7151 return method->method->token;
7155 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7156 * and avoid useless allocations.
7159 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7163 for (i = 0; i < type->num_mods; ++i) {
7164 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7169 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7171 for (i = 0; i < type->num_mods; ++i) {
7172 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7173 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7174 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7182 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7184 MonoType *type = param->ClassImpl->type;
7185 MonoReflectionMethod *method = (MonoReflectionMethod*)param->MemberImpl;
7186 MonoImage *image = method->method->klass->image;
7187 int pos = param->PositionImpl;
7188 MonoMethodSignature *sig = mono_method_signature (method->method);
7192 type = sig->params [pos];
7194 return type_array_from_modifiers (image, type, optional);
7198 get_property_type (MonoProperty *prop)
7200 MonoMethodSignature *sig;
7202 sig = mono_method_signature (prop->get);
7204 } else if (prop->set) {
7205 sig = mono_method_signature (prop->set);
7206 return sig->params [sig->param_count - 1];
7212 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7214 MonoType *type = get_property_type (property->property);
7215 MonoImage *image = property->klass->image;
7219 return type_array_from_modifiers (image, type, optional);
7223 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7225 MonoCustomAttrInfo *cinfo;
7228 cinfo = mono_reflection_get_custom_attrs_info (obj);
7231 found = mono_custom_attrs_has_attr (cinfo, mono_class_from_mono_type (attr_type->type));
7233 mono_custom_attrs_free (cinfo);
7238 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7240 MonoArray *res = mono_reflection_get_custom_attrs_by_type (obj, attr_type ? mono_class_from_mono_type (attr_type->type) : NULL);
7242 if (mono_loader_get_last_error ()) {
7243 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7244 g_assert_not_reached ();
7253 ves_icall_Mono_Runtime_GetDisplayName (void)
7256 MonoString *display_name;
7258 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7259 display_name = mono_string_new (mono_domain_get (), info);
7261 return display_name;
7265 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7267 MonoString *message;
7271 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7272 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7275 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7277 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7285 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7286 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7287 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7288 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7289 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7290 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7291 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7292 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7296 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7301 gunichar2 last, prev_last, prev2_last;
7309 last = prev_last = 0, prev2_last = 0;
7310 for (i = 0; i < ilength; i++) {
7312 if (c >= sizeof (dbase64)) {
7313 exc = mono_exception_from_name_msg (mono_get_corlib (),
7314 "System", "FormatException",
7315 "Invalid character found.");
7316 mono_raise_exception (exc);
7317 } else if (isspace (c)) {
7320 prev2_last = prev_last;
7326 olength = ilength - ignored;
7328 if (allowWhitespaceOnly && olength == 0) {
7329 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7332 if ((olength & 3) != 0 || olength <= 0) {
7333 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7334 "FormatException", "Invalid length.");
7335 mono_raise_exception (exc);
7338 if (prev2_last == '=') {
7339 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7340 mono_raise_exception (exc);
7343 olength = (olength * 3) / 4;
7347 if (prev_last == '=')
7350 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7351 res_ptr = mono_array_addr (result, guchar, 0);
7352 for (i = 0; i < ilength; ) {
7355 for (k = 0; k < 4 && i < ilength;) {
7361 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7362 exc = mono_exception_from_name_msg (mono_get_corlib (),
7363 "System", "FormatException",
7364 "Invalid character found.");
7365 mono_raise_exception (exc);
7370 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7372 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7374 *res_ptr++ = (b [2] << 6) | b [3];
7376 while (i < ilength && isspace (start [i]))
7384 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7386 MONO_ARCH_SAVE_REGS;
7388 return base64_to_byte_array (mono_string_chars (str),
7389 mono_string_length (str), allowWhitespaceOnly);
7393 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7395 MONO_ARCH_SAVE_REGS;
7397 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7401 #define ICALL_TYPE(id,name,first)
7402 #define ICALL(id,name,func) Icall_ ## id,
7405 #include "metadata/icall-def.h"
7411 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7412 #define ICALL(id,name,func)
7414 #include "metadata/icall-def.h"
7420 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7421 #define ICALL(id,name,func)
7423 guint16 first_icall;
7426 static const IcallTypeDesc
7427 icall_type_descs [] = {
7428 #include "metadata/icall-def.h"
7432 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7435 #define ICALL_TYPE(id,name,first)
7438 #ifdef HAVE_ARRAY_ELEM_INIT
7439 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7440 #define MSGSTRFIELD1(line) str##line
7442 static const struct msgstrtn_t {
7443 #define ICALL(id,name,func)
7445 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7446 #include "metadata/icall-def.h"
7448 } icall_type_names_str = {
7449 #define ICALL_TYPE(id,name,first) (name),
7450 #include "metadata/icall-def.h"
7453 static const guint16 icall_type_names_idx [] = {
7454 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7455 #include "metadata/icall-def.h"
7458 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7460 static const struct msgstr_t {
7462 #define ICALL_TYPE(id,name,first)
7463 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7464 #include "metadata/icall-def.h"
7466 } icall_names_str = {
7467 #define ICALL(id,name,func) (name),
7468 #include "metadata/icall-def.h"
7471 static const guint16 icall_names_idx [] = {
7472 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7473 #include "metadata/icall-def.h"
7476 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7482 #define ICALL_TYPE(id,name,first) name,
7483 #define ICALL(id,name,func)
7484 static const char* const
7485 icall_type_names [] = {
7486 #include "metadata/icall-def.h"
7490 #define icall_type_name_get(id) (icall_type_names [(id)])
7494 #define ICALL_TYPE(id,name,first)
7495 #define ICALL(id,name,func) name,
7496 static const char* const
7498 #include "metadata/icall-def.h"
7501 #define icall_name_get(id) icall_names [(id)]
7503 #endif /* !HAVE_ARRAY_ELEM_INIT */
7507 #define ICALL_TYPE(id,name,first)
7508 #define ICALL(id,name,func) func,
7509 static const gconstpointer
7510 icall_functions [] = {
7511 #include "metadata/icall-def.h"
7515 static GHashTable *icall_hash = NULL;
7516 static GHashTable *jit_icall_hash_name = NULL;
7517 static GHashTable *jit_icall_hash_addr = NULL;
7520 mono_icall_init (void)
7524 /* check that tables are sorted: disable in release */
7527 const char *prev_class = NULL;
7528 const char *prev_method;
7530 for (i = 0; i < Icall_type_num; ++i) {
7531 const IcallTypeDesc *desc;
7534 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7535 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7536 prev_class = icall_type_name_get (i);
7537 desc = &icall_type_descs [i];
7538 num_icalls = icall_desc_num_icalls (desc);
7539 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7540 for (j = 0; j < num_icalls; ++j) {
7541 const char *methodn = icall_name_get (desc->first_icall + j);
7542 if (prev_method && strcmp (prev_method, methodn) >= 0)
7543 g_print ("method %s should come before method %s\n", methodn, prev_method);
7544 prev_method = methodn;
7549 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7553 mono_icall_cleanup (void)
7555 g_hash_table_destroy (icall_hash);
7556 g_hash_table_destroy (jit_icall_hash_name);
7557 g_hash_table_destroy (jit_icall_hash_addr);
7561 mono_add_internal_call (const char *name, gconstpointer method)
7563 mono_loader_lock ();
7565 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7567 mono_loader_unlock ();
7570 #ifdef HAVE_ARRAY_ELEM_INIT
7572 compare_method_imap (const void *key, const void *elem)
7574 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7575 return strcmp (key, method_name);
7579 find_method_icall (const IcallTypeDesc *imap, const char *name)
7581 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7584 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7588 compare_class_imap (const void *key, const void *elem)
7590 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7591 return strcmp (key, class_name);
7594 static const IcallTypeDesc*
7595 find_class_icalls (const char *name)
7597 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7600 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7605 compare_method_imap (const void *key, const void *elem)
7607 const char** method_name = (const char**)elem;
7608 return strcmp (key, *method_name);
7612 find_method_icall (const IcallTypeDesc *imap, const char *name)
7614 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7617 return (gpointer)icall_functions [(nameslot - icall_names)];
7621 compare_class_imap (const void *key, const void *elem)
7623 const char** class_name = (const char**)elem;
7624 return strcmp (key, *class_name);
7627 static const IcallTypeDesc*
7628 find_class_icalls (const char *name)
7630 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7633 return &icall_type_descs [nameslot - icall_type_names];
7639 * we should probably export this as an helper (handle nested types).
7640 * Returns the number of chars written in buf.
7643 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7645 int nspacelen, cnamelen;
7646 nspacelen = strlen (klass->name_space);
7647 cnamelen = strlen (klass->name);
7648 if (nspacelen + cnamelen + 2 > bufsize)
7651 memcpy (buf, klass->name_space, nspacelen);
7652 buf [nspacelen ++] = '.';
7654 memcpy (buf + nspacelen, klass->name, cnamelen);
7655 buf [nspacelen + cnamelen] = 0;
7656 return nspacelen + cnamelen;
7660 mono_lookup_internal_call (MonoMethod *method)
7665 int typelen = 0, mlen, siglen;
7667 const IcallTypeDesc *imap;
7669 g_assert (method != NULL);
7671 if (method->is_inflated)
7672 method = ((MonoMethodInflated *) method)->declaring;
7674 if (method->klass->nested_in) {
7675 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7679 mname [pos++] = '/';
7682 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7688 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7693 imap = find_class_icalls (mname);
7695 mname [typelen] = ':';
7696 mname [typelen + 1] = ':';
7698 mlen = strlen (method->name);
7699 memcpy (mname + typelen + 2, method->name, mlen);
7700 sigstart = mname + typelen + 2 + mlen;
7703 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7704 siglen = strlen (tmpsig);
7705 if (typelen + mlen + siglen + 6 > sizeof (mname))
7708 memcpy (sigstart + 1, tmpsig, siglen);
7709 sigstart [siglen + 1] = ')';
7710 sigstart [siglen + 2] = 0;
7713 mono_loader_lock ();
7715 res = g_hash_table_lookup (icall_hash, mname);
7717 mono_loader_unlock ();
7720 /* try without signature */
7722 res = g_hash_table_lookup (icall_hash, mname);
7724 mono_loader_unlock ();
7728 /* it wasn't found in the static call tables */
7730 mono_loader_unlock ();
7733 res = find_method_icall (imap, sigstart - mlen);
7735 mono_loader_unlock ();
7738 /* try _with_ signature */
7740 res = find_method_icall (imap, sigstart - mlen);
7742 mono_loader_unlock ();
7746 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7747 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7748 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7749 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7750 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");
7751 g_print ("If you see other errors or faults after this message they are probably related\n");
7752 g_print ("and you need to fix your mono install first.\n");
7754 mono_loader_unlock ();
7760 type_from_typename (char *typename)
7762 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7764 if (!strcmp (typename, "int"))
7765 klass = mono_defaults.int_class;
7766 else if (!strcmp (typename, "ptr"))
7767 klass = mono_defaults.int_class;
7768 else if (!strcmp (typename, "void"))
7769 klass = mono_defaults.void_class;
7770 else if (!strcmp (typename, "int32"))
7771 klass = mono_defaults.int32_class;
7772 else if (!strcmp (typename, "uint32"))
7773 klass = mono_defaults.uint32_class;
7774 else if (!strcmp (typename, "int8"))
7775 klass = mono_defaults.sbyte_class;
7776 else if (!strcmp (typename, "uint8"))
7777 klass = mono_defaults.byte_class;
7778 else if (!strcmp (typename, "int16"))
7779 klass = mono_defaults.int16_class;
7780 else if (!strcmp (typename, "uint16"))
7781 klass = mono_defaults.uint16_class;
7782 else if (!strcmp (typename, "long"))
7783 klass = mono_defaults.int64_class;
7784 else if (!strcmp (typename, "ulong"))
7785 klass = mono_defaults.uint64_class;
7786 else if (!strcmp (typename, "float"))
7787 klass = mono_defaults.single_class;
7788 else if (!strcmp (typename, "double"))
7789 klass = mono_defaults.double_class;
7790 else if (!strcmp (typename, "object"))
7791 klass = mono_defaults.object_class;
7792 else if (!strcmp (typename, "obj"))
7793 klass = mono_defaults.object_class;
7794 else if (!strcmp (typename, "string"))
7795 klass = mono_defaults.string_class;
7796 else if (!strcmp (typename, "bool"))
7797 klass = mono_defaults.boolean_class;
7798 else if (!strcmp (typename, "boolean"))
7799 klass = mono_defaults.boolean_class;
7801 g_error ("%s", typename);
7802 g_assert_not_reached ();
7804 return &klass->byval_arg;
7807 MonoMethodSignature*
7808 mono_create_icall_signature (const char *sigstr)
7813 MonoMethodSignature *res;
7815 mono_loader_lock ();
7816 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7818 mono_loader_unlock ();
7822 parts = g_strsplit (sigstr, " ", 256);
7831 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7834 #ifdef PLATFORM_WIN32
7836 * Under windows, the default pinvoke calling convention is STDCALL but
7839 res->call_convention = MONO_CALL_C;
7842 res->ret = type_from_typename (parts [0]);
7843 for (i = 1; i < len; ++i) {
7844 res->params [i - 1] = type_from_typename (parts [i]);
7849 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7851 mono_loader_unlock ();
7857 mono_find_jit_icall_by_name (const char *name)
7859 MonoJitICallInfo *info;
7860 g_assert (jit_icall_hash_name);
7862 mono_loader_lock ();
7863 info = g_hash_table_lookup (jit_icall_hash_name, name);
7864 mono_loader_unlock ();
7869 mono_find_jit_icall_by_addr (gconstpointer addr)
7871 MonoJitICallInfo *info;
7872 g_assert (jit_icall_hash_addr);
7874 mono_loader_lock ();
7875 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7876 mono_loader_unlock ();
7882 * mono_get_jit_icall_info:
7884 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
7885 * caller should access it while holding the loader lock.
7888 mono_get_jit_icall_info (void)
7890 return jit_icall_hash_name;
7894 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
7896 mono_loader_lock ();
7897 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
7898 mono_loader_unlock ();
7902 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
7904 MonoJitICallInfo *info;
7909 mono_loader_lock ();
7911 if (!jit_icall_hash_name) {
7912 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
7913 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
7916 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
7917 g_warning ("jit icall already defined \"%s\"\n", name);
7918 g_assert_not_reached ();
7921 info = g_new0 (MonoJitICallInfo, 1);
7928 info->wrapper = func;
7930 info->wrapper = NULL;
7933 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
7934 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
7936 mono_loader_unlock ();