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 (HOST_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/metadata/mono-ptr-array.h>
71 #include <mono/io-layer/io-layer.h>
72 #include <mono/utils/strtod.h>
73 #include <mono/utils/monobitset.h>
74 #include <mono/utils/mono-time.h>
75 #include <mono/utils/mono-proclib.h>
76 #include <mono/utils/mono-string.h>
77 #include <mono/utils/mono-error-internals.h>
78 #include <mono/utils/mono-mmap.h>
80 #if defined (HOST_WIN32)
86 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
88 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
91 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
93 static inline MonoBoolean
94 is_generic_parameter (MonoType *type)
96 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
100 mono_class_init_or_throw (MonoClass *klass)
102 if (!mono_class_init (klass))
103 mono_raise_exception (mono_class_get_exception_for_failure (klass));
107 * We expect a pointer to a char, not a string
110 mono_double_ParseImpl (char *ptr, double *result)
112 gchar *endptr = NULL;
119 *result = strtod (ptr, &endptr);
122 /* mono_strtod () is not thread-safe */
123 EnterCriticalSection (&mono_strtod_mutex);
124 *result = mono_strtod (ptr, &endptr);
125 LeaveCriticalSection (&mono_strtod_mutex);
129 if (!*ptr || (endptr && *endptr))
136 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
145 ao = (MonoArray *)this;
146 ac = (MonoClass *)ao->obj.vtable->klass;
148 esize = mono_array_element_size (ac);
149 ea = (gpointer*)((char*)ao->vector + (pos * esize));
151 if (ac->element_class->valuetype)
152 return mono_value_box (this->vtable->domain, ac->element_class, ea);
158 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
166 MONO_CHECK_ARG_NULL (idxs);
168 io = (MonoArray *)idxs;
169 ic = (MonoClass *)io->obj.vtable->klass;
171 ao = (MonoArray *)this;
172 ac = (MonoClass *)ao->obj.vtable->klass;
174 g_assert (ic->rank == 1);
175 if (io->bounds != NULL || io->max_length != ac->rank)
176 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
178 ind = (gint32 *)io->vector;
180 if (ao->bounds == NULL) {
181 if (*ind < 0 || *ind >= ao->max_length)
182 mono_raise_exception (mono_get_exception_index_out_of_range ());
184 return ves_icall_System_Array_GetValueImpl (this, *ind);
187 for (i = 0; i < ac->rank; i++)
188 if ((ind [i] < ao->bounds [i].lower_bound) ||
189 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
190 mono_raise_exception (mono_get_exception_index_out_of_range ());
192 pos = ind [0] - ao->bounds [0].lower_bound;
193 for (i = 1; i < ac->rank; i++)
194 pos = pos*ao->bounds [i].length + ind [i] -
195 ao->bounds [i].lower_bound;
197 return ves_icall_System_Array_GetValueImpl (this, pos);
201 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
203 MonoClass *ac, *vc, *ec;
215 vc = value->vtable->klass;
219 ac = this->obj.vtable->klass;
220 ec = ac->element_class;
222 esize = mono_array_element_size (ac);
223 ea = (gpointer*)((char*)this->vector + (pos * esize));
224 va = (gpointer*)((char*)value + sizeof (MonoObject));
226 if (mono_class_is_nullable (ec)) {
227 mono_nullable_init ((guint8*)ea, value, ec);
232 memset (ea, 0, esize);
236 #define NO_WIDENING_CONVERSION G_STMT_START{\
237 mono_raise_exception (mono_get_exception_argument ( \
238 "value", "not a widening conversion")); \
241 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
242 if (esize < vsize + (extra)) \
243 mono_raise_exception (mono_get_exception_argument ( \
244 "value", "not a widening conversion")); \
247 #define INVALID_CAST G_STMT_START{\
248 mono_raise_exception (mono_get_exception_invalid_cast ()); \
251 /* Check element (destination) type. */
252 switch (ec->byval_arg.type) {
253 case MONO_TYPE_STRING:
254 switch (vc->byval_arg.type) {
255 case MONO_TYPE_STRING:
261 case MONO_TYPE_BOOLEAN:
262 switch (vc->byval_arg.type) {
263 case MONO_TYPE_BOOLEAN:
276 NO_WIDENING_CONVERSION;
283 if (!ec->valuetype) {
284 if (!mono_object_isinst (value, ec))
286 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
290 if (mono_object_isinst (value, ec)) {
291 if (ec->has_references)
292 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
294 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
301 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
303 et = ec->byval_arg.type;
304 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
305 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
307 vt = vc->byval_arg.type;
308 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
309 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
311 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
317 case MONO_TYPE_CHAR: \
318 CHECK_WIDENING_CONVERSION(0); \
319 *(etype *) ea = (etype) u64; \
321 /* You can't assign a signed value to an unsigned array. */ \
326 /* You can't assign a floating point number to an integer array. */ \
329 NO_WIDENING_CONVERSION; \
333 #define ASSIGN_SIGNED(etype) G_STMT_START{\
339 CHECK_WIDENING_CONVERSION(0); \
340 *(etype *) ea = (etype) i64; \
342 /* You can assign an unsigned value to a signed array if the array's */ \
343 /* element size is larger than the value size. */ \
348 case MONO_TYPE_CHAR: \
349 CHECK_WIDENING_CONVERSION(1); \
350 *(etype *) ea = (etype) u64; \
352 /* You can't assign a floating point number to an integer array. */ \
355 NO_WIDENING_CONVERSION; \
359 #define ASSIGN_REAL(etype) G_STMT_START{\
363 CHECK_WIDENING_CONVERSION(0); \
364 *(etype *) ea = (etype) r64; \
366 /* All integer values fit into a floating point array, so we don't */ \
367 /* need to CHECK_WIDENING_CONVERSION here. */ \
372 *(etype *) ea = (etype) i64; \
378 case MONO_TYPE_CHAR: \
379 *(etype *) ea = (etype) u64; \
386 u64 = *(guint8 *) va;
389 u64 = *(guint16 *) va;
392 u64 = *(guint32 *) va;
395 u64 = *(guint64 *) va;
401 i64 = *(gint16 *) va;
404 i64 = *(gint32 *) va;
407 i64 = *(gint64 *) va;
410 r64 = *(gfloat *) va;
413 r64 = *(gdouble *) va;
416 u64 = *(guint16 *) va;
418 case MONO_TYPE_BOOLEAN:
419 /* Boolean is only compatible with itself. */
432 NO_WIDENING_CONVERSION;
439 /* If we can't do a direct copy, let's try a widening conversion. */
442 ASSIGN_UNSIGNED (guint16);
444 ASSIGN_UNSIGNED (guint8);
446 ASSIGN_UNSIGNED (guint16);
448 ASSIGN_UNSIGNED (guint32);
450 ASSIGN_UNSIGNED (guint64);
452 ASSIGN_SIGNED (gint8);
454 ASSIGN_SIGNED (gint16);
456 ASSIGN_SIGNED (gint32);
458 ASSIGN_SIGNED (gint64);
460 ASSIGN_REAL (gfloat);
462 ASSIGN_REAL (gdouble);
466 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
470 #undef NO_WIDENING_CONVERSION
471 #undef CHECK_WIDENING_CONVERSION
472 #undef ASSIGN_UNSIGNED
478 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
486 MONO_CHECK_ARG_NULL (idxs);
488 ic = idxs->obj.vtable->klass;
489 ac = this->obj.vtable->klass;
491 g_assert (ic->rank == 1);
492 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
493 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
495 ind = (gint32 *)idxs->vector;
497 if (this->bounds == NULL) {
498 if (*ind < 0 || *ind >= this->max_length)
499 mono_raise_exception (mono_get_exception_index_out_of_range ());
501 ves_icall_System_Array_SetValueImpl (this, value, *ind);
505 for (i = 0; i < ac->rank; i++)
506 if ((ind [i] < this->bounds [i].lower_bound) ||
507 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
508 mono_raise_exception (mono_get_exception_index_out_of_range ());
510 pos = ind [0] - this->bounds [0].lower_bound;
511 for (i = 1; i < ac->rank; i++)
512 pos = pos * this->bounds [i].length + ind [i] -
513 this->bounds [i].lower_bound;
515 ves_icall_System_Array_SetValueImpl (this, value, pos);
519 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
521 MonoClass *aklass, *klass;
524 gboolean bounded = FALSE;
528 MONO_CHECK_ARG_NULL (type);
529 MONO_CHECK_ARG_NULL (lengths);
531 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
533 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
535 for (i = 0; i < mono_array_length (lengths); i++)
536 if (mono_array_get (lengths, gint32, i) < 0)
537 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
539 klass = mono_class_from_mono_type (type->type);
540 mono_class_init_or_throw (klass);
542 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
543 /* vectors are not the same as one dimensional arrays with no-zero bounds */
548 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
550 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
551 for (i = 0; i < aklass->rank; ++i) {
552 sizes [i] = mono_array_get (lengths, guint32, i);
554 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
556 sizes [i + aklass->rank] = 0;
559 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
565 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
567 MonoClass *aklass, *klass;
570 gboolean bounded = FALSE;
574 MONO_CHECK_ARG_NULL (type);
575 MONO_CHECK_ARG_NULL (lengths);
577 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
579 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
581 for (i = 0; i < mono_array_length (lengths); i++)
582 if ((mono_array_get (lengths, gint64, i) < 0) ||
583 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
584 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
586 klass = mono_class_from_mono_type (type->type);
587 mono_class_init_or_throw (klass);
589 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
590 /* vectors are not the same as one dimensional arrays with no-zero bounds */
595 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
597 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
598 for (i = 0; i < aklass->rank; ++i) {
599 sizes [i] = mono_array_get (lengths, guint64, i);
601 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
603 sizes [i + aklass->rank] = 0;
606 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
612 ves_icall_System_Array_GetRank (MonoObject *this)
616 return this->vtable->klass->rank;
620 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
622 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
627 if ((dimension < 0) || (dimension >= rank))
628 mono_raise_exception (mono_get_exception_index_out_of_range ());
630 if (this->bounds == NULL)
631 length = this->max_length;
633 length = this->bounds [dimension].length;
635 #ifdef MONO_BIG_ARRAYS
636 if (length > G_MAXINT32)
637 mono_raise_exception (mono_get_exception_overflow ());
643 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
645 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
649 if ((dimension < 0) || (dimension >= rank))
650 mono_raise_exception (mono_get_exception_index_out_of_range ());
652 if (this->bounds == NULL)
653 return this->max_length;
655 return this->bounds [dimension].length;
659 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
661 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
665 if ((dimension < 0) || (dimension >= rank))
666 mono_raise_exception (mono_get_exception_index_out_of_range ());
668 if (this->bounds == NULL)
671 return this->bounds [dimension].lower_bound;
675 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
677 int sz = mono_array_element_size (mono_object_class (arr));
678 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
682 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
687 MonoClass *src_class;
688 MonoClass *dest_class;
693 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
696 if (source->bounds || dest->bounds)
699 /* there's no integer overflow since mono_array_length returns an unsigned integer */
700 if ((dest_idx + length > mono_array_length (dest)) ||
701 (source_idx + length > mono_array_length (source)))
704 src_class = source->obj.vtable->klass->element_class;
705 dest_class = dest->obj.vtable->klass->element_class;
708 * Handle common cases.
711 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
712 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
713 int has_refs = dest_class->has_references;
714 for (i = source_idx; i < source_idx + length; ++i) {
715 MonoObject *elem = mono_array_get (source, MonoObject*, i);
716 if (elem && !mono_object_isinst (elem, dest_class))
720 element_size = mono_array_element_size (dest->obj.vtable->klass);
721 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
722 for (i = 0; i < length; ++i) {
723 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
724 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
728 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
730 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
735 /* Check if we're copying a char[] <==> (u)short[] */
736 if (src_class != dest_class) {
737 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
740 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
742 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
743 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
744 for (i = source_idx; i < source_idx + length; ++i) {
745 MonoObject *elem = mono_array_get (source, MonoObject*, i);
746 if (elem && !mono_object_isinst (elem, dest_class))
753 if (dest_class->valuetype) {
754 element_size = mono_array_element_size (source->obj.vtable->klass);
755 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
756 if (dest_class->has_references) {
757 mono_value_copy_array (dest, dest_idx, source_addr, length);
759 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
760 memmove (dest_addr, source_addr, element_size * length);
763 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
770 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
779 ao = (MonoArray *)this;
780 ac = (MonoClass *)ao->obj.vtable->klass;
782 esize = mono_array_element_size (ac);
783 ea = (gpointer*)((char*)ao->vector + (pos * esize));
785 memcpy (value, ea, esize);
789 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
798 ao = (MonoArray *)this;
799 ac = (MonoClass *)ao->obj.vtable->klass;
800 ec = ac->element_class;
802 esize = mono_array_element_size (ac);
803 ea = (gpointer*)((char*)ao->vector + (pos * esize));
805 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
806 g_assert (esize == sizeof (gpointer));
807 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
809 g_assert (ec->inited);
810 g_assert (esize == mono_class_value_size (ec, NULL));
811 if (ec->has_references)
812 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
814 memcpy (ea, value, esize);
819 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
821 MonoClass *klass = array->obj.vtable->klass;
822 guint32 size = mono_array_element_size (klass);
823 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
825 const char *field_data;
827 if (MONO_TYPE_IS_REFERENCE (type) ||
828 (type->type == MONO_TYPE_VALUETYPE &&
829 (!mono_type_get_class (type) ||
830 mono_type_get_class (type)->has_references))) {
831 MonoException *exc = mono_get_exception_argument("array",
832 "Cannot initialize array containing references");
833 mono_raise_exception (exc);
836 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
837 MonoException *exc = mono_get_exception_argument("field_handle",
838 "Field doesn't have an RVA");
839 mono_raise_exception (exc);
842 size *= array->max_length;
843 field_data = mono_field_get_data (field_handle);
845 if (size > mono_type_size (field_handle->type, &align)) {
846 MonoException *exc = mono_get_exception_argument("field_handle",
847 "Field not large enough to fill array");
848 mono_raise_exception (exc);
851 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
853 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
854 guint ## n *src = (guint ## n *) field_data; \
855 guint ## n *end = (guint ## n *)((char*)src + size); \
857 for (; src < end; data++, src++) { \
858 *data = read ## n (src); \
862 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
864 switch (type->type) {
881 memcpy (mono_array_addr (array, char, 0), field_data, size);
885 memcpy (mono_array_addr (array, char, 0), field_data, size);
887 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
890 double *data = (double*)mono_array_addr (array, double, 0);
892 for (i = 0; i < size; i++, data++) {
902 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
906 return offsetof (MonoString, chars);
910 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
914 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
917 return mono_object_clone (obj);
921 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
926 MONO_CHECK_ARG_NULL (handle);
928 klass = mono_class_from_mono_type (handle);
929 MONO_CHECK_ARG (handle, klass);
931 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
933 /* This will call the type constructor */
934 mono_runtime_class_init (vtable);
938 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
942 mono_image_check_for_module_cctor (image);
943 if (image->has_module_cctor) {
944 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
945 /*It's fine to raise the exception here*/
946 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
951 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
956 /* later make this configurable and per-arch */
957 int min_size = 4096 * 4 * sizeof (void*);
958 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
959 /* if we have no info we are optimistic and assume there is enough room */
962 current = (guint8 *)&stack_addr;
963 if (current > stack_addr) {
964 if ((current - stack_addr) < min_size)
967 if (current - (stack_addr - stack_size) < min_size)
974 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
978 return mono_object_clone (this);
982 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
985 MonoObject **values = NULL;
989 MonoClassField* field;
994 klass = mono_object_class (this);
996 if (mono_class_num_fields (klass) == 0)
997 return mono_object_hash (this);
1000 * Compute the starting value of the hashcode for fields of primitive
1001 * types, and return the remaining fields in an array to the managed side.
1002 * This way, we can avoid costly reflection operations in managed code.
1005 while ((field = mono_class_get_fields (klass, &iter))) {
1006 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1008 if (mono_field_is_deleted (field))
1010 /* FIXME: Add more types */
1011 switch (field->type->type) {
1013 result ^= *(gint32*)((guint8*)this + field->offset);
1015 case MONO_TYPE_STRING: {
1017 s = *(MonoString**)((guint8*)this + field->offset);
1019 result ^= mono_string_hash (s);
1024 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1025 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1026 values [count++] = o;
1032 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1033 for (i = 0; i < count; ++i)
1034 mono_array_setref (*fields, i, values [i]);
1042 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1045 MonoObject **values = NULL;
1047 MonoClassField* field;
1051 MONO_ARCH_SAVE_REGS;
1053 MONO_CHECK_ARG_NULL (that);
1055 if (this->vtable != that->vtable)
1058 klass = mono_object_class (this);
1060 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1061 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1064 * Do the comparison for fields of primitive type and return a result if
1065 * possible. Otherwise, return the remaining fields in an array to the
1066 * managed side. This way, we can avoid costly reflection operations in
1071 while ((field = mono_class_get_fields (klass, &iter))) {
1072 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1074 if (mono_field_is_deleted (field))
1076 /* FIXME: Add more types */
1077 switch (field->type->type) {
1080 case MONO_TYPE_BOOLEAN:
1081 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1086 case MONO_TYPE_CHAR:
1087 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1092 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1097 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1101 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1105 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1110 case MONO_TYPE_STRING: {
1111 MonoString *s1, *s2;
1112 guint32 s1len, s2len;
1113 s1 = *(MonoString**)((guint8*)this + field->offset);
1114 s2 = *(MonoString**)((guint8*)that + field->offset);
1117 if ((s1 == NULL) || (s2 == NULL))
1119 s1len = mono_string_length (s1);
1120 s2len = mono_string_length (s2);
1124 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1130 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1131 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1132 values [count++] = o;
1133 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1134 values [count++] = o;
1137 if (klass->enumtype)
1138 /* enums only have one non-static field */
1144 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1145 for (i = 0; i < count; ++i)
1146 mono_array_setref (*fields, i, values [i]);
1153 static MonoReflectionType *
1154 ves_icall_System_Object_GetType (MonoObject *obj)
1156 MONO_ARCH_SAVE_REGS;
1158 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1159 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1161 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1165 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1167 MONO_ARCH_SAVE_REGS;
1169 mtype->type = &obj->vtable->klass->byval_arg;
1170 g_assert (mtype->type->type);
1174 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1176 MONO_ARCH_SAVE_REGS;
1178 MONO_CHECK_ARG_NULL (obj);
1180 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1184 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1185 MonoReflectionMethod *method,
1186 MonoArray *opt_param_types)
1188 MONO_ARCH_SAVE_REGS;
1190 MONO_CHECK_ARG_NULL (method);
1192 return mono_image_create_method_token (
1193 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1197 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1199 MONO_ARCH_SAVE_REGS;
1201 mono_image_create_pefile (mb, file);
1205 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1207 MONO_ARCH_SAVE_REGS;
1209 mono_image_build_metadata (mb);
1213 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1215 MONO_ARCH_SAVE_REGS;
1217 mono_image_register_token (mb->dynamic_image, token, obj);
1221 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1223 MonoMethod **dest = data;
1225 /* skip unmanaged frames */
1241 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1243 MonoMethod **dest = data;
1245 /* skip unmanaged frames */
1250 if (!strcmp (m->klass->name_space, "System.Reflection"))
1259 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1261 MonoMethod **dest = data;
1263 /* skip unmanaged frames */
1267 if (m->wrapper_type != MONO_WRAPPER_NONE)
1270 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1284 static MonoReflectionType *
1285 type_from_name (const char *str, MonoBoolean ignoreCase)
1287 MonoType *type = NULL;
1288 MonoAssembly *assembly = NULL;
1289 MonoTypeNameParse info;
1290 char *temp_str = g_strdup (str);
1291 gboolean type_resolve = FALSE;
1293 MONO_ARCH_SAVE_REGS;
1295 /* mono_reflection_parse_type() mangles the string */
1296 if (!mono_reflection_parse_type (temp_str, &info)) {
1297 mono_reflection_free_type_info (&info);
1302 if (info.assembly.name) {
1303 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1305 MonoMethod *m = mono_method_get_last_managed ();
1306 MonoMethod *dest = m;
1308 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1313 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1314 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1315 * to crash. This only seems to happen in some strange remoting
1316 * scenarios and I was unable to figure out what's happening there.
1317 * Dec 10, 2005 - Martin.
1321 assembly = dest->klass->image->assembly;
1322 type_resolve = TRUE;
1324 g_warning (G_STRLOC);
1329 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1330 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1333 if (!info.assembly.name && !type) /* try mscorlib */
1334 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1336 if (assembly && !type && type_resolve) {
1337 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1338 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1341 mono_reflection_free_type_info (&info);
1347 return mono_type_get_object (mono_domain_get (), type);
1351 MonoReflectionType *
1352 mono_type_get (const char *str)
1354 char *copy = g_strdup (str);
1355 MonoReflectionType *type = type_from_name (copy, FALSE);
1362 static MonoReflectionType*
1363 ves_icall_type_from_name (MonoString *name,
1364 MonoBoolean throwOnError,
1365 MonoBoolean ignoreCase)
1367 char *str = mono_string_to_utf8 (name);
1368 MonoReflectionType *type;
1370 type = type_from_name (str, ignoreCase);
1373 MonoException *e = NULL;
1376 e = mono_get_exception_type_load (name, NULL);
1378 mono_loader_clear_error ();
1380 mono_raise_exception (e);
1387 static MonoReflectionType*
1388 ves_icall_type_from_handle (MonoType *handle)
1390 MonoDomain *domain = mono_domain_get ();
1392 MONO_ARCH_SAVE_REGS;
1394 return mono_type_get_object (domain, handle);
1398 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1400 MONO_ARCH_SAVE_REGS;
1402 if (c && type->type && c->type)
1403 return mono_metadata_type_equal (type->type, c->type);
1405 return (type == c) ? TRUE : FALSE;
1408 /* System.TypeCode */
1427 TYPECODE_STRING = 18
1431 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1433 int t = type->type->type;
1435 MONO_ARCH_SAVE_REGS;
1437 if (type->type->byref)
1438 return TYPECODE_OBJECT;
1442 case MONO_TYPE_VOID:
1443 return TYPECODE_OBJECT;
1444 case MONO_TYPE_BOOLEAN:
1445 return TYPECODE_BOOLEAN;
1447 return TYPECODE_BYTE;
1449 return TYPECODE_SBYTE;
1451 return TYPECODE_UINT16;
1453 return TYPECODE_INT16;
1454 case MONO_TYPE_CHAR:
1455 return TYPECODE_CHAR;
1459 return TYPECODE_OBJECT;
1461 return TYPECODE_UINT32;
1463 return TYPECODE_INT32;
1465 return TYPECODE_UINT64;
1467 return TYPECODE_INT64;
1469 return TYPECODE_SINGLE;
1471 return TYPECODE_DOUBLE;
1472 case MONO_TYPE_VALUETYPE: {
1473 MonoClass *klass = type->type->data.klass;
1475 if (klass->enumtype) {
1476 t = mono_class_enum_basetype (klass)->type;
1478 } else if (mono_is_corlib_image (klass->image)) {
1479 if (strcmp (klass->name_space, "System") == 0) {
1480 if (strcmp (klass->name, "Decimal") == 0)
1481 return TYPECODE_DECIMAL;
1482 else if (strcmp (klass->name, "DateTime") == 0)
1483 return TYPECODE_DATETIME;
1486 return TYPECODE_OBJECT;
1488 case MONO_TYPE_STRING:
1489 return TYPECODE_STRING;
1490 case MONO_TYPE_SZARRAY:
1491 case MONO_TYPE_ARRAY:
1492 case MONO_TYPE_OBJECT:
1494 case MONO_TYPE_MVAR:
1495 case MONO_TYPE_TYPEDBYREF:
1496 return TYPECODE_OBJECT;
1497 case MONO_TYPE_CLASS:
1499 MonoClass *klass = type->type->data.klass;
1500 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1501 if (strcmp (klass->name, "DBNull") == 0)
1502 return TYPECODE_DBNULL;
1505 return TYPECODE_OBJECT;
1506 case MONO_TYPE_GENERICINST:
1507 return TYPECODE_OBJECT;
1509 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1515 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1521 MONO_ARCH_SAVE_REGS;
1523 g_assert (type != NULL);
1525 domain = ((MonoObject *)type)->vtable->domain;
1527 if (!c) /* FIXME: dont know what do do here */
1530 klass = mono_class_from_mono_type (type->type);
1531 klassc = mono_class_from_mono_type (c->type);
1533 /* Interface check requires a more complex setup so we
1534 * only do for them. Otherwise we simply avoid mono_class_init.
1536 if (check_interfaces) {
1537 mono_class_init_or_throw (klass);
1538 mono_class_init_or_throw (klassc);
1539 } else if (!klass->supertypes || !klassc->supertypes) {
1540 mono_loader_lock ();
1541 mono_class_setup_supertypes (klass);
1542 mono_class_setup_supertypes (klassc);
1543 mono_loader_unlock ();
1546 if (type->type->byref)
1547 return klassc == mono_defaults.object_class;
1549 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1553 mono_type_is_primitive (MonoType *type)
1555 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1556 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1560 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1562 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1563 return mono_class_enum_basetype (type->data.klass);
1564 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1565 return mono_class_enum_basetype (type->data.generic_class->container_class);
1570 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1576 MONO_ARCH_SAVE_REGS;
1578 g_assert (type != NULL);
1580 domain = ((MonoObject *)type)->vtable->domain;
1582 klass = mono_class_from_mono_type (type->type);
1583 klassc = mono_class_from_mono_type (c->type);
1585 mono_class_init_or_throw (klass);
1586 mono_class_init_or_throw (klassc);
1588 if (type->type->byref ^ c->type->byref)
1591 if (type->type->byref) {
1592 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1593 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1595 klass = mono_class_from_mono_type (t);
1596 klassc = mono_class_from_mono_type (ot);
1598 if (mono_type_is_primitive (t)) {
1599 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1600 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1601 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1602 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1603 return t->type == ot->type;
1605 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1608 if (klass->valuetype)
1609 return klass == klassc;
1610 return klass->valuetype == klassc->valuetype;
1613 return mono_class_is_assignable_from (klass, klassc);
1617 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1619 MonoClass *klass = mono_class_from_mono_type (type->type);
1620 mono_class_init_or_throw (klass);
1621 return mono_object_isinst (obj, klass) != NULL;
1625 ves_icall_get_attributes (MonoReflectionType *type)
1627 MonoClass *klass = mono_class_from_mono_type (type->type);
1628 return klass->flags;
1631 static MonoReflectionMarshal*
1632 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1634 MonoClass *klass = field->field->parent;
1635 MonoMarshalType *info;
1638 if (klass->generic_container ||
1639 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1642 info = mono_marshal_load_type_info (klass);
1644 for (i = 0; i < info->num_fields; ++i) {
1645 if (info->fields [i].field == field->field) {
1646 if (!info->fields [i].mspec)
1649 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1656 static MonoReflectionField*
1657 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1659 gboolean found = FALSE;
1666 klass = handle->parent;
1668 klass = mono_class_from_mono_type (type);
1670 /* Check that the field belongs to the class */
1671 for (k = klass; k; k = k->parent) {
1672 if (k == handle->parent) {
1679 /* The managed code will throw the exception */
1683 return mono_field_get_object (mono_domain_get (), klass, handle);
1687 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1690 MonoType *type = mono_field_get_type_checked (field->field, &error);
1691 if (!mono_error_ok (&error))
1692 mono_error_raise_exception (&error);
1694 return type_array_from_modifiers (field->field->parent->image, type, optional);
1698 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1700 MonoDomain *domain = mono_domain_get ();
1701 MonoMethodSignature* sig;
1702 MONO_ARCH_SAVE_REGS;
1704 sig = mono_method_signature (method);
1706 g_assert (mono_loader_get_last_error ());
1707 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1710 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1711 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1712 info->attrs = method->flags;
1713 info->implattrs = method->iflags;
1714 if (sig->call_convention == MONO_CALL_DEFAULT)
1715 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1717 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1722 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1726 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1728 MonoDomain *domain = mono_domain_get ();
1730 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1733 static MonoReflectionMarshal*
1734 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1736 MonoDomain *domain = mono_domain_get ();
1737 MonoReflectionMarshal* res = NULL;
1738 MonoMarshalSpec **mspecs;
1741 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1742 mono_method_get_marshal_info (method, mspecs);
1745 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1747 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1749 mono_metadata_free_marshal_spec (mspecs [i]);
1756 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1758 MonoClass *parent = field->field->parent;
1759 if (!parent->size_inited)
1760 mono_class_init (parent);
1762 return field->field->offset - sizeof (MonoObject);
1765 static MonoReflectionType*
1766 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1769 MONO_ARCH_SAVE_REGS;
1771 parent = declaring? field->field->parent: field->klass;
1773 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1777 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1779 MonoClass *fklass = field->klass;
1780 MonoClassField *cf = field->field;
1781 MonoDomain *domain = mono_object_domain (field);
1783 if (fklass->image->assembly->ref_only)
1784 mono_raise_exception (mono_get_exception_invalid_operation (
1785 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1787 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1788 mono_security_core_clr_ensure_reflection_access_field (cf);
1790 return mono_field_get_value_object (domain, cf, obj);
1794 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1796 MonoClassField *cf = field->field;
1799 MONO_ARCH_SAVE_REGS;
1801 if (field->klass->image->assembly->ref_only)
1802 mono_raise_exception (mono_get_exception_invalid_operation (
1803 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1805 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1806 mono_security_core_clr_ensure_reflection_access_field (cf);
1808 v = (gchar *) value;
1809 if (!cf->type->byref) {
1810 switch (cf->type->type) {
1813 case MONO_TYPE_BOOLEAN:
1816 case MONO_TYPE_CHAR:
1825 case MONO_TYPE_VALUETYPE:
1827 v += sizeof (MonoObject);
1829 case MONO_TYPE_STRING:
1830 case MONO_TYPE_OBJECT:
1831 case MONO_TYPE_CLASS:
1832 case MONO_TYPE_ARRAY:
1833 case MONO_TYPE_SZARRAY:
1836 case MONO_TYPE_GENERICINST: {
1837 MonoGenericClass *gclass = cf->type->data.generic_class;
1838 g_assert (!gclass->context.class_inst->is_open);
1840 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1841 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1842 MonoObject *nullable;
1845 * Convert the boxed vtype into a Nullable structure.
1846 * This is complicated by the fact that Nullables have
1847 * a variable structure.
1849 nullable = mono_object_new (mono_domain_get (), nklass);
1851 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1853 v = mono_object_unbox (nullable);
1856 if (gclass->container_class->valuetype && (v != NULL))
1857 v += sizeof (MonoObject);
1861 g_error ("type 0x%x not handled in "
1862 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1867 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1868 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1869 if (!vtable->initialized)
1870 mono_runtime_class_init (vtable);
1871 mono_field_static_set_value (vtable, cf, v);
1873 mono_field_set_value (obj, cf, v);
1878 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1880 MonoObject *o = NULL;
1881 MonoClassField *field = this->field;
1883 MonoDomain *domain = mono_object_domain (this);
1885 MonoTypeEnum def_type;
1886 const char *def_value;
1888 MONO_ARCH_SAVE_REGS;
1890 mono_class_init (field->parent);
1892 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1893 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1895 if (field->parent->image->dynamic) {
1897 g_assert_not_reached ();
1900 def_value = mono_class_get_field_default_value (field, &def_type);
1902 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1906 case MONO_TYPE_BOOLEAN:
1909 case MONO_TYPE_CHAR:
1917 case MONO_TYPE_R8: {
1920 /* boxed value type */
1921 t = g_new0 (MonoType, 1);
1923 klass = mono_class_from_mono_type (t);
1925 o = mono_object_new (domain, klass);
1926 v = ((gchar *) o) + sizeof (MonoObject);
1927 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1930 case MONO_TYPE_STRING:
1931 case MONO_TYPE_CLASS:
1932 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1935 g_assert_not_reached ();
1941 static MonoReflectionType*
1942 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1945 MonoClassField *field = ref_field->field;
1946 MonoType *type = mono_field_get_type_checked (field, &error);
1947 if (!mono_error_ok (&error))
1948 mono_error_raise_exception (&error);
1949 return mono_type_get_object (mono_object_domain (ref_field), type);
1952 static MonoReflectionType*
1953 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1955 MonoMethod *method = rmethod->method.method;
1957 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1960 /* From MonoProperty.cs */
1962 PInfo_Attributes = 1,
1963 PInfo_GetMethod = 1 << 1,
1964 PInfo_SetMethod = 1 << 2,
1965 PInfo_ReflectedType = 1 << 3,
1966 PInfo_DeclaringType = 1 << 4,
1971 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1973 MonoDomain *domain = mono_object_domain (property);
1975 MONO_ARCH_SAVE_REGS;
1977 if ((req_info & PInfo_ReflectedType) != 0)
1978 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1979 else if ((req_info & PInfo_DeclaringType) != 0)
1980 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1982 if ((req_info & PInfo_Name) != 0)
1983 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1985 if ((req_info & PInfo_Attributes) != 0)
1986 info->attrs = property->property->attrs;
1988 if ((req_info & PInfo_GetMethod) != 0)
1989 MONO_STRUCT_SETREF (info, get, property->property->get ?
1990 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1992 if ((req_info & PInfo_SetMethod) != 0)
1993 MONO_STRUCT_SETREF (info, set, property->property->set ?
1994 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1996 * There may be other methods defined for properties, though, it seems they are not exposed
1997 * in the reflection API
2002 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2004 MonoDomain *domain = mono_object_domain (event);
2006 MONO_ARCH_SAVE_REGS;
2008 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2009 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2011 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2012 info->attrs = event->event->attrs;
2013 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2014 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2015 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2017 #ifndef MONO_SMALL_CONFIG
2018 if (event->event->other) {
2020 while (event->event->other [n])
2022 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2024 for (i = 0; i < n; i++)
2025 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2031 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2036 mono_class_setup_interfaces (klass, error);
2037 if (!mono_error_ok (error))
2040 for (i = 0; i < klass->interface_count; i++) {
2041 ic = klass->interfaces [i];
2042 g_hash_table_insert (ifaces, ic, ic);
2044 collect_interfaces (ic, ifaces, error);
2045 if (!mono_error_ok (error))
2051 MonoArray *iface_array;
2052 MonoGenericContext *context;
2056 } FillIfaceArrayData;
2059 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2061 FillIfaceArrayData *data = user_data;
2062 MonoClass *ic = key;
2063 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2065 if (!mono_error_ok (data->error))
2068 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2069 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2070 if (!mono_error_ok (data->error))
2074 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2077 mono_metadata_free_type (inflated);
2081 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2084 MonoClass *class = mono_class_from_mono_type (type->type);
2086 FillIfaceArrayData data = { 0 };
2089 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2091 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2092 data.context = mono_class_get_context (class);
2093 class = class->generic_class->container_class;
2096 for (parent = class; parent; parent = parent->parent) {
2097 mono_class_setup_interfaces (parent, &error);
2098 if (!mono_error_ok (&error))
2100 collect_interfaces (parent, iface_hash, &error);
2101 if (!mono_error_ok (&error))
2105 data.error = &error;
2106 data.domain = mono_object_domain (type);
2108 len = g_hash_table_size (iface_hash);
2110 return mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2112 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2113 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2114 if (!mono_error_ok (&error))
2117 g_hash_table_destroy (iface_hash);
2118 return data.iface_array;
2121 g_hash_table_destroy (iface_hash);
2122 mono_error_raise_exception (&error);
2127 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2129 gboolean variance_used;
2130 MonoClass *class = mono_class_from_mono_type (type->type);
2131 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2132 MonoReflectionMethod *member;
2135 int i = 0, len, ioffset;
2138 MONO_ARCH_SAVE_REGS;
2139 mono_class_init_or_throw (class);
2140 mono_class_init_or_throw (iclass);
2142 mono_class_setup_vtable (class);
2144 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2148 len = mono_class_num_methods (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));
2153 while ((method = mono_class_get_methods (iclass, &iter))) {
2154 member = mono_method_get_object (domain, method, iclass);
2155 mono_array_setref (*methods, i, member);
2156 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2157 mono_array_setref (*targets, i, member);
2164 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2166 MonoClass *klass = mono_class_from_mono_type (type->type);
2167 mono_class_init_or_throw (klass);
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);
2189 mono_class_init_or_throw (class);
2191 // GetElementType should only return a type for:
2192 // Array Pointer PassedByRef
2193 if (type->type->byref)
2194 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2195 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2196 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2197 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2198 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2203 static MonoReflectionType*
2204 ves_icall_get_type_parent (MonoReflectionType *type)
2206 MonoClass *class = mono_class_from_mono_type (type->type);
2207 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2211 ves_icall_type_ispointer (MonoReflectionType *type)
2213 MONO_ARCH_SAVE_REGS;
2215 return type->type->type == MONO_TYPE_PTR;
2219 ves_icall_type_isprimitive (MonoReflectionType *type)
2221 MONO_ARCH_SAVE_REGS;
2223 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)));
2227 ves_icall_type_isbyref (MonoReflectionType *type)
2229 MONO_ARCH_SAVE_REGS;
2231 return type->type->byref;
2235 ves_icall_type_iscomobject (MonoReflectionType *type)
2237 MonoClass *klass = mono_class_from_mono_type (type->type);
2238 mono_class_init_or_throw (klass);
2240 return (klass && klass->is_com_object);
2243 static MonoReflectionModule*
2244 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2246 MonoClass *class = mono_class_from_mono_type (type->type);
2247 return mono_module_get_object (mono_object_domain (type), class->image);
2250 static MonoReflectionAssembly*
2251 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2253 MonoDomain *domain = mono_domain_get ();
2254 MonoClass *class = mono_class_from_mono_type (type->type);
2255 return mono_assembly_get_object (domain, class->image->assembly);
2258 static MonoReflectionType*
2259 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2261 MonoDomain *domain = mono_domain_get ();
2264 MONO_ARCH_SAVE_REGS;
2266 if (type->type->byref)
2268 if (type->type->type == MONO_TYPE_VAR)
2269 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2270 else if (type->type->type == MONO_TYPE_MVAR)
2271 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2273 class = mono_class_from_mono_type (type->type)->nested_in;
2275 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2279 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2281 MonoDomain *domain = mono_domain_get ();
2282 MonoClass *class = mono_class_from_mono_type (type->type);
2284 if (type->type->byref) {
2285 char *n = g_strdup_printf ("%s&", class->name);
2286 MonoString *res = mono_string_new (domain, n);
2292 return mono_string_new (domain, class->name);
2297 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2299 MonoDomain *domain = mono_domain_get ();
2300 MonoClass *class = mono_class_from_mono_type (type->type);
2302 while (class->nested_in)
2303 class = class->nested_in;
2305 if (class->name_space [0] == '\0')
2308 return mono_string_new (domain, class->name_space);
2312 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2316 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2317 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2319 class = mono_class_from_mono_type (type->type);
2320 mono_class_init_or_throw (class);
2326 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2329 MonoClass *klass, *pklass;
2330 MonoDomain *domain = mono_object_domain (type);
2331 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2333 MONO_ARCH_SAVE_REGS;
2335 klass = mono_class_from_mono_type (type->type);
2336 mono_class_init_or_throw (klass);
2338 if (klass->generic_container) {
2339 MonoGenericContainer *container = klass->generic_container;
2340 res = mono_array_new_specific (array_vtable, container->type_argc);
2341 for (i = 0; i < container->type_argc; ++i) {
2342 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2343 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2345 } else if (klass->generic_class) {
2346 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2347 res = mono_array_new_specific (array_vtable, inst->type_argc);
2348 for (i = 0; i < inst->type_argc; ++i)
2349 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2351 res = mono_array_new_specific (array_vtable, 0);
2357 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2360 MONO_ARCH_SAVE_REGS;
2362 if (!IS_MONOTYPE (type))
2365 if (type->type->byref)
2368 klass = mono_class_from_mono_type (type->type);
2369 return klass->generic_container != NULL;
2372 static MonoReflectionType*
2373 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2376 MONO_ARCH_SAVE_REGS;
2378 if (type->type->byref)
2381 klass = mono_class_from_mono_type (type->type);
2382 mono_class_init_or_throw (klass);
2384 if (klass->generic_container) {
2385 return type; /* check this one */
2387 if (klass->generic_class) {
2388 MonoClass *generic_class = klass->generic_class->container_class;
2391 tb = mono_class_get_ref_info (generic_class);
2393 if (generic_class->wastypebuilder && tb)
2396 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2401 static MonoReflectionType*
2402 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2404 MonoType *geninst, **types;
2407 g_assert (IS_MONOTYPE (type));
2408 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2410 count = mono_array_length (type_array);
2411 types = g_new0 (MonoType *, count);
2413 for (i = 0; i < count; i++) {
2414 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2415 types [i] = t->type;
2418 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2423 return mono_type_get_object (mono_object_domain (type), geninst);
2427 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2430 MONO_ARCH_SAVE_REGS;
2432 if (type->type->byref)
2435 klass = mono_class_from_mono_type (type->type);
2437 return klass->generic_class != NULL;
2441 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2444 MONO_ARCH_SAVE_REGS;
2446 if (!IS_MONOTYPE (type))
2449 if (type->type->byref)
2452 klass = mono_class_from_mono_type (type->type);
2453 return klass->generic_class != NULL || klass->generic_container != NULL;
2457 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2459 MONO_ARCH_SAVE_REGS;
2461 if (!IS_MONOTYPE (type))
2464 if (is_generic_parameter (type->type))
2465 return mono_type_get_generic_param_num (type->type);
2469 static GenericParameterAttributes
2470 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2472 MONO_ARCH_SAVE_REGS;
2474 g_assert (IS_MONOTYPE (type));
2475 g_assert (is_generic_parameter (type->type));
2476 return mono_generic_param_info (type->type->data.generic_param)->flags;
2480 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2482 MonoGenericParamInfo *param_info;
2488 MONO_ARCH_SAVE_REGS;
2490 g_assert (IS_MONOTYPE (type));
2492 domain = mono_object_domain (type);
2493 param_info = mono_generic_param_info (type->type->data.generic_param);
2494 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2497 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2498 for (i = 0; i < count; i++)
2499 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2506 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2508 MONO_ARCH_SAVE_REGS;
2509 return is_generic_parameter (type->type);
2513 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2515 MONO_ARCH_SAVE_REGS;
2516 return is_generic_parameter (tb->type.type);
2520 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2521 MonoReflectionType *t)
2523 enumtype->type = t->type;
2526 static MonoReflectionMethod*
2527 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2528 MonoReflectionMethod* generic)
2535 MONO_ARCH_SAVE_REGS;
2537 domain = ((MonoObject *)type)->vtable->domain;
2539 klass = mono_class_from_mono_type (type->type);
2540 mono_class_init_or_throw (klass);
2543 while ((method = mono_class_get_methods (klass, &iter))) {
2544 if (method->token == generic->method->token)
2545 return mono_method_get_object (domain, method, klass);
2553 static MonoReflectionMethod *
2554 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2557 MonoType *type = ref_type->type;
2559 MONO_ARCH_SAVE_REGS;
2561 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2562 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2563 if (type->type == MONO_TYPE_VAR)
2566 method = mono_type_get_generic_param_owner (type)->owner.method;
2568 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2571 static MonoReflectionDllImportAttribute*
2572 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2574 static MonoClass *DllImportAttributeClass = NULL;
2575 MonoDomain *domain = mono_domain_get ();
2576 MonoReflectionDllImportAttribute *attr;
2577 MonoImage *image = method->klass->image;
2578 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2579 MonoTableInfo *tables = image->tables;
2580 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2581 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2582 guint32 im_cols [MONO_IMPLMAP_SIZE];
2583 guint32 scope_token;
2584 const char *import = NULL;
2585 const char *scope = NULL;
2588 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2591 if (!DllImportAttributeClass) {
2592 DllImportAttributeClass =
2593 mono_class_from_name (mono_defaults.corlib,
2594 "System.Runtime.InteropServices", "DllImportAttribute");
2595 g_assert (DllImportAttributeClass);
2598 if (method->klass->image->dynamic) {
2599 MonoReflectionMethodAux *method_aux =
2600 g_hash_table_lookup (
2601 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2603 import = method_aux->dllentry;
2604 scope = method_aux->dll;
2607 if (!import || !scope) {
2608 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2613 if (piinfo->implmap_idx) {
2614 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2616 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2617 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2618 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2619 scope = mono_metadata_string_heap (image, scope_token);
2622 flags = piinfo->piflags;
2624 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2626 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2627 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2628 attr->call_conv = (flags & 0x700) >> 8;
2629 attr->charset = ((flags & 0x6) >> 1) + 1;
2630 if (attr->charset == 1)
2632 attr->exact_spelling = (flags & 0x1) != 0;
2633 attr->set_last_error = (flags & 0x40) != 0;
2634 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2635 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2636 attr->preserve_sig = FALSE;
2641 static MonoReflectionMethod *
2642 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2644 MonoMethodInflated *imethod;
2647 MONO_ARCH_SAVE_REGS;
2649 if (method->method->is_generic)
2652 if (!method->method->is_inflated)
2655 imethod = (MonoMethodInflated *) method->method;
2657 result = imethod->declaring;
2658 /* Not a generic method. */
2659 if (!result->is_generic)
2662 if (method->method->klass->image->dynamic) {
2663 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2664 MonoReflectionMethod *res;
2667 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2668 * the dynamic case as well ?
2670 mono_loader_lock ();
2671 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2672 mono_loader_unlock ();
2678 if (imethod->context.class_inst) {
2679 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2680 /*Generic methods gets the context of the GTD.*/
2681 if (mono_class_get_context (klass))
2682 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2685 return mono_method_get_object (mono_object_domain (method), result, NULL);
2689 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2691 MONO_ARCH_SAVE_REGS;
2693 return mono_method_signature (method->method)->generic_param_count != 0;
2697 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2699 MONO_ARCH_SAVE_REGS;
2701 return method->method->is_generic;
2705 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2710 MONO_ARCH_SAVE_REGS;
2712 domain = mono_object_domain (method);
2714 if (method->method->is_inflated) {
2715 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2718 count = inst->type_argc;
2719 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2721 for (i = 0; i < count; i++)
2722 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2728 count = mono_method_signature (method->method)->generic_param_count;
2729 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2731 for (i = 0; i < count; i++) {
2732 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2733 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2734 MonoClass *pklass = mono_class_from_generic_parameter (
2735 param, method->method->klass->image, TRUE);
2736 mono_array_setref (res, i,
2737 mono_type_get_object (domain, &pklass->byval_arg));
2744 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2747 * Invoke from reflection is supposed to always be a virtual call (the API
2748 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2749 * greater flexibility.
2751 MonoMethod *m = method->method;
2755 MONO_ARCH_SAVE_REGS;
2759 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2760 mono_security_core_clr_ensure_reflection_access_method (m);
2762 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2763 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2764 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2769 if (!mono_object_isinst (this, m->klass)) {
2770 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2773 m = mono_object_get_virtual_method (this, m);
2774 /* must pass the pointer to the value for valuetype methods */
2775 if (m->klass->valuetype)
2776 obj = mono_object_unbox (this);
2777 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2778 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2783 pcount = params? mono_array_length (params): 0;
2784 if (pcount != mono_method_signature (m)->param_count) {
2785 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2789 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2790 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."));
2794 if (m->klass->image->assembly->ref_only) {
2795 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."));
2799 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2802 intptr_t *lower_bounds;
2803 pcount = mono_array_length (params);
2804 lengths = alloca (sizeof (uintptr_t) * pcount);
2805 /* Note: the synthetized array .ctors have int32 as argument type */
2806 for (i = 0; i < pcount; ++i)
2807 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2809 if (m->klass->rank == pcount) {
2810 /* Only lengths provided. */
2811 lower_bounds = NULL;
2813 g_assert (pcount == (m->klass->rank * 2));
2814 /* lower bounds are first. */
2815 lower_bounds = (intptr_t*)lengths;
2816 lengths += m->klass->rank;
2819 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2821 return mono_runtime_invoke_array (m, obj, params, NULL);
2825 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2827 MonoDomain *domain = mono_object_domain (method);
2828 MonoMethod *m = method->method;
2829 MonoMethodSignature *sig = mono_method_signature (m);
2830 MonoArray *out_args;
2832 int i, j, outarg_count = 0;
2834 MONO_ARCH_SAVE_REGS;
2836 if (m->klass == mono_defaults.object_class) {
2838 if (!strcmp (m->name, "FieldGetter")) {
2839 MonoClass *k = this->vtable->klass;
2843 /* If this is a proxy, then it must be a CBO */
2844 if (k == mono_defaults.transparent_proxy_class) {
2845 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2846 this = tp->rp->unwrapped_server;
2848 k = this->vtable->klass;
2851 name = mono_array_get (params, MonoString *, 1);
2852 str = mono_string_to_utf8 (name);
2855 MonoClassField* field = mono_class_get_field_from_name (k, str);
2857 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2858 if (field_klass->valuetype)
2859 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2861 result = *((gpointer *)((char *)this + field->offset));
2863 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2864 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2865 mono_array_setref (out_args, 0, result);
2873 g_assert_not_reached ();
2875 } else if (!strcmp (m->name, "FieldSetter")) {
2876 MonoClass *k = this->vtable->klass;
2882 /* If this is a proxy, then it must be a CBO */
2883 if (k == mono_defaults.transparent_proxy_class) {
2884 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2885 this = tp->rp->unwrapped_server;
2887 k = this->vtable->klass;
2890 name = mono_array_get (params, MonoString *, 1);
2891 str = mono_string_to_utf8 (name);
2894 MonoClassField* field = mono_class_get_field_from_name (k, str);
2896 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2897 MonoObject *val = mono_array_get (params, gpointer, 2);
2899 if (field_klass->valuetype) {
2900 size = mono_type_size (field->type, &align);
2901 g_assert (size == mono_class_value_size (field_klass, NULL));
2902 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2904 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2907 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2908 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2918 g_assert_not_reached ();
2923 for (i = 0; i < mono_array_length (params); i++) {
2924 if (sig->params [i]->byref)
2928 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2930 /* handle constructors only for objects already allocated */
2931 if (!strcmp (method->method->name, ".ctor"))
2934 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2935 g_assert (!method->method->klass->valuetype);
2936 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2938 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2939 if (sig->params [i]->byref) {
2941 arg = mono_array_get (params, gpointer, i);
2942 mono_array_setref (out_args, j, arg);
2947 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2953 read_enum_value (char *mem, int type)
2957 return *(guint8*)mem;
2959 return *(gint8*)mem;
2961 return *(guint16*)mem;
2963 return *(gint16*)mem;
2965 return *(guint32*)mem;
2967 return *(gint32*)mem;
2969 return *(guint64*)mem;
2971 return *(gint64*)mem;
2973 g_assert_not_reached ();
2979 write_enum_value (char *mem, int type, guint64 value)
2983 case MONO_TYPE_I1: {
2984 guint8 *p = (guint8*)mem;
2989 case MONO_TYPE_I2: {
2990 guint16 *p = (void*)mem;
2995 case MONO_TYPE_I4: {
2996 guint32 *p = (void*)mem;
3001 case MONO_TYPE_I8: {
3002 guint64 *p = (void*)mem;
3007 g_assert_not_reached ();
3013 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3016 MonoClass *enumc, *objc;
3021 MONO_ARCH_SAVE_REGS;
3023 MONO_CHECK_ARG_NULL (enumType);
3024 MONO_CHECK_ARG_NULL (value);
3026 domain = mono_object_domain (enumType);
3027 enumc = mono_class_from_mono_type (enumType->type);
3029 mono_class_init_or_throw (enumc);
3031 objc = value->vtable->klass;
3033 if (!enumc->enumtype)
3034 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3035 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3036 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."));
3038 etype = mono_class_enum_basetype (enumc);
3040 /* MS throws this for typebuilders */
3041 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3043 res = mono_object_new (domain, enumc);
3044 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3045 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3051 ves_icall_System_Enum_get_value (MonoObject *this)
3059 MONO_ARCH_SAVE_REGS;
3064 g_assert (this->vtable->klass->enumtype);
3066 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3067 res = mono_object_new (mono_object_domain (this), enumc);
3068 dst = (char *)res + sizeof (MonoObject);
3069 src = (char *)this + sizeof (MonoObject);
3070 size = mono_class_value_size (enumc, NULL);
3072 memcpy (dst, src, size);
3077 static MonoReflectionType *
3078 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3083 MONO_ARCH_SAVE_REGS;
3085 klass = mono_class_from_mono_type (type->type);
3086 mono_class_init_or_throw (klass);
3088 etype = mono_class_enum_basetype (klass);
3090 /* MS throws this for typebuilders */
3091 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3093 return mono_type_get_object (mono_object_domain (type), etype);
3097 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3099 gpointer tdata = (char *)this + sizeof (MonoObject);
3100 gpointer odata = (char *)other + sizeof (MonoObject);
3101 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3102 g_assert (basetype);
3104 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3105 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3106 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3109 return me > other ? 1 : -1; \
3112 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3113 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3114 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3117 return me - other; \
3120 switch (basetype->type) {
3122 COMPARE_ENUM_VALUES (guint8);
3124 COMPARE_ENUM_VALUES (gint8);
3125 case MONO_TYPE_CHAR:
3127 COMPARE_ENUM_VALUES_RANGE (guint16);
3129 COMPARE_ENUM_VALUES (gint16);
3131 COMPARE_ENUM_VALUES (guint32);
3133 COMPARE_ENUM_VALUES (gint32);
3135 COMPARE_ENUM_VALUES (guint64);
3137 COMPARE_ENUM_VALUES (gint64);
3139 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3141 #undef COMPARE_ENUM_VALUES_RANGE
3142 #undef COMPARE_ENUM_VALUES
3147 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3149 gpointer data = (char *)this + sizeof (MonoObject);
3150 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3151 g_assert (basetype);
3153 switch (basetype->type) {
3155 return *((gint8*)data);
3157 return *((guint8*)data);
3158 case MONO_TYPE_CHAR:
3160 return *((guint16*)data);
3163 return *((gint16*)data);
3165 return *((guint32*)data);
3167 return *((gint32*)data);
3169 case MONO_TYPE_I8: {
3170 gint64 value = *((gint64*)data);
3171 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3174 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3180 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3182 MonoDomain *domain = mono_object_domain (type);
3183 MonoClass *enumc = mono_class_from_mono_type (type->type);
3184 guint j = 0, nvalues, crow;
3186 MonoClassField *field;
3188 MONO_ARCH_SAVE_REGS;
3190 mono_class_init_or_throw (enumc);
3192 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3193 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3194 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3195 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3199 while ((field = mono_class_get_fields (enumc, &iter))) {
3202 MonoTypeEnum def_type;
3204 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3206 if (mono_field_is_deleted (field))
3208 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3210 p = mono_class_get_field_default_value (field, &def_type);
3211 len = mono_metadata_decode_blob_size (p, &p);
3212 switch (mono_class_enum_basetype (enumc)->type) {
3215 mono_array_set (info->values, gchar, j, *p);
3217 case MONO_TYPE_CHAR:
3220 mono_array_set (info->values, gint16, j, read16 (p));
3224 mono_array_set (info->values, gint32, j, read32 (p));
3228 mono_array_set (info->values, gint64, j, read64 (p));
3231 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3238 BFLAGS_IgnoreCase = 1,
3239 BFLAGS_DeclaredOnly = 2,
3240 BFLAGS_Instance = 4,
3242 BFLAGS_Public = 0x10,
3243 BFLAGS_NonPublic = 0x20,
3244 BFLAGS_FlattenHierarchy = 0x40,
3245 BFLAGS_InvokeMethod = 0x100,
3246 BFLAGS_CreateInstance = 0x200,
3247 BFLAGS_GetField = 0x400,
3248 BFLAGS_SetField = 0x800,
3249 BFLAGS_GetProperty = 0x1000,
3250 BFLAGS_SetProperty = 0x2000,
3251 BFLAGS_ExactBinding = 0x10000,
3252 BFLAGS_SuppressChangeType = 0x20000,
3253 BFLAGS_OptionalParamBinding = 0x40000
3256 static MonoReflectionField *
3257 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3260 MonoClass *startklass, *klass;
3262 MonoClassField *field;
3265 int (*compare_func) (const char *s1, const char *s2) = NULL;
3266 domain = ((MonoObject *)type)->vtable->domain;
3267 klass = startklass = mono_class_from_mono_type (type->type);
3268 mono_class_init_or_throw (klass);
3271 mono_raise_exception (mono_get_exception_argument_null ("name"));
3272 if (type->type->byref)
3275 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3278 if (klass->exception_type != MONO_EXCEPTION_NONE)
3279 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3282 while ((field = mono_class_get_fields (klass, &iter))) {
3285 if (field->type == NULL)
3287 if (mono_field_is_deleted (field))
3289 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3290 if (bflags & BFLAGS_Public)
3292 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3293 if (bflags & BFLAGS_NonPublic) {
3300 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3301 if (bflags & BFLAGS_Static)
3302 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3305 if (bflags & BFLAGS_Instance)
3312 utf8_name = mono_string_to_utf8 (name);
3314 if (compare_func (mono_field_get_name (field), utf8_name)) {
3320 return mono_field_get_object (domain, klass, field);
3322 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3329 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3332 MonoClass *startklass, *klass, *refklass;
3337 MonoClassField *field;
3338 MonoPtrArray tmp_array;
3340 MONO_ARCH_SAVE_REGS;
3342 domain = ((MonoObject *)type)->vtable->domain;
3343 if (type->type->byref)
3344 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3345 klass = startklass = mono_class_from_mono_type (type->type);
3346 refklass = mono_class_from_mono_type (reftype->type);
3348 mono_ptr_array_init (tmp_array, 2);
3351 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3352 mono_ptr_array_destroy (tmp_array);
3353 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3357 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3358 guint32 flags = mono_field_get_flags (field);
3360 if (mono_field_is_deleted_with_flags (field, flags))
3362 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3363 if (bflags & BFLAGS_Public)
3365 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3366 if (bflags & BFLAGS_NonPublic) {
3373 if (flags & FIELD_ATTRIBUTE_STATIC) {
3374 if (bflags & BFLAGS_Static)
3375 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3378 if (bflags & BFLAGS_Instance)
3384 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3385 mono_ptr_array_append (tmp_array, member);
3387 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3390 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3392 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3393 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3395 mono_ptr_array_destroy (tmp_array);
3401 method_nonpublic (MonoMethod* method, gboolean start_klass)
3403 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3404 case METHOD_ATTRIBUTE_ASSEM:
3405 return (start_klass || mono_defaults.generic_ilist_class);
3406 case METHOD_ATTRIBUTE_PRIVATE:
3408 case METHOD_ATTRIBUTE_PUBLIC:
3416 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3418 static MonoClass *MethodInfo_array;
3420 MonoClass *startklass, *klass, *refklass;
3425 int i, len, match, nslots;
3426 /*FIXME, use MonoBitSet*/
3427 guint32 method_slots_default [8];
3428 guint32 *method_slots = NULL;
3429 gchar *mname = NULL;
3430 int (*compare_func) (const char *s1, const char *s2) = NULL;
3431 MonoVTable *array_vtable;
3433 MonoPtrArray tmp_array;
3435 mono_ptr_array_init (tmp_array, 4);
3437 if (!MethodInfo_array) {
3438 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3439 mono_memory_barrier ();
3440 MethodInfo_array = klass;
3443 domain = ((MonoObject *)type)->vtable->domain;
3444 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3445 if (type->type->byref)
3446 return mono_array_new_specific (array_vtable, 0);
3447 klass = startklass = mono_class_from_mono_type (type->type);
3448 refklass = mono_class_from_mono_type (reftype->type);
3452 mname = mono_string_to_utf8 (name);
3453 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3456 /* An optimization for calls made from Delegate:CreateDelegate () */
3457 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3458 method = mono_get_delegate_invoke (klass);
3459 if (mono_loader_get_last_error ())
3462 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3464 res = mono_array_new_specific (array_vtable, 1);
3465 mono_array_setref (res, 0, member);
3470 mono_class_setup_vtable (klass);
3471 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3474 if (is_generic_parameter (type->type))
3475 nslots = mono_class_get_vtable_size (klass->parent);
3477 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3478 if (nslots >= sizeof (method_slots_default) * 8) {
3479 method_slots = g_new0 (guint32, nslots / 32 + 1);
3481 method_slots = method_slots_default;
3482 memset (method_slots, 0, sizeof (method_slots_default));
3485 mono_class_setup_vtable (klass);
3486 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3490 while ((method = mono_class_get_methods (klass, &iter))) {
3492 if (method->slot != -1) {
3493 g_assert (method->slot < nslots);
3494 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3496 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3497 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3500 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3502 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3503 if (bflags & BFLAGS_Public)
3505 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3511 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3512 if (bflags & BFLAGS_Static)
3513 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3516 if (bflags & BFLAGS_Instance)
3524 if (compare_func (mname, method->name))
3530 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3532 mono_ptr_array_append (tmp_array, member);
3534 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3538 if (method_slots != method_slots_default)
3539 g_free (method_slots);
3541 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3543 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3544 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3546 mono_ptr_array_destroy (tmp_array);
3551 if (method_slots != method_slots_default)
3552 g_free (method_slots);
3553 mono_ptr_array_destroy (tmp_array);
3554 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3555 ex = mono_class_get_exception_for_failure (klass);
3557 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3558 mono_loader_clear_error ();
3560 mono_raise_exception (ex);
3565 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3568 static MonoClass *System_Reflection_ConstructorInfo;
3569 MonoClass *startklass, *klass, *refklass;
3574 gpointer iter = NULL;
3575 MonoPtrArray tmp_array;
3577 MONO_ARCH_SAVE_REGS;
3579 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3581 domain = ((MonoObject *)type)->vtable->domain;
3582 if (type->type->byref)
3583 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3584 klass = startklass = mono_class_from_mono_type (type->type);
3585 refklass = mono_class_from_mono_type (reftype->type);
3587 if (!System_Reflection_ConstructorInfo)
3588 System_Reflection_ConstructorInfo = mono_class_from_name (
3589 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3592 while ((method = mono_class_get_methods (klass, &iter))) {
3594 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3596 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3597 if (bflags & BFLAGS_Public)
3600 if (bflags & BFLAGS_NonPublic)
3606 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3607 if (bflags & BFLAGS_Static)
3608 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3611 if (bflags & BFLAGS_Instance)
3617 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3619 mono_ptr_array_append (tmp_array, member);
3622 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3624 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3625 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3627 mono_ptr_array_destroy (tmp_array);
3633 property_hash (gconstpointer data)
3635 MonoProperty *prop = (MonoProperty*)data;
3637 return g_str_hash (prop->name);
3641 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3643 // Properties are hide-by-name-and-signature
3644 if (!g_str_equal (prop1->name, prop2->name))
3647 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3649 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3655 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3660 return method_nonpublic (accessor, start_klass);
3664 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3668 static MonoClass *System_Reflection_PropertyInfo;
3669 MonoClass *startklass, *klass;
3675 gchar *propname = NULL;
3676 int (*compare_func) (const char *s1, const char *s2) = NULL;
3678 GHashTable *properties = NULL;
3679 MonoPtrArray tmp_array;
3681 MONO_ARCH_SAVE_REGS;
3683 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3685 if (!System_Reflection_PropertyInfo)
3686 System_Reflection_PropertyInfo = mono_class_from_name (
3687 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3689 domain = ((MonoObject *)type)->vtable->domain;
3690 if (type->type->byref)
3691 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3692 klass = startklass = mono_class_from_mono_type (type->type);
3695 propname = mono_string_to_utf8 (name);
3696 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3699 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3701 mono_class_setup_vtable (klass);
3702 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3706 while ((prop = mono_class_get_properties (klass, &iter))) {
3712 flags = method->flags;
3715 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3716 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3717 if (bflags & BFLAGS_Public)
3719 } else if (bflags & BFLAGS_NonPublic) {
3720 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3721 property_accessor_nonpublic(prop->set, startklass == klass)) {
3728 if (flags & METHOD_ATTRIBUTE_STATIC) {
3729 if (bflags & BFLAGS_Static)
3730 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3733 if (bflags & BFLAGS_Instance)
3742 if (compare_func (propname, prop->name))
3746 if (g_hash_table_lookup (properties, prop))
3749 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3751 g_hash_table_insert (properties, prop, prop);
3753 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3756 g_hash_table_destroy (properties);
3759 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3760 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3761 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3763 mono_ptr_array_destroy (tmp_array);
3769 g_hash_table_destroy (properties);
3772 mono_ptr_array_destroy (tmp_array);
3774 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3775 ex = mono_class_get_exception_for_failure (klass);
3777 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3778 mono_loader_clear_error ();
3780 mono_raise_exception (ex);
3784 static MonoReflectionEvent *
3785 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3788 MonoClass *klass, *startklass;
3793 int (*compare_func) (const char *s1, const char *s2);
3795 MONO_ARCH_SAVE_REGS;
3797 event_name = mono_string_to_utf8 (name);
3798 if (type->type->byref)
3800 klass = startklass = mono_class_from_mono_type (type->type);
3801 domain = mono_object_domain (type);
3803 mono_class_init_or_throw (klass);
3805 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3807 if (klass->exception_type != MONO_EXCEPTION_NONE)
3808 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3811 while ((event = mono_class_get_events (klass, &iter))) {
3812 if (compare_func (event->name, event_name))
3815 method = event->add;
3817 method = event->remove;
3819 method = event->raise;
3821 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3822 if (!(bflags & BFLAGS_Public))
3825 if (!(bflags & BFLAGS_NonPublic))
3827 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3831 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3832 if (!(bflags & BFLAGS_Static))
3834 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3837 if (!(bflags & BFLAGS_Instance))
3841 if (!(bflags & BFLAGS_NonPublic))
3844 g_free (event_name);
3845 return mono_event_get_object (domain, startklass, event);
3848 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3851 g_free (event_name);
3856 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3860 static MonoClass *System_Reflection_EventInfo;
3861 MonoClass *startklass, *klass;
3868 MonoPtrArray tmp_array;
3870 MONO_ARCH_SAVE_REGS;
3872 mono_ptr_array_init (tmp_array, 4);
3874 if (!System_Reflection_EventInfo)
3875 System_Reflection_EventInfo = mono_class_from_name (
3876 mono_defaults.corlib, "System.Reflection", "EventInfo");
3878 domain = mono_object_domain (type);
3879 if (type->type->byref)
3880 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3881 klass = startklass = mono_class_from_mono_type (type->type);
3884 mono_class_setup_vtable (klass);
3885 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3889 while ((event = mono_class_get_events (klass, &iter))) {
3891 method = event->add;
3893 method = event->remove;
3895 method = event->raise;
3897 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3898 if (bflags & BFLAGS_Public)
3900 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3901 if (bflags & BFLAGS_NonPublic)
3906 if (bflags & BFLAGS_NonPublic)
3912 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3913 if (bflags & BFLAGS_Static)
3914 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3917 if (bflags & BFLAGS_Instance)
3922 if (bflags & BFLAGS_Instance)
3926 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3928 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3931 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3933 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3934 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3936 mono_ptr_array_destroy (tmp_array);
3941 mono_ptr_array_destroy (tmp_array);
3942 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3943 ex = mono_class_get_exception_for_failure (klass);
3945 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3946 mono_loader_clear_error ();
3948 mono_raise_exception (ex);
3952 static MonoReflectionType *
3953 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3961 MONO_ARCH_SAVE_REGS;
3964 mono_raise_exception (mono_get_exception_argument_null ("name"));
3966 domain = ((MonoObject *)type)->vtable->domain;
3967 if (type->type->byref)
3969 klass = mono_class_from_mono_type (type->type);
3971 str = mono_string_to_utf8 (name);
3974 if (klass->exception_type != MONO_EXCEPTION_NONE)
3975 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3978 * If a nested type is generic, return its generic type definition.
3979 * Note that this means that the return value is essentially a
3980 * nested type of the generic type definition of @klass.
3982 * A note in MSDN claims that a generic type definition can have
3983 * nested types that aren't generic. In any case, the container of that
3984 * nested type would be the generic type definition.
3986 if (klass->generic_class)
3987 klass = klass->generic_class->container_class;
3990 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3992 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3993 if (bflags & BFLAGS_Public)
3996 if (bflags & BFLAGS_NonPublic)
4001 if (strcmp (nested->name, str) == 0){
4003 return mono_type_get_object (domain, &nested->byval_arg);
4006 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4013 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4022 MonoPtrArray tmp_array;
4024 MONO_ARCH_SAVE_REGS;
4026 domain = ((MonoObject *)type)->vtable->domain;
4027 if (type->type->byref)
4028 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4029 klass = mono_class_from_mono_type (type->type);
4032 * If a nested type is generic, return its generic type definition.
4033 * Note that this means that the return value is essentially the set
4034 * of nested types of the generic type definition of @klass.
4036 * A note in MSDN claims that a generic type definition can have
4037 * nested types that aren't generic. In any case, the container of that
4038 * nested type would be the generic type definition.
4040 if (klass->generic_class)
4041 klass = klass->generic_class->container_class;
4043 mono_ptr_array_init (tmp_array, 1);
4045 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4047 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4048 if (bflags & BFLAGS_Public)
4051 if (bflags & BFLAGS_NonPublic)
4056 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4057 mono_ptr_array_append (tmp_array, member);
4060 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4062 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4063 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4065 mono_ptr_array_destroy (tmp_array);
4070 static MonoReflectionType*
4071 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4074 MonoType *type = NULL;
4075 MonoTypeNameParse info;
4076 gboolean type_resolve;
4078 MONO_ARCH_SAVE_REGS;
4080 /* On MS.NET, this does not fire a TypeResolve event */
4081 type_resolve = TRUE;
4082 str = mono_string_to_utf8 (name);
4083 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4084 if (!mono_reflection_parse_type (str, &info)) {
4086 mono_reflection_free_type_info (&info);
4087 if (throwOnError) /* uhm: this is a parse error, though... */
4088 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4089 /*g_print ("failed parse\n");*/
4093 if (info.assembly.name) {
4095 mono_reflection_free_type_info (&info);
4097 /* 1.0 and 2.0 throw different exceptions */
4098 if (mono_defaults.generic_ilist_class)
4099 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4101 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4106 if (module != NULL) {
4108 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4113 if (assembly->assembly->dynamic) {
4114 /* Enumerate all modules */
4115 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4119 if (abuilder->modules) {
4120 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4121 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4122 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4128 if (!type && abuilder->loaded_modules) {
4129 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4130 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4131 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4138 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4140 mono_reflection_free_type_info (&info);
4142 MonoException *e = NULL;
4145 e = mono_get_exception_type_load (name, NULL);
4147 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4148 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4150 mono_loader_clear_error ();
4153 mono_raise_exception (e);
4156 } else if (mono_loader_get_last_error ()) {
4158 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4159 mono_loader_clear_error ();
4162 if (type->type == MONO_TYPE_CLASS) {
4163 MonoClass *klass = mono_type_get_class (type);
4165 if (mono_is_security_manager_active () && !klass->exception_type)
4166 /* Some security problems are detected during generic vtable construction */
4167 mono_class_setup_vtable (klass);
4168 /* need to report exceptions ? */
4169 if (throwOnError && klass->exception_type) {
4170 /* report SecurityException (or others) that occured when loading the assembly */
4171 MonoException *exc = mono_class_get_exception_for_failure (klass);
4172 mono_loader_clear_error ();
4173 mono_raise_exception (exc);
4174 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4179 /* g_print ("got it\n"); */
4180 return mono_type_get_object (mono_object_domain (assembly), type);
4184 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4187 gchar *shadow_ini_file;
4190 /* Check for shadow-copied assembly */
4191 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4192 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4194 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4195 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4201 g_free (shadow_ini_file);
4202 if (content != NULL) {
4205 *filename = content;
4213 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4215 MonoDomain *domain = mono_object_domain (assembly);
4216 MonoAssembly *mass = assembly->assembly;
4217 MonoString *res = NULL;
4222 MONO_ARCH_SAVE_REGS;
4224 if (g_path_is_absolute (mass->image->name)) {
4225 absolute = g_strdup (mass->image->name);
4226 dirname = g_path_get_dirname (absolute);
4228 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4229 dirname = g_strdup (mass->basedir);
4232 replace_shadow_path (domain, dirname, &absolute);
4237 for (i = strlen (absolute) - 1; i >= 0; i--)
4238 if (absolute [i] == '\\')
4243 uri = g_filename_to_uri (absolute, NULL, NULL);
4245 const char *prepend = "file://";
4247 if (*absolute == '/' && *(absolute + 1) == '/') {
4250 prepend = "file:///";
4253 uri = g_strconcat (prepend, absolute, NULL);
4257 res = mono_string_new (domain, uri);
4265 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4267 MonoAssembly *mass = assembly->assembly;
4269 MONO_ARCH_SAVE_REGS;
4271 return mass->in_gac;
4274 static MonoReflectionAssembly*
4275 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4279 MonoImageOpenStatus status;
4281 MONO_ARCH_SAVE_REGS;
4283 name = mono_string_to_utf8 (mname);
4284 res = mono_assembly_load_with_partial_name (name, &status);
4290 return mono_assembly_get_object (mono_domain_get (), res);
4294 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4296 MonoDomain *domain = mono_object_domain (assembly);
4299 MONO_ARCH_SAVE_REGS;
4301 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4307 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4309 MONO_ARCH_SAVE_REGS;
4311 return assembly->assembly->ref_only;
4315 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4317 MonoDomain *domain = mono_object_domain (assembly);
4319 MONO_ARCH_SAVE_REGS;
4321 return mono_string_new (domain, assembly->assembly->image->version);
4324 static MonoReflectionMethod*
4325 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4327 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4329 MONO_ARCH_SAVE_REGS;
4333 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4336 static MonoReflectionModule*
4337 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4339 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4343 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4345 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4346 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4350 MONO_ARCH_SAVE_REGS;
4352 for (i = 0; i < table->rows; ++i) {
4353 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4354 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4360 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4362 static MonoClass *System_Version = NULL;
4363 static MonoMethod *create_version = NULL;
4367 if (!System_Version) {
4368 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4369 g_assert (System_Version);
4372 if (!create_version) {
4373 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4374 create_version = mono_method_desc_search_in_class (desc, System_Version);
4375 g_assert (create_version);
4376 mono_method_desc_free (desc);
4382 args [3] = &revision;
4383 result = mono_object_new (domain, System_Version);
4384 mono_runtime_invoke (create_version, result, args, NULL);
4390 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4392 static MonoClass *System_Reflection_AssemblyName;
4394 MonoDomain *domain = mono_object_domain (assembly);
4396 static MonoMethod *create_culture = NULL;
4397 MonoImage *image = assembly->assembly->image;
4400 MONO_ARCH_SAVE_REGS;
4402 if (!System_Reflection_AssemblyName)
4403 System_Reflection_AssemblyName = mono_class_from_name (
4404 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4406 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4409 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4411 if (count > 0 && !create_culture) {
4412 MonoMethodDesc *desc = mono_method_desc_new (
4413 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4414 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4415 g_assert (create_culture);
4416 mono_method_desc_free (desc);
4419 for (i = 0; i < count; i++) {
4420 MonoReflectionAssemblyName *aname;
4421 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4423 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4425 aname = (MonoReflectionAssemblyName *) mono_object_new (
4426 domain, System_Reflection_AssemblyName);
4428 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4430 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4431 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4432 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4433 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4434 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4435 aname->versioncompat = 1; /* SameMachine (default) */
4436 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4437 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4439 if (create_culture) {
4441 MonoBoolean assembly_ref = 1;
4442 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4443 args [1] = &assembly_ref;
4444 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4447 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4448 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4449 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4451 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4452 /* public key token isn't copied - the class library will
4453 automatically generate it from the public key if required */
4454 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4455 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4457 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4458 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4461 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4464 /* note: this function doesn't return the codebase on purpose (i.e. it can
4465 be used under partial trust as path information isn't present). */
4467 mono_array_setref (result, i, aname);
4478 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4480 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4482 mono_array_setref (info->res, info->idx, name);
4487 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4489 MonoImage *img = assembly->assembly->image;
4494 MONO_ARCH_SAVE_REGS;
4496 mono_image_lock (img);
4497 mono_image_init_name_cache (img);
4500 len = g_hash_table_size (img->name_cache);
4501 mono_image_unlock (img);
4503 /*we can't create objects holding the image lock */
4504 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4506 mono_image_lock (img);
4507 /*len might have changed, create a new array*/
4508 if (len != g_hash_table_size (img->name_cache))
4513 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4514 mono_image_unlock (img);
4519 /* move this in some file in mono/util/ */
4521 g_concat_dir_and_file (const char *dir, const char *file)
4523 g_return_val_if_fail (dir != NULL, NULL);
4524 g_return_val_if_fail (file != NULL, NULL);
4527 * If the directory name doesn't have a / on the end, we need
4528 * to add one so we get a proper path to the file
4530 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4531 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4533 return g_strconcat (dir, file, NULL);
4537 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4539 char *n = mono_string_to_utf8 (name);
4540 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4542 guint32 cols [MONO_MANIFEST_SIZE];
4543 guint32 impl, file_idx;
4547 MONO_ARCH_SAVE_REGS;
4549 for (i = 0; i < table->rows; ++i) {
4550 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4551 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4552 if (strcmp (val, n) == 0)
4556 if (i == table->rows)
4559 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4562 * this code should only be called after obtaining the
4563 * ResourceInfo and handling the other cases.
4565 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4566 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4568 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4573 module = assembly->assembly->image;
4575 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4577 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4581 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4583 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4585 guint32 cols [MONO_MANIFEST_SIZE];
4586 guint32 file_cols [MONO_FILE_SIZE];
4590 MONO_ARCH_SAVE_REGS;
4592 n = mono_string_to_utf8 (name);
4593 for (i = 0; i < table->rows; ++i) {
4594 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4595 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4596 if (strcmp (val, n) == 0)
4600 if (i == table->rows)
4603 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4604 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4607 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4608 case MONO_IMPLEMENTATION_FILE:
4609 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4610 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4611 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4612 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4613 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4614 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4617 info->location = RESOURCE_LOCATION_EMBEDDED;
4620 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4621 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4622 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4623 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4624 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4625 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4627 mono_raise_exception (ex);
4629 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4631 /* Obtain info recursively */
4632 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4633 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4636 case MONO_IMPLEMENTATION_EXP_TYPE:
4637 g_assert_not_reached ();
4646 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4648 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4649 MonoArray *result = NULL;
4654 MONO_ARCH_SAVE_REGS;
4656 /* check hash if needed */
4658 n = mono_string_to_utf8 (name);
4659 for (i = 0; i < table->rows; ++i) {
4660 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4661 if (strcmp (val, n) == 0) {
4664 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4665 fn = mono_string_new (mono_object_domain (assembly), n);
4667 return (MonoObject*)fn;
4675 for (i = 0; i < table->rows; ++i) {
4676 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4680 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4683 for (i = 0; i < table->rows; ++i) {
4684 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4685 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4686 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4687 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4692 return (MonoObject*)result;
4696 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4698 MonoDomain *domain = mono_domain_get();
4701 int i, j, file_count = 0;
4702 MonoImage **modules;
4703 guint32 module_count, real_module_count;
4704 MonoTableInfo *table;
4705 guint32 cols [MONO_FILE_SIZE];
4706 MonoImage *image = assembly->assembly->image;
4708 g_assert (image != NULL);
4709 g_assert (!assembly->assembly->dynamic);
4711 table = &image->tables [MONO_TABLE_FILE];
4712 file_count = table->rows;
4714 modules = image->modules;
4715 module_count = image->module_count;
4717 real_module_count = 0;
4718 for (i = 0; i < module_count; ++i)
4720 real_module_count ++;
4722 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4723 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4725 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4727 for (i = 0; i < module_count; ++i)
4729 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4733 for (i = 0; i < file_count; ++i, ++j) {
4734 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4735 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4736 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4738 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4740 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4741 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4743 mono_array_setref (res, j, mono_module_get_object (domain, m));
4750 static MonoReflectionMethod*
4751 ves_icall_GetCurrentMethod (void)
4753 MonoMethod *m = mono_method_get_last_managed ();
4755 while (m->is_inflated)
4756 m = ((MonoMethodInflated*)m)->declaring;
4758 return mono_method_get_object (mono_domain_get (), m, NULL);
4763 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4766 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4767 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4768 //method is inflated, we should inflate it on the other class
4769 MonoGenericContext ctx;
4770 ctx.method_inst = inflated->context.method_inst;
4771 ctx.class_inst = inflated->context.class_inst;
4772 if (klass->generic_class)
4773 ctx.class_inst = klass->generic_class->context.class_inst;
4774 else if (klass->generic_container)
4775 ctx.class_inst = klass->generic_container->context.class_inst;
4776 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4779 mono_class_setup_methods (method->klass);
4780 if (method->klass->exception_type)
4782 for (i = 0; i < method->klass->method.count; ++i) {
4783 if (method->klass->methods [i] == method) {
4788 mono_class_setup_methods (klass);
4789 if (klass->exception_type)
4791 g_assert (offset >= 0 && offset < klass->method.count);
4792 return klass->methods [offset];
4795 static MonoReflectionMethod*
4796 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4800 klass = mono_class_from_mono_type (type);
4801 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4803 if (method->klass != klass) {
4804 method = mono_method_get_equivalent_method (method, klass);
4809 klass = method->klass;
4810 return mono_method_get_object (mono_domain_get (), method, klass);
4813 static MonoReflectionMethod*
4814 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4816 return mono_method_get_object (mono_domain_get (), method, NULL);
4819 static MonoReflectionMethodBody*
4820 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4822 return mono_method_body_get_object (mono_domain_get (), method);
4825 static MonoReflectionAssembly*
4826 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4828 MonoMethod *dest = NULL;
4830 MONO_ARCH_SAVE_REGS;
4832 mono_stack_walk_no_il (get_executing, &dest);
4833 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4837 static MonoReflectionAssembly*
4838 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4840 MonoDomain* domain = mono_domain_get ();
4842 MONO_ARCH_SAVE_REGS;
4844 if (!domain->entry_assembly)
4847 return mono_assembly_get_object (domain, domain->entry_assembly);
4850 static MonoReflectionAssembly*
4851 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4856 MONO_ARCH_SAVE_REGS;
4859 mono_stack_walk_no_il (get_executing, &dest);
4861 mono_stack_walk_no_il (get_caller, &dest);
4864 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4868 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4869 gboolean assembly_qualified)
4871 MonoDomain *domain = mono_object_domain (object);
4872 MonoTypeNameFormat format;
4877 format = assembly_qualified ?
4878 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4879 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4881 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4883 name = mono_type_get_name_full (object->type, format);
4887 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4892 res = mono_string_new (domain, name);
4899 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4901 MonoClass *klass = mono_class_from_mono_type (this->type);
4902 mono_class_init_or_throw (klass);
4903 return mono_security_core_clr_class_level (klass);
4907 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4909 static MonoMethod *create_culture = NULL;
4912 const char *pkey_ptr;
4914 MonoBoolean assembly_ref = 0;
4916 MONO_ARCH_SAVE_REGS;
4918 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4919 aname->major = name->major;
4920 aname->minor = name->minor;
4921 aname->build = name->build;
4922 aname->flags = name->flags;
4923 aname->revision = name->revision;
4924 aname->hashalg = name->hash_alg;
4925 aname->versioncompat = 1; /* SameMachine (default) */
4927 if (by_default_version)
4928 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4931 if (absolute != NULL && *absolute != '\0') {
4932 const gchar *prepend = "file://";
4935 codebase = g_strdup (absolute);
4940 for (i = strlen (codebase) - 1; i >= 0; i--)
4941 if (codebase [i] == '\\')
4944 if (*codebase == '/' && *(codebase + 1) == '/') {
4947 prepend = "file:///";
4951 result = g_strconcat (prepend, codebase, NULL);
4957 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4961 if (!create_culture) {
4962 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4963 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4964 g_assert (create_culture);
4965 mono_method_desc_free (desc);
4968 if (name->culture) {
4969 args [0] = mono_string_new (domain, name->culture);
4970 args [1] = &assembly_ref;
4971 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4974 if (name->public_key) {
4975 pkey_ptr = (char*)name->public_key;
4976 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4978 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4979 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4980 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4981 } else if (default_publickey) {
4982 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4983 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4986 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4987 if (name->public_key_token [0]) {
4991 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4992 p = mono_array_addr (aname->keyToken, char, 0);
4994 for (i = 0, j = 0; i < 8; i++) {
4995 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4996 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4999 } else if (default_token) {
5000 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5005 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5007 MonoDomain *domain = mono_object_domain (assembly);
5008 MonoAssembly *mass = assembly->assembly;
5012 name = g_strdup_printf (
5013 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5015 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5016 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5017 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5018 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5020 res = mono_string_new (domain, name);
5027 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5030 MonoAssembly *mass = assembly->assembly;
5032 MONO_ARCH_SAVE_REGS;
5034 if (g_path_is_absolute (mass->image->name)) {
5035 fill_reflection_assembly_name (mono_object_domain (assembly),
5036 aname, &mass->aname, mass->image->name, TRUE,
5040 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5042 fill_reflection_assembly_name (mono_object_domain (assembly),
5043 aname, &mass->aname, absolute, TRUE, TRUE,
5050 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5053 MonoImageOpenStatus status = MONO_IMAGE_OK;
5056 MonoAssemblyName name;
5059 MONO_ARCH_SAVE_REGS;
5061 filename = mono_string_to_utf8 (fname);
5063 dirname = g_path_get_dirname (filename);
5064 replace_shadow_path (mono_domain_get (), dirname, &filename);
5067 image = mono_image_open (filename, &status);
5073 if (status == MONO_IMAGE_IMAGE_INVALID)
5074 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5076 exc = mono_get_exception_file_not_found2 (NULL, fname);
5077 mono_raise_exception (exc);
5080 res = mono_assembly_fill_assembly_name (image, &name);
5082 mono_image_close (image);
5084 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5087 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5091 mono_image_close (image);
5095 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5096 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5098 MonoBoolean result = FALSE;
5099 MonoDeclSecurityEntry entry;
5101 /* SecurityAction.RequestMinimum */
5102 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5103 *minimum = entry.blob;
5104 *minLength = entry.size;
5107 /* SecurityAction.RequestOptional */
5108 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5109 *optional = entry.blob;
5110 *optLength = entry.size;
5113 /* SecurityAction.RequestRefuse */
5114 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5115 *refused = entry.blob;
5116 *refLength = entry.size;
5124 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5128 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5130 guint32 attrs, visibility;
5132 /* we start the count from 1 because we skip the special type <Module> */
5135 for (i = 1; i < tdef->rows; ++i) {
5136 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5137 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5138 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5142 count = tdef->rows - 1;
5144 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5145 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5147 for (i = 1; i < tdef->rows; ++i) {
5148 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5149 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5150 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5151 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5153 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5155 MonoLoaderError *error;
5158 error = mono_loader_get_last_error ();
5159 g_assert (error != NULL);
5161 ex = mono_loader_error_prepare_exception (error);
5162 mono_array_setref (*exceptions, count, ex);
5164 if (mono_loader_get_last_error ())
5165 mono_loader_clear_error ();
5174 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5176 MonoArray *res = NULL;
5177 MonoArray *exceptions = NULL;
5178 MonoImage *image = NULL;
5179 MonoTableInfo *table = NULL;
5182 int i, len, ex_count;
5184 MONO_ARCH_SAVE_REGS;
5186 domain = mono_object_domain (assembly);
5188 g_assert (!assembly->assembly->dynamic);
5189 image = assembly->assembly->image;
5190 table = &image->tables [MONO_TABLE_FILE];
5191 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5193 /* Append data from all modules in the assembly */
5194 for (i = 0; i < table->rows; ++i) {
5195 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5196 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5199 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5200 /* Append the new types to the end of the array */
5201 if (mono_array_length (res2) > 0) {
5203 MonoArray *res3, *ex3;
5205 len1 = mono_array_length (res);
5206 len2 = mono_array_length (res2);
5208 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5209 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5210 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5213 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5214 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5215 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5222 /* the ReflectionTypeLoadException must have all the types (Types property),
5223 * NULL replacing types which throws an exception. The LoaderException must
5224 * contain all exceptions for NULL items.
5227 len = mono_array_length (res);
5230 for (i = 0; i < len; i++) {
5231 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5235 klass = mono_type_get_class (t->type);
5236 if ((klass != NULL) && klass->exception_type) {
5237 /* keep the class in the list */
5238 list = g_list_append (list, klass);
5239 /* and replace Type with NULL */
5240 mono_array_setref (res, i, NULL);
5247 if (list || ex_count) {
5249 MonoException *exc = NULL;
5250 MonoArray *exl = NULL;
5251 int j, length = g_list_length (list) + ex_count;
5253 mono_loader_clear_error ();
5255 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5256 /* Types for which mono_class_get () succeeded */
5257 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5258 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5259 mono_array_setref (exl, i, exc);
5261 /* Types for which it don't */
5262 for (j = 0; j < mono_array_length (exceptions); ++j) {
5263 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5265 g_assert (i < length);
5266 mono_array_setref (exl, i, exc);
5273 exc = mono_get_exception_reflection_type_load (res, exl);
5274 mono_loader_clear_error ();
5275 mono_raise_exception (exc);
5282 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5284 MonoAssemblyName aname;
5285 MonoDomain *domain = mono_object_domain (name);
5287 gboolean is_version_defined;
5288 gboolean is_token_defined;
5290 aname.public_key = NULL;
5291 val = mono_string_to_utf8 (assname);
5292 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5293 g_free ((guint8*) aname.public_key);
5298 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5299 FALSE, is_token_defined);
5301 mono_assembly_name_free (&aname);
5302 g_free ((guint8*) aname.public_key);
5308 static MonoReflectionType*
5309 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5311 MonoDomain *domain = mono_object_domain (module);
5314 MONO_ARCH_SAVE_REGS;
5316 g_assert (module->image);
5318 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5319 /* These images do not have a global type */
5322 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5323 return mono_type_get_object (domain, &klass->byval_arg);
5327 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5329 /*if (module->image)
5330 mono_image_close (module->image);*/
5334 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5336 MonoDomain *domain = mono_object_domain (module);
5338 MONO_ARCH_SAVE_REGS;
5340 g_assert (module->image);
5341 return mono_string_new (domain, module->image->guid);
5345 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5348 if (module->image && module->image->is_module_handle)
5349 return module->image->raw_data;
5352 return (gpointer) (-1);
5356 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5358 if (image->dynamic) {
5359 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5360 *pe_kind = dyn->pe_kind;
5361 *machine = dyn->machine;
5364 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5365 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5370 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5372 return (image->md_version_major << 16) | (image->md_version_minor);
5376 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5378 MonoArray *exceptions;
5381 MONO_ARCH_SAVE_REGS;
5384 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5386 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5387 for (i = 0; i < mono_array_length (exceptions); ++i) {
5388 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5390 mono_raise_exception (ex);
5397 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5399 guint32 cols [MONO_MEMBERREF_SIZE];
5401 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5402 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5403 mono_metadata_decode_blob_size (sig, &sig);
5404 return (*sig != 0x6);
5408 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5411 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5412 mono_array_addr (type_args, MonoType*, 0));
5414 context->class_inst = NULL;
5416 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5417 mono_array_addr (method_args, MonoType*, 0));
5419 context->method_inst = NULL;
5423 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5426 int table = mono_metadata_token_table (token);
5427 int index = mono_metadata_token_index (token);
5428 MonoGenericContext context;
5430 *error = ResolveTokenError_Other;
5432 /* Validate token */
5433 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5434 (table != MONO_TABLE_TYPESPEC)) {
5435 *error = ResolveTokenError_BadTable;
5439 if (image->dynamic) {
5440 if (type_args || method_args)
5441 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5442 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5445 return &klass->byval_arg;
5448 if ((index <= 0) || (index > image->tables [table].rows)) {
5449 *error = ResolveTokenError_OutOfRange;
5453 init_generic_context_from_args (&context, type_args, method_args);
5454 klass = mono_class_get_full (image, token, &context);
5456 if (mono_loader_get_last_error ())
5457 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5460 return &klass->byval_arg;
5466 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5468 int table = mono_metadata_token_table (token);
5469 int index = mono_metadata_token_index (token);
5470 MonoGenericContext context;
5473 *error = ResolveTokenError_Other;
5475 /* Validate token */
5476 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5477 (table != MONO_TABLE_MEMBERREF)) {
5478 *error = ResolveTokenError_BadTable;
5482 if (image->dynamic) {
5483 if (type_args || method_args)
5484 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5485 /* FIXME: validate memberref token type */
5486 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5489 if ((index <= 0) || (index > image->tables [table].rows)) {
5490 *error = ResolveTokenError_OutOfRange;
5493 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5494 *error = ResolveTokenError_BadTable;
5498 init_generic_context_from_args (&context, type_args, method_args);
5499 method = mono_get_method_full (image, token, NULL, &context);
5501 if (mono_loader_get_last_error ())
5502 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5508 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5510 int index = mono_metadata_token_index (token);
5512 *error = ResolveTokenError_Other;
5514 /* Validate token */
5515 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5516 *error = ResolveTokenError_BadTable;
5521 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5523 if ((index <= 0) || (index >= image->heap_us.size)) {
5524 *error = ResolveTokenError_OutOfRange;
5528 /* FIXME: What to do if the index points into the middle of a string ? */
5530 return mono_ldstr (mono_domain_get (), image, index);
5533 static MonoClassField*
5534 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5537 int table = mono_metadata_token_table (token);
5538 int index = mono_metadata_token_index (token);
5539 MonoGenericContext context;
5540 MonoClassField *field;
5542 *error = ResolveTokenError_Other;
5544 /* Validate token */
5545 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5546 *error = ResolveTokenError_BadTable;
5550 if (image->dynamic) {
5551 if (type_args || method_args)
5552 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5553 /* FIXME: validate memberref token type */
5554 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5557 if ((index <= 0) || (index > image->tables [table].rows)) {
5558 *error = ResolveTokenError_OutOfRange;
5561 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5562 *error = ResolveTokenError_BadTable;
5566 init_generic_context_from_args (&context, type_args, method_args);
5567 field = mono_field_from_token (image, token, &klass, &context);
5569 if (mono_loader_get_last_error ())
5570 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5577 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5579 int table = mono_metadata_token_table (token);
5581 *error = ResolveTokenError_Other;
5584 case MONO_TABLE_TYPEDEF:
5585 case MONO_TABLE_TYPEREF:
5586 case MONO_TABLE_TYPESPEC: {
5587 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5589 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5593 case MONO_TABLE_METHOD:
5594 case MONO_TABLE_METHODSPEC: {
5595 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5597 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5601 case MONO_TABLE_FIELD: {
5602 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5604 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5608 case MONO_TABLE_MEMBERREF:
5609 if (mono_metadata_memberref_is_method (image, token)) {
5610 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5612 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5617 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5619 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5626 *error = ResolveTokenError_BadTable;
5633 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5635 int table = mono_metadata_token_table (token);
5636 int idx = mono_metadata_token_index (token);
5637 MonoTableInfo *tables = image->tables;
5642 *error = ResolveTokenError_OutOfRange;
5644 /* FIXME: Support other tables ? */
5645 if (table != MONO_TABLE_STANDALONESIG)
5651 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5654 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5656 ptr = mono_metadata_blob_heap (image, sig);
5657 len = mono_metadata_decode_blob_size (ptr, &ptr);
5659 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5660 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5664 static MonoReflectionType*
5665 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5668 int isbyref = 0, rank;
5669 char *str = mono_string_to_utf8 (smodifiers);
5672 MONO_ARCH_SAVE_REGS;
5674 klass = mono_class_from_mono_type (tb->type.type);
5676 /* logic taken from mono_reflection_parse_type(): keep in sync */
5680 if (isbyref) { /* only one level allowed by the spec */
5687 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5690 klass = mono_ptr_class_get (&klass->byval_arg);
5691 mono_class_init (klass);
5702 else if (*p != '*') { /* '*' means unknown lower bound */
5713 klass = mono_array_class_get (klass, rank);
5714 mono_class_init (klass);
5721 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5725 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5730 MONO_ARCH_SAVE_REGS;
5733 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5739 check_for_invalid_type (MonoClass *klass)
5743 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5746 name = mono_type_get_full_name (klass);
5747 str = mono_string_new (mono_domain_get (), name);
5749 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5752 static MonoReflectionType *
5753 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5755 MonoClass *klass, *aklass;
5757 MONO_ARCH_SAVE_REGS;
5759 klass = mono_class_from_mono_type (type->type);
5760 mono_class_init_or_throw (klass);
5761 check_for_invalid_type (klass);
5763 if (rank == 0) //single dimentional array
5764 aklass = mono_array_class_get (klass, 1);
5766 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5768 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5771 static MonoReflectionType *
5772 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5776 MONO_ARCH_SAVE_REGS;
5778 klass = mono_class_from_mono_type (type->type);
5779 mono_class_init_or_throw (klass);
5780 check_for_invalid_type (klass);
5782 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5785 static MonoReflectionType *
5786 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5788 MonoClass *klass, *pklass;
5790 klass = mono_class_from_mono_type (type->type);
5791 mono_class_init_or_throw (klass);
5792 check_for_invalid_type (klass);
5794 pklass = mono_ptr_class_get (type->type);
5796 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5800 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5801 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5803 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5804 MonoObject *delegate;
5806 MonoMethod *method = info->method;
5808 MONO_ARCH_SAVE_REGS;
5810 mono_class_init_or_throw (delegate_class);
5812 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5814 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5815 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5819 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5821 if (method->dynamic) {
5822 /* Creating a trampoline would leak memory */
5823 func = mono_compile_method (method);
5825 func = mono_create_ftnptr (mono_domain_get (),
5826 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5829 mono_delegate_ctor_with_method (delegate, target, func, method);
5835 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5837 /* Reset the invoke impl to the default one */
5838 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5842 * Magic number to convert a time which is relative to
5843 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5845 #define EPOCH_ADJUST ((guint64)62135596800LL)
5848 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5850 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5853 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5855 convert_to_absolute_date(SYSTEMTIME *date)
5857 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5858 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5859 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5860 /* from the calendar FAQ */
5861 int a = (14 - date->wMonth) / 12;
5862 int y = date->wYear - a;
5863 int m = date->wMonth + 12 * a - 2;
5864 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5866 /* d is now the day of the week for the first of the month (0 == Sunday) */
5868 int day_of_week = date->wDayOfWeek;
5870 /* set day_in_month to the first day in the month which falls on day_of_week */
5871 int day_in_month = 1 + (day_of_week - d);
5872 if (day_in_month <= 0)
5875 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5876 date->wDay = day_in_month + (date->wDay - 1) * 7;
5877 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5884 * Return's the offset from GMT of a local time.
5886 * tm is a local time
5887 * t is the same local time as seconds.
5890 gmt_offset(struct tm *tm, time_t t)
5892 #if defined (HAVE_TM_GMTOFF)
5893 return tm->tm_gmtoff;
5898 g.tm_isdst = tm->tm_isdst;
5900 return (int)difftime(t, t2);
5905 * This is heavily based on zdump.c from glibc 2.2.
5907 * * data[0]: start of daylight saving time (in DateTime ticks).
5908 * * data[1]: end of daylight saving time (in DateTime ticks).
5909 * * data[2]: utcoffset (in TimeSpan ticks).
5910 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5911 * * name[0]: name of this timezone when not daylight saving.
5912 * * name[1]: name of this timezone when daylight saving.
5914 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5915 * the class library allows years between 1 and 9999.
5917 * Returns true on success and zero on failure.
5920 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5923 MonoDomain *domain = mono_domain_get ();
5924 struct tm start, tt;
5928 int is_daylight = 0, day;
5931 MONO_ARCH_SAVE_REGS;
5933 MONO_CHECK_ARG_NULL (data);
5934 MONO_CHECK_ARG_NULL (names);
5936 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5937 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5940 * no info is better than crashing: we'll need our own tz data
5941 * to make this work properly, anyway. The range is probably
5942 * reduced to 1970 .. 2037 because that is what mktime is
5943 * guaranteed to support (we get into an infinite loop
5947 memset (&start, 0, sizeof (start));
5950 start.tm_year = year-1900;
5952 t = mktime (&start);
5954 if ((year < 1970) || (year > 2037) || (t == -1)) {
5956 tt = *localtime (&t);
5957 strftime (tzone, sizeof (tzone), "%Z", &tt);
5958 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5959 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5963 gmtoff = gmt_offset (&start, t);
5965 /* For each day of the year, calculate the tm_gmtoff. */
5966 for (day = 0; day < 365; day++) {
5969 tt = *localtime (&t);
5971 /* Daylight saving starts or ends here. */
5972 if (gmt_offset (&tt, t) != gmtoff) {
5976 /* Try to find the exact hour when daylight saving starts/ends. */
5980 tt1 = *localtime (&t1);
5981 } while (gmt_offset (&tt1, t1) != gmtoff);
5983 /* Try to find the exact minute when daylight saving starts/ends. */
5986 tt1 = *localtime (&t1);
5987 } while (gmt_offset (&tt1, t1) == gmtoff);
5989 strftime (tzone, sizeof (tzone), "%Z", &tt);
5991 /* Write data, if we're already in daylight saving, we're done. */
5993 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5994 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5997 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5998 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6002 /* This is only set once when we enter daylight saving. */
6003 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6004 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6006 gmtoff = gmt_offset (&tt, t);
6011 strftime (tzone, sizeof (tzone), "%Z", &tt);
6012 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6013 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6014 mono_array_set ((*data), gint64, 0, 0);
6015 mono_array_set ((*data), gint64, 1, 0);
6016 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6017 mono_array_set ((*data), gint64, 3, 0);
6022 MonoDomain *domain = mono_domain_get ();
6023 TIME_ZONE_INFORMATION tz_info;
6028 tz_id = GetTimeZoneInformation (&tz_info);
6029 if (tz_id == TIME_ZONE_ID_INVALID)
6032 MONO_CHECK_ARG_NULL (data);
6033 MONO_CHECK_ARG_NULL (names);
6035 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6036 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6038 for (i = 0; i < 32; ++i)
6039 if (!tz_info.DaylightName [i])
6041 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6042 for (i = 0; i < 32; ++i)
6043 if (!tz_info.StandardName [i])
6045 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6047 if ((year <= 1601) || (year > 30827)) {
6049 * According to MSDN, the MS time functions can't handle dates outside
6055 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6056 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6057 tz_info.StandardDate.wYear = year;
6058 convert_to_absolute_date(&tz_info.StandardDate);
6059 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6064 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6065 tz_info.DaylightDate.wYear = year;
6066 convert_to_absolute_date(&tz_info.DaylightDate);
6067 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6072 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6074 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6075 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6082 ves_icall_System_Object_obj_address (MonoObject *this)
6084 MONO_ARCH_SAVE_REGS;
6091 static inline gint32
6092 mono_array_get_byte_length (MonoArray *array)
6098 klass = array->obj.vtable->klass;
6100 if (array->bounds == NULL)
6101 length = array->max_length;
6104 for (i = 0; i < klass->rank; ++ i)
6105 length *= array->bounds [i].length;
6108 switch (klass->element_class->byval_arg.type) {
6111 case MONO_TYPE_BOOLEAN:
6115 case MONO_TYPE_CHAR:
6123 return length * sizeof (gpointer);
6134 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6136 MONO_ARCH_SAVE_REGS;
6138 return mono_array_get_byte_length (array);
6142 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6144 MONO_ARCH_SAVE_REGS;
6146 return mono_array_get (array, gint8, idx);
6150 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6152 MONO_ARCH_SAVE_REGS;
6154 mono_array_set (array, gint8, idx, value);
6158 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6160 guint8 *src_buf, *dest_buf;
6162 MONO_ARCH_SAVE_REGS;
6164 /* watch out for integer overflow */
6165 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6168 src_buf = (guint8 *)src->vector + src_offset;
6169 dest_buf = (guint8 *)dest->vector + dest_offset;
6172 memcpy (dest_buf, src_buf, count);
6174 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6180 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6182 MonoDomain *domain = mono_object_domain (this);
6184 MonoRealProxy *rp = ((MonoRealProxy *)this);
6185 MonoTransparentProxy *tp;
6189 MONO_ARCH_SAVE_REGS;
6191 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6192 tp = (MonoTransparentProxy*) res;
6194 MONO_OBJECT_SETREF (tp, rp, rp);
6195 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6196 klass = mono_class_from_mono_type (type);
6198 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6199 tp->remote_class = mono_remote_class (domain, class_name, klass);
6201 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6205 static MonoReflectionType *
6206 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6208 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6211 /* System.Environment */
6214 ves_icall_System_Environment_get_UserName (void)
6216 MONO_ARCH_SAVE_REGS;
6218 /* using glib is more portable */
6219 return mono_string_new (mono_domain_get (), g_get_user_name ());
6224 ves_icall_System_Environment_get_MachineName (void)
6226 #if defined (HOST_WIN32)
6231 len = MAX_COMPUTERNAME_LENGTH + 1;
6232 buf = g_new (gunichar2, len);
6235 if (GetComputerName (buf, (PDWORD) &len))
6236 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6240 #elif !defined(DISABLE_SOCKETS)
6244 if (gethostname (buf, sizeof (buf)) == 0)
6245 result = mono_string_new (mono_domain_get (), buf);
6251 return mono_string_new (mono_domain_get (), "mono");
6256 ves_icall_System_Environment_get_Platform (void)
6258 #if defined (TARGET_WIN32)
6261 #elif defined(__MACH__)
6264 // For compatibility with our client code, this will be 4 for a while.
6265 // We will eventually move to 6 to match .NET, but it requires all client
6266 // code to be updated and the documentation everywhere to be updated
6277 ves_icall_System_Environment_get_NewLine (void)
6279 MONO_ARCH_SAVE_REGS;
6281 #if defined (HOST_WIN32)
6282 return mono_string_new (mono_domain_get (), "\r\n");
6284 return mono_string_new (mono_domain_get (), "\n");
6289 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6294 MONO_ARCH_SAVE_REGS;
6299 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6300 value = g_getenv (utf8_name);
6307 return mono_string_new (mono_domain_get (), value);
6311 * There is no standard way to get at environ.
6314 #ifndef __MINGW32_VERSION
6315 #if defined(__APPLE__) && !defined (__arm__)
6316 /* Apple defines this in crt_externs.h but doesn't provide that header for
6317 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6318 * in fact exist on all implementations (so far)
6320 gchar ***_NSGetEnviron(void);
6321 #define environ (*_NSGetEnviron())
6330 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6341 env_strings = GetEnvironmentStrings();
6344 env_string = env_strings;
6345 while (*env_string != '\0') {
6346 /* weird case that MS seems to skip */
6347 if (*env_string != '=')
6349 while (*env_string != '\0')
6355 domain = mono_domain_get ();
6356 names = mono_array_new (domain, mono_defaults.string_class, n);
6360 env_string = env_strings;
6361 while (*env_string != '\0') {
6362 /* weird case that MS seems to skip */
6363 if (*env_string != '=') {
6364 equal_str = wcschr(env_string, '=');
6365 g_assert(equal_str);
6366 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6367 mono_array_setref (names, n, str);
6370 while (*env_string != '\0')
6375 FreeEnvironmentStrings (env_strings);
6387 MONO_ARCH_SAVE_REGS;
6390 for (e = environ; *e != 0; ++ e)
6393 domain = mono_domain_get ();
6394 names = mono_array_new (domain, mono_defaults.string_class, n);
6397 for (e = environ; *e != 0; ++ e) {
6398 parts = g_strsplit (*e, "=", 2);
6400 str = mono_string_new (domain, *parts);
6401 mono_array_setref (names, n, str);
6414 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6416 #if !GLIB_CHECK_VERSION(2,4,0)
6417 #define g_setenv(a,b,c) setenv(a,b,c)
6418 #define g_unsetenv(a) unsetenv(a)
6422 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6427 gunichar2 *utf16_name, *utf16_value;
6429 gchar *utf8_name, *utf8_value;
6432 MONO_ARCH_SAVE_REGS;
6435 utf16_name = mono_string_to_utf16 (name);
6436 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6437 SetEnvironmentVariable (utf16_name, NULL);
6438 g_free (utf16_name);
6442 utf16_value = mono_string_to_utf16 (value);
6444 SetEnvironmentVariable (utf16_name, utf16_value);
6446 g_free (utf16_name);
6447 g_free (utf16_value);
6449 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6451 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6452 g_unsetenv (utf8_name);
6457 utf8_value = mono_string_to_utf8_checked (value, &error);
6458 if (!mono_error_ok (&error)) {
6460 mono_error_raise_exception (&error);
6462 g_setenv (utf8_name, utf8_value, TRUE);
6465 g_free (utf8_value);
6470 ves_icall_System_Environment_Exit (int result)
6472 MONO_ARCH_SAVE_REGS;
6474 mono_threads_set_shutting_down ();
6476 mono_runtime_set_shutting_down ();
6478 /* This will kill the tp threads which cannot be suspended */
6479 mono_thread_pool_cleanup ();
6481 /* Suspend all managed threads since the runtime is going away */
6482 mono_thread_suspend_all_other_threads ();
6484 mono_runtime_quit ();
6486 /* we may need to do some cleanup here... */
6491 ves_icall_System_Environment_GetGacPath (void)
6493 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6497 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6499 #if defined (HOST_WIN32)
6500 #ifndef CSIDL_FLAG_CREATE
6501 #define CSIDL_FLAG_CREATE 0x8000
6504 WCHAR path [MAX_PATH];
6505 /* Create directory if no existing */
6506 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6510 return mono_string_new_utf16 (mono_domain_get (), path, len);
6513 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6515 return mono_string_new (mono_domain_get (), "");
6519 ves_icall_System_Environment_GetLogicalDrives (void)
6521 gunichar2 buf [128], *ptr, *dname;
6523 guint initial_size = 127, size = 128;
6526 MonoString *drivestr;
6527 MonoDomain *domain = mono_domain_get ();
6530 MONO_ARCH_SAVE_REGS;
6535 while (size > initial_size) {
6536 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6537 if (size > initial_size) {
6540 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6541 initial_size = size;
6555 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6560 while (*u16) { u16++; len ++; }
6561 drivestr = mono_string_new_utf16 (domain, dname, len);
6562 mono_array_setref (result, ndrives++, drivestr);
6573 ves_icall_System_Environment_InternalGetHome (void)
6575 MONO_ARCH_SAVE_REGS;
6577 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6580 static const char *encodings [] = {
6582 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6583 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6584 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6586 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6587 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6588 "x_unicode_2_0_utf_7",
6590 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6591 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6593 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6596 "unicodefffe", "utf_16be",
6603 * Returns the internal codepage, if the value of "int_code_page" is
6604 * 1 at entry, and we can not compute a suitable code page number,
6605 * returns the code page as a string
6608 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6613 char *codepage = NULL;
6615 int want_name = *int_code_page;
6618 *int_code_page = -1;
6619 MONO_ARCH_SAVE_REGS;
6621 g_get_charset (&cset);
6622 c = codepage = strdup (cset);
6623 for (c = codepage; *c; c++){
6624 if (isascii (*c) && isalpha (*c))
6629 /* g_print ("charset: %s\n", cset); */
6631 /* handle some common aliases */
6634 for (i = 0; p != 0; ){
6635 if ((gssize) p < 7){
6637 p = encodings [++i];
6640 if (strcmp (p, codepage) == 0){
6641 *int_code_page = code;
6644 p = encodings [++i];
6647 if (strstr (codepage, "utf_8") != NULL)
6648 *int_code_page |= 0x10000000;
6651 if (want_name && *int_code_page == -1)
6652 return mono_string_new (mono_domain_get (), cset);
6658 ves_icall_System_Environment_get_HasShutdownStarted (void)
6660 if (mono_runtime_is_shutting_down ())
6663 if (mono_domain_is_unloading (mono_domain_get ()))
6670 ves_icall_System_Environment_BroadcastSettingChange (void)
6673 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6678 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6679 MonoReflectionMethod *method,
6680 MonoArray *out_args)
6682 MONO_ARCH_SAVE_REGS;
6684 mono_message_init (mono_object_domain (this), this, method, out_args);
6688 ves_icall_IsTransparentProxy (MonoObject *proxy)
6690 MONO_ARCH_SAVE_REGS;
6695 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6701 static MonoReflectionMethod *
6702 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6703 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6707 MonoMethod **vtable;
6708 MonoMethod *res = NULL;
6710 MONO_CHECK_ARG_NULL (rtype);
6711 MONO_CHECK_ARG_NULL (rmethod);
6713 method = rmethod->method;
6714 klass = mono_class_from_mono_type (rtype->type);
6715 mono_class_init_or_throw (klass);
6717 if (MONO_CLASS_IS_INTERFACE (klass))
6720 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6723 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6724 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6730 mono_class_setup_vtable (klass);
6731 vtable = klass->vtable;
6733 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6734 gboolean variance_used = FALSE;
6735 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6736 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6738 res = vtable [offs + method->slot];
6740 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6743 if (method->slot != -1)
6744 res = vtable [method->slot];
6750 return mono_method_get_object (mono_domain_get (), res, NULL);
6754 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6759 MONO_ARCH_SAVE_REGS;
6761 klass = mono_class_from_mono_type (type->type);
6762 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6764 if (enable) vtable->remote = 1;
6765 else vtable->remote = 0;
6769 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6774 MONO_ARCH_SAVE_REGS;
6776 domain = mono_object_domain (type);
6777 klass = mono_class_from_mono_type (type->type);
6778 mono_class_init_or_throw (klass);
6780 if (klass->rank >= 1) {
6781 g_assert (klass->rank == 1);
6782 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6784 /* Bypass remoting object creation check */
6785 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6790 ves_icall_System_IO_get_temp_path (void)
6792 MONO_ARCH_SAVE_REGS;
6794 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6797 #ifndef PLATFORM_NO_DRIVEINFO
6799 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6800 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6804 ULARGE_INTEGER wapi_free_bytes_avail;
6805 ULARGE_INTEGER wapi_total_number_of_bytes;
6806 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6808 MONO_ARCH_SAVE_REGS;
6810 *error = ERROR_SUCCESS;
6811 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6812 &wapi_total_number_of_free_bytes);
6815 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6816 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6817 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6819 *free_bytes_avail = 0;
6820 *total_number_of_bytes = 0;
6821 *total_number_of_free_bytes = 0;
6822 *error = GetLastError ();
6829 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6831 MONO_ARCH_SAVE_REGS;
6833 return GetDriveType (mono_string_chars (root_path_name));
6838 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6840 MONO_ARCH_SAVE_REGS;
6842 return mono_compile_method (method);
6846 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6851 MONO_ARCH_SAVE_REGS;
6853 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6855 #if defined (HOST_WIN32)
6856 /* Avoid mixing '/' and '\\' */
6859 for (i = strlen (path) - 1; i >= 0; i--)
6860 if (path [i] == '/')
6864 mcpath = mono_string_new (mono_domain_get (), path);
6871 get_bundled_app_config (void)
6873 const gchar *app_config;
6880 MONO_ARCH_SAVE_REGS;
6882 domain = mono_domain_get ();
6883 file = domain->setup->configuration_file;
6887 // Retrieve config file and remove the extension
6888 config_file = mono_string_to_utf8 (file);
6889 len = strlen (config_file) - strlen (".config");
6890 module = g_malloc0 (len + 1);
6891 memcpy (module, config_file, len);
6892 // Get the config file from the module name
6893 app_config = mono_config_string_for_assembly_file (module);
6896 g_free (config_file);
6901 return mono_string_new (mono_domain_get (), app_config);
6905 get_bundled_machine_config (void)
6907 const gchar *machine_config;
6909 MONO_ARCH_SAVE_REGS;
6911 machine_config = mono_get_machine_config ();
6913 if (!machine_config)
6916 return mono_string_new (mono_domain_get (), machine_config);
6920 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6925 MONO_ARCH_SAVE_REGS;
6927 path = g_path_get_dirname (mono_get_config_dir ());
6929 #if defined (HOST_WIN32)
6930 /* Avoid mixing '/' and '\\' */
6933 for (i = strlen (path) - 1; i >= 0; i--)
6934 if (path [i] == '/')
6938 ipath = mono_string_new (mono_domain_get (), path);
6945 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6947 MonoPEResourceDataEntry *entry;
6950 MONO_ARCH_SAVE_REGS;
6952 if (!assembly || !result || !size)
6957 image = assembly->assembly->image;
6958 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6962 *result = mono_image_rva_map (image, entry->rde_data_offset);
6967 *size = entry->rde_size;
6973 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6975 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6979 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6981 #if defined (HOST_WIN32)
6982 OutputDebugString (mono_string_chars (message));
6984 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6988 /* Only used for value types */
6990 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6995 MONO_ARCH_SAVE_REGS;
6997 domain = mono_object_domain (type);
6998 klass = mono_class_from_mono_type (type->type);
6999 mono_class_init_or_throw (klass);
7001 if (mono_class_is_nullable (klass))
7002 /* No arguments -> null */
7005 return mono_object_new (domain, klass);
7008 static MonoReflectionMethod *
7009 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7011 MonoClass *klass, *parent;
7012 MonoMethod *method = m->method;
7013 MonoMethod *result = NULL;
7015 MONO_ARCH_SAVE_REGS;
7017 if (method->klass == NULL)
7020 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7021 MONO_CLASS_IS_INTERFACE (method->klass) ||
7022 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7025 klass = method->klass;
7026 if (klass->generic_class)
7027 klass = klass->generic_class->container_class;
7030 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7031 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7032 mono_class_setup_vtable (parent);
7033 if (parent->vtable_size <= method->slot)
7038 klass = klass->parent;
7043 if (klass == method->klass)
7046 /*This is possible if definition == FALSE.
7047 * Do it here to be really sure we don't read invalid memory.
7049 if (method->slot >= klass->vtable_size)
7052 result = klass->vtable [method->slot];
7053 if (result == NULL) {
7054 /* It is an abstract method */
7055 gpointer iter = NULL;
7056 while ((result = mono_class_get_methods (klass, &iter)))
7057 if (result->slot == method->slot)
7064 return mono_method_get_object (mono_domain_get (), result, NULL);
7068 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7070 MonoMethod *method = m->method;
7072 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7077 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7079 MONO_ARCH_SAVE_REGS;
7081 iter->sig = *(MonoMethodSignature**)argsp;
7083 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7084 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7087 /* FIXME: it's not documented what start is exactly... */
7091 iter->args = argsp + sizeof (gpointer);
7093 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7095 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7099 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7101 guint32 i, arg_size;
7104 MONO_ARCH_SAVE_REGS;
7106 i = iter->sig->sentinelpos + iter->next_arg;
7108 g_assert (i < iter->sig->param_count);
7110 res.type = iter->sig->params [i];
7111 res.klass = mono_class_from_mono_type (res.type);
7112 res.value = iter->args;
7113 arg_size = mono_type_stack_size (res.type, &align);
7114 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7115 if (arg_size <= sizeof (gpointer)) {
7117 int padding = arg_size - mono_type_size (res.type, &dummy);
7118 res.value = (guint8*)res.value + padding;
7121 iter->args = (char*)iter->args + arg_size;
7124 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7130 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7132 guint32 i, arg_size;
7135 MONO_ARCH_SAVE_REGS;
7137 i = iter->sig->sentinelpos + iter->next_arg;
7139 g_assert (i < iter->sig->param_count);
7141 while (i < iter->sig->param_count) {
7142 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7144 res.type = iter->sig->params [i];
7145 res.klass = mono_class_from_mono_type (res.type);
7146 /* FIXME: endianess issue... */
7147 res.value = iter->args;
7148 arg_size = mono_type_stack_size (res.type, &align);
7149 iter->args = (char*)iter->args + arg_size;
7151 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7154 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7163 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7166 MONO_ARCH_SAVE_REGS;
7168 i = iter->sig->sentinelpos + iter->next_arg;
7170 g_assert (i < iter->sig->param_count);
7172 return iter->sig->params [i];
7176 mono_TypedReference_ToObject (MonoTypedRef tref)
7178 MONO_ARCH_SAVE_REGS;
7180 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7181 MonoObject** objp = tref.value;
7185 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7189 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7191 MONO_ARCH_SAVE_REGS;
7193 if (MONO_TYPE_IS_REFERENCE (type)) {
7194 MonoObject** objp = value;
7198 return mono_value_box (mono_domain_get (), klass, value);
7202 prelink_method (MonoMethod *method)
7204 const char *exc_class, *exc_arg;
7205 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7207 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7209 mono_raise_exception(
7210 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7212 /* create the wrapper, too? */
7216 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7218 MONO_ARCH_SAVE_REGS;
7219 prelink_method (method->method);
7223 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7225 MonoClass *klass = mono_class_from_mono_type (type->type);
7227 gpointer iter = NULL;
7228 MONO_ARCH_SAVE_REGS;
7230 mono_class_init_or_throw (klass);
7232 while ((m = mono_class_get_methods (klass, &iter)))
7236 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7238 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7239 gint32 const **exponents,
7240 gunichar2 const **digitLowerTable,
7241 gunichar2 const **digitUpperTable,
7242 gint64 const **tenPowersList,
7243 gint32 const **decHexDigits)
7245 *mantissas = Formatter_MantissaBitsTable;
7246 *exponents = Formatter_TensExponentTable;
7247 *digitLowerTable = Formatter_DigitLowerTable;
7248 *digitUpperTable = Formatter_DigitUpperTable;
7249 *tenPowersList = Formatter_TenPowersList;
7250 *decHexDigits = Formatter_DecHexDigits;
7253 /* These parameters are "readonly" in corlib/System/Char.cs */
7255 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7256 guint8 const **numeric_data,
7257 gdouble const **numeric_data_values,
7258 guint16 const **to_lower_data_low,
7259 guint16 const **to_lower_data_high,
7260 guint16 const **to_upper_data_low,
7261 guint16 const **to_upper_data_high)
7263 *category_data = CategoryData;
7264 *numeric_data = NumericData;
7265 *numeric_data_values = NumericDataValues;
7266 *to_lower_data_low = ToLowerDataLow;
7267 *to_lower_data_high = ToLowerDataHigh;
7268 *to_upper_data_low = ToUpperDataLow;
7269 *to_upper_data_high = ToUpperDataHigh;
7273 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7275 return method->method->token;
7279 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7280 * and avoid useless allocations.
7283 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7287 for (i = 0; i < type->num_mods; ++i) {
7288 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7293 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7295 for (i = 0; i < type->num_mods; ++i) {
7296 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7297 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7298 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7306 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7308 MonoType *type = param->ClassImpl->type;
7309 MonoClass *member_class = mono_object_class (param->MemberImpl);
7310 MonoMethod *method = NULL;
7313 MonoMethodSignature *sig;
7315 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7316 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7317 method = rmethod->method;
7318 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7319 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7320 if (!(method = prop->property->get))
7321 method = prop->property->set;
7324 char *type_name = mono_type_get_full_name (member_class);
7325 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7326 MonoException *ex = mono_get_exception_not_supported (msg);
7329 mono_raise_exception (ex);
7332 image = method->klass->image;
7333 pos = param->PositionImpl;
7334 sig = mono_method_signature (method);
7338 type = sig->params [pos];
7340 return type_array_from_modifiers (image, type, optional);
7344 get_property_type (MonoProperty *prop)
7346 MonoMethodSignature *sig;
7348 sig = mono_method_signature (prop->get);
7350 } else if (prop->set) {
7351 sig = mono_method_signature (prop->set);
7352 return sig->params [sig->param_count - 1];
7358 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7360 MonoType *type = get_property_type (property->property);
7361 MonoImage *image = property->klass->image;
7365 return type_array_from_modifiers (image, type, optional);
7369 *Construct a MonoType suited to be used to decode a constant blob object.
7371 * @type is the target type which will be constructed
7372 * @blob_type is the blob type, for example, that comes from the constant table
7373 * @real_type is the expected constructed type.
7376 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7378 type->type = blob_type;
7379 type->data.klass = NULL;
7380 if (blob_type == MONO_TYPE_CLASS)
7381 type->data.klass = mono_defaults.object_class;
7382 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7383 /* For enums, we need to use the base type */
7384 type->type = MONO_TYPE_VALUETYPE;
7385 type->data.klass = mono_class_from_mono_type (real_type);
7387 type->data.klass = mono_class_from_mono_type (real_type);
7391 property_info_get_default_value (MonoReflectionProperty *property)
7394 MonoProperty *prop = property->property;
7395 MonoType *type = get_property_type (prop);
7396 MonoDomain *domain = mono_object_domain (property);
7397 MonoTypeEnum def_type;
7398 const char *def_value;
7401 mono_class_init (prop->parent);
7403 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7404 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7406 def_value = mono_class_get_property_default_value (prop, &def_type);
7408 mono_type_from_blob_type (&blob_type, def_type, type);
7409 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7415 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7417 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7418 MonoCustomAttrInfo *cinfo;
7421 mono_class_init_or_throw (attr_class);
7423 cinfo = mono_reflection_get_custom_attrs_info (obj);
7426 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7428 mono_custom_attrs_free (cinfo);
7433 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7435 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7439 mono_class_init_or_throw (attr_class);
7441 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7443 if (mono_loader_get_last_error ()) {
7444 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7445 g_assert_not_reached ();
7454 ves_icall_Mono_Runtime_GetDisplayName (void)
7457 MonoString *display_name;
7459 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7460 display_name = mono_string_new (mono_domain_get (), info);
7462 return display_name;
7466 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7468 MonoString *message;
7472 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7473 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7476 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7478 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7486 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7487 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7488 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7489 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7490 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7491 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7492 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7493 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7497 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7502 gunichar2 last, prev_last, prev2_last;
7510 last = prev_last = 0, prev2_last = 0;
7511 for (i = 0; i < ilength; i++) {
7513 if (c >= sizeof (dbase64)) {
7514 exc = mono_exception_from_name_msg (mono_get_corlib (),
7515 "System", "FormatException",
7516 "Invalid character found.");
7517 mono_raise_exception (exc);
7518 } else if (isspace (c)) {
7521 prev2_last = prev_last;
7527 olength = ilength - ignored;
7529 if (allowWhitespaceOnly && olength == 0) {
7530 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7533 if ((olength & 3) != 0 || olength <= 0) {
7534 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7535 "FormatException", "Invalid length.");
7536 mono_raise_exception (exc);
7539 if (prev2_last == '=') {
7540 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7541 mono_raise_exception (exc);
7544 olength = (olength * 3) / 4;
7548 if (prev_last == '=')
7551 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7552 res_ptr = mono_array_addr (result, guchar, 0);
7553 for (i = 0; i < ilength; ) {
7556 for (k = 0; k < 4 && i < ilength;) {
7562 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7563 exc = mono_exception_from_name_msg (mono_get_corlib (),
7564 "System", "FormatException",
7565 "Invalid character found.");
7566 mono_raise_exception (exc);
7571 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7573 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7575 *res_ptr++ = (b [2] << 6) | b [3];
7577 while (i < ilength && isspace (start [i]))
7585 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7587 MONO_ARCH_SAVE_REGS;
7589 return base64_to_byte_array (mono_string_chars (str),
7590 mono_string_length (str), allowWhitespaceOnly);
7594 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7596 MONO_ARCH_SAVE_REGS;
7598 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7602 #define ICALL_TYPE(id,name,first)
7603 #define ICALL(id,name,func) Icall_ ## id,
7606 #include "metadata/icall-def.h"
7612 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7613 #define ICALL(id,name,func)
7615 #include "metadata/icall-def.h"
7621 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7622 #define ICALL(id,name,func)
7624 guint16 first_icall;
7627 static const IcallTypeDesc
7628 icall_type_descs [] = {
7629 #include "metadata/icall-def.h"
7633 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7636 #define ICALL_TYPE(id,name,first)
7639 #ifdef HAVE_ARRAY_ELEM_INIT
7640 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7641 #define MSGSTRFIELD1(line) str##line
7643 static const struct msgstrtn_t {
7644 #define ICALL(id,name,func)
7646 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7647 #include "metadata/icall-def.h"
7649 } icall_type_names_str = {
7650 #define ICALL_TYPE(id,name,first) (name),
7651 #include "metadata/icall-def.h"
7654 static const guint16 icall_type_names_idx [] = {
7655 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7656 #include "metadata/icall-def.h"
7659 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7661 static const struct msgstr_t {
7663 #define ICALL_TYPE(id,name,first)
7664 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7665 #include "metadata/icall-def.h"
7667 } icall_names_str = {
7668 #define ICALL(id,name,func) (name),
7669 #include "metadata/icall-def.h"
7672 static const guint16 icall_names_idx [] = {
7673 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7674 #include "metadata/icall-def.h"
7677 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7683 #define ICALL_TYPE(id,name,first) name,
7684 #define ICALL(id,name,func)
7685 static const char* const
7686 icall_type_names [] = {
7687 #include "metadata/icall-def.h"
7691 #define icall_type_name_get(id) (icall_type_names [(id)])
7695 #define ICALL_TYPE(id,name,first)
7696 #define ICALL(id,name,func) name,
7697 static const char* const
7699 #include "metadata/icall-def.h"
7702 #define icall_name_get(id) icall_names [(id)]
7704 #endif /* !HAVE_ARRAY_ELEM_INIT */
7708 #define ICALL_TYPE(id,name,first)
7709 #define ICALL(id,name,func) func,
7710 static const gconstpointer
7711 icall_functions [] = {
7712 #include "metadata/icall-def.h"
7716 static GHashTable *icall_hash = NULL;
7717 static GHashTable *jit_icall_hash_name = NULL;
7718 static GHashTable *jit_icall_hash_addr = NULL;
7721 mono_icall_init (void)
7725 /* check that tables are sorted: disable in release */
7728 const char *prev_class = NULL;
7729 const char *prev_method;
7731 for (i = 0; i < Icall_type_num; ++i) {
7732 const IcallTypeDesc *desc;
7735 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7736 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7737 prev_class = icall_type_name_get (i);
7738 desc = &icall_type_descs [i];
7739 num_icalls = icall_desc_num_icalls (desc);
7740 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7741 for (j = 0; j < num_icalls; ++j) {
7742 const char *methodn = icall_name_get (desc->first_icall + j);
7743 if (prev_method && strcmp (prev_method, methodn) >= 0)
7744 g_print ("method %s should come before method %s\n", methodn, prev_method);
7745 prev_method = methodn;
7750 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7754 mono_icall_cleanup (void)
7756 g_hash_table_destroy (icall_hash);
7757 g_hash_table_destroy (jit_icall_hash_name);
7758 g_hash_table_destroy (jit_icall_hash_addr);
7762 mono_add_internal_call (const char *name, gconstpointer method)
7764 mono_loader_lock ();
7766 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7768 mono_loader_unlock ();
7771 #ifdef HAVE_ARRAY_ELEM_INIT
7773 compare_method_imap (const void *key, const void *elem)
7775 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7776 return strcmp (key, method_name);
7780 find_method_icall (const IcallTypeDesc *imap, const char *name)
7782 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7785 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7789 compare_class_imap (const void *key, const void *elem)
7791 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7792 return strcmp (key, class_name);
7795 static const IcallTypeDesc*
7796 find_class_icalls (const char *name)
7798 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7801 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7806 compare_method_imap (const void *key, const void *elem)
7808 const char** method_name = (const char**)elem;
7809 return strcmp (key, *method_name);
7813 find_method_icall (const IcallTypeDesc *imap, const char *name)
7815 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7818 return (gpointer)icall_functions [(nameslot - icall_names)];
7822 compare_class_imap (const void *key, const void *elem)
7824 const char** class_name = (const char**)elem;
7825 return strcmp (key, *class_name);
7828 static const IcallTypeDesc*
7829 find_class_icalls (const char *name)
7831 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7834 return &icall_type_descs [nameslot - icall_type_names];
7840 * we should probably export this as an helper (handle nested types).
7841 * Returns the number of chars written in buf.
7844 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7846 int nspacelen, cnamelen;
7847 nspacelen = strlen (klass->name_space);
7848 cnamelen = strlen (klass->name);
7849 if (nspacelen + cnamelen + 2 > bufsize)
7852 memcpy (buf, klass->name_space, nspacelen);
7853 buf [nspacelen ++] = '.';
7855 memcpy (buf + nspacelen, klass->name, cnamelen);
7856 buf [nspacelen + cnamelen] = 0;
7857 return nspacelen + cnamelen;
7861 mono_lookup_internal_call (MonoMethod *method)
7866 int typelen = 0, mlen, siglen;
7868 const IcallTypeDesc *imap;
7870 g_assert (method != NULL);
7872 if (method->is_inflated)
7873 method = ((MonoMethodInflated *) method)->declaring;
7875 if (method->klass->nested_in) {
7876 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7880 mname [pos++] = '/';
7883 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7889 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7894 imap = find_class_icalls (mname);
7896 mname [typelen] = ':';
7897 mname [typelen + 1] = ':';
7899 mlen = strlen (method->name);
7900 memcpy (mname + typelen + 2, method->name, mlen);
7901 sigstart = mname + typelen + 2 + mlen;
7904 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7905 siglen = strlen (tmpsig);
7906 if (typelen + mlen + siglen + 6 > sizeof (mname))
7909 memcpy (sigstart + 1, tmpsig, siglen);
7910 sigstart [siglen + 1] = ')';
7911 sigstart [siglen + 2] = 0;
7914 mono_loader_lock ();
7916 res = g_hash_table_lookup (icall_hash, mname);
7918 mono_loader_unlock ();
7921 /* try without signature */
7923 res = g_hash_table_lookup (icall_hash, mname);
7925 mono_loader_unlock ();
7929 /* it wasn't found in the static call tables */
7931 mono_loader_unlock ();
7934 res = find_method_icall (imap, sigstart - mlen);
7936 mono_loader_unlock ();
7939 /* try _with_ signature */
7941 res = find_method_icall (imap, sigstart - mlen);
7943 mono_loader_unlock ();
7947 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7948 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7949 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7950 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7951 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");
7952 g_print ("If you see other errors or faults after this message they are probably related\n");
7953 g_print ("and you need to fix your mono install first.\n");
7955 mono_loader_unlock ();
7961 type_from_typename (char *typename)
7963 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7965 if (!strcmp (typename, "int"))
7966 klass = mono_defaults.int_class;
7967 else if (!strcmp (typename, "ptr"))
7968 klass = mono_defaults.int_class;
7969 else if (!strcmp (typename, "void"))
7970 klass = mono_defaults.void_class;
7971 else if (!strcmp (typename, "int32"))
7972 klass = mono_defaults.int32_class;
7973 else if (!strcmp (typename, "uint32"))
7974 klass = mono_defaults.uint32_class;
7975 else if (!strcmp (typename, "int8"))
7976 klass = mono_defaults.sbyte_class;
7977 else if (!strcmp (typename, "uint8"))
7978 klass = mono_defaults.byte_class;
7979 else if (!strcmp (typename, "int16"))
7980 klass = mono_defaults.int16_class;
7981 else if (!strcmp (typename, "uint16"))
7982 klass = mono_defaults.uint16_class;
7983 else if (!strcmp (typename, "long"))
7984 klass = mono_defaults.int64_class;
7985 else if (!strcmp (typename, "ulong"))
7986 klass = mono_defaults.uint64_class;
7987 else if (!strcmp (typename, "float"))
7988 klass = mono_defaults.single_class;
7989 else if (!strcmp (typename, "double"))
7990 klass = mono_defaults.double_class;
7991 else if (!strcmp (typename, "object"))
7992 klass = mono_defaults.object_class;
7993 else if (!strcmp (typename, "obj"))
7994 klass = mono_defaults.object_class;
7995 else if (!strcmp (typename, "string"))
7996 klass = mono_defaults.string_class;
7997 else if (!strcmp (typename, "bool"))
7998 klass = mono_defaults.boolean_class;
7999 else if (!strcmp (typename, "boolean"))
8000 klass = mono_defaults.boolean_class;
8002 g_error ("%s", typename);
8003 g_assert_not_reached ();
8005 return &klass->byval_arg;
8008 MonoMethodSignature*
8009 mono_create_icall_signature (const char *sigstr)
8014 MonoMethodSignature *res;
8016 mono_loader_lock ();
8017 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8019 mono_loader_unlock ();
8023 parts = g_strsplit (sigstr, " ", 256);
8032 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8037 * Under windows, the default pinvoke calling convention is STDCALL but
8040 res->call_convention = MONO_CALL_C;
8043 res->ret = type_from_typename (parts [0]);
8044 for (i = 1; i < len; ++i) {
8045 res->params [i - 1] = type_from_typename (parts [i]);
8050 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8052 mono_loader_unlock ();
8058 mono_find_jit_icall_by_name (const char *name)
8060 MonoJitICallInfo *info;
8061 g_assert (jit_icall_hash_name);
8063 mono_loader_lock ();
8064 info = g_hash_table_lookup (jit_icall_hash_name, name);
8065 mono_loader_unlock ();
8070 mono_find_jit_icall_by_addr (gconstpointer addr)
8072 MonoJitICallInfo *info;
8073 g_assert (jit_icall_hash_addr);
8075 mono_loader_lock ();
8076 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8077 mono_loader_unlock ();
8083 * mono_get_jit_icall_info:
8085 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8086 * caller should access it while holding the loader lock.
8089 mono_get_jit_icall_info (void)
8091 return jit_icall_hash_name;
8095 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8097 mono_loader_lock ();
8098 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8099 mono_loader_unlock ();
8103 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8105 MonoJitICallInfo *info;
8110 mono_loader_lock ();
8112 if (!jit_icall_hash_name) {
8113 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8114 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8117 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8118 g_warning ("jit icall already defined \"%s\"\n", name);
8119 g_assert_not_reached ();
8122 info = g_new0 (MonoJitICallInfo, 1);
8129 info->wrapper = func;
8131 info->wrapper = NULL;
8134 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8135 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8137 mono_loader_unlock ();