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 if ((req_info & PInfo_DeclaringType) != 0)
1980 MONO_STRUCT_SETREF (info, declaring_type, 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 g_hash_table_destroy (iface_hash);
2111 if (!data.domain->empty_types)
2112 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2113 return data.domain->empty_types;
2116 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2117 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2118 if (!mono_error_ok (&error))
2121 g_hash_table_destroy (iface_hash);
2122 return data.iface_array;
2125 g_hash_table_destroy (iface_hash);
2126 mono_error_raise_exception (&error);
2131 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2133 gboolean variance_used;
2134 MonoClass *class = mono_class_from_mono_type (type->type);
2135 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2136 MonoReflectionMethod *member;
2139 int i = 0, len, ioffset;
2142 MONO_ARCH_SAVE_REGS;
2143 mono_class_init_or_throw (class);
2144 mono_class_init_or_throw (iclass);
2146 mono_class_setup_vtable (class);
2148 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2152 len = mono_class_num_methods (iclass);
2153 domain = mono_object_domain (type);
2154 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2155 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2157 while ((method = mono_class_get_methods (iclass, &iter))) {
2158 member = mono_method_get_object (domain, method, iclass);
2159 mono_array_setref (*methods, i, member);
2160 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2161 mono_array_setref (*targets, i, member);
2168 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2170 MonoClass *klass = mono_class_from_mono_type (type->type);
2171 mono_class_init_or_throw (klass);
2173 if (klass->image->dynamic) {
2174 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2175 *packing = tb->packing_size;
2176 *size = tb->class_size;
2178 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2182 static MonoReflectionType*
2183 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2187 MONO_ARCH_SAVE_REGS;
2189 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2190 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2192 class = mono_class_from_mono_type (type->type);
2193 mono_class_init_or_throw (class);
2195 // GetElementType should only return a type for:
2196 // Array Pointer PassedByRef
2197 if (type->type->byref)
2198 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2199 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2200 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2201 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2202 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2207 static MonoReflectionType*
2208 ves_icall_get_type_parent (MonoReflectionType *type)
2210 MonoClass *class = mono_class_from_mono_type (type->type);
2211 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2215 ves_icall_type_ispointer (MonoReflectionType *type)
2217 MONO_ARCH_SAVE_REGS;
2219 return type->type->type == MONO_TYPE_PTR;
2223 ves_icall_type_isprimitive (MonoReflectionType *type)
2225 MONO_ARCH_SAVE_REGS;
2227 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2231 ves_icall_type_isbyref (MonoReflectionType *type)
2233 MONO_ARCH_SAVE_REGS;
2235 return type->type->byref;
2239 ves_icall_type_iscomobject (MonoReflectionType *type)
2241 MonoClass *klass = mono_class_from_mono_type (type->type);
2242 mono_class_init_or_throw (klass);
2244 return (klass && klass->is_com_object);
2247 static MonoReflectionModule*
2248 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2250 MonoClass *class = mono_class_from_mono_type (type->type);
2251 return mono_module_get_object (mono_object_domain (type), class->image);
2254 static MonoReflectionAssembly*
2255 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2257 MonoDomain *domain = mono_domain_get ();
2258 MonoClass *class = mono_class_from_mono_type (type->type);
2259 return mono_assembly_get_object (domain, class->image->assembly);
2262 static MonoReflectionType*
2263 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2265 MonoDomain *domain = mono_domain_get ();
2268 MONO_ARCH_SAVE_REGS;
2270 if (type->type->byref)
2272 if (type->type->type == MONO_TYPE_VAR)
2273 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2274 else if (type->type->type == MONO_TYPE_MVAR)
2275 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2277 class = mono_class_from_mono_type (type->type)->nested_in;
2279 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2283 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2285 MonoDomain *domain = mono_domain_get ();
2286 MonoClass *class = mono_class_from_mono_type (type->type);
2288 if (type->type->byref) {
2289 char *n = g_strdup_printf ("%s&", class->name);
2290 MonoString *res = mono_string_new (domain, n);
2296 return mono_string_new (domain, class->name);
2301 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2303 MonoDomain *domain = mono_domain_get ();
2304 MonoClass *class = mono_class_from_mono_type (type->type);
2306 while (class->nested_in)
2307 class = class->nested_in;
2309 if (class->name_space [0] == '\0')
2312 return mono_string_new (domain, class->name_space);
2316 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2320 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2321 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2323 class = mono_class_from_mono_type (type->type);
2324 mono_class_init_or_throw (class);
2330 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2333 MonoClass *klass, *pklass;
2334 MonoDomain *domain = mono_object_domain (type);
2335 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2337 MONO_ARCH_SAVE_REGS;
2339 klass = mono_class_from_mono_type (type->type);
2340 mono_class_init_or_throw (klass);
2342 if (klass->generic_container) {
2343 MonoGenericContainer *container = klass->generic_container;
2344 res = mono_array_new_specific (array_vtable, container->type_argc);
2345 for (i = 0; i < container->type_argc; ++i) {
2346 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2347 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2349 } else if (klass->generic_class) {
2350 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2351 res = mono_array_new_specific (array_vtable, inst->type_argc);
2352 for (i = 0; i < inst->type_argc; ++i)
2353 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2355 res = mono_array_new_specific (array_vtable, 0);
2361 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2364 MONO_ARCH_SAVE_REGS;
2366 if (!IS_MONOTYPE (type))
2369 if (type->type->byref)
2372 klass = mono_class_from_mono_type (type->type);
2373 return klass->generic_container != NULL;
2376 static MonoReflectionType*
2377 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2380 MONO_ARCH_SAVE_REGS;
2382 if (type->type->byref)
2385 klass = mono_class_from_mono_type (type->type);
2386 mono_class_init_or_throw (klass);
2388 if (klass->generic_container) {
2389 return type; /* check this one */
2391 if (klass->generic_class) {
2392 MonoClass *generic_class = klass->generic_class->container_class;
2395 tb = mono_class_get_ref_info (generic_class);
2397 if (generic_class->wastypebuilder && tb)
2400 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2405 static MonoReflectionType*
2406 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2408 MonoType *geninst, **types;
2411 g_assert (IS_MONOTYPE (type));
2412 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2414 count = mono_array_length (type_array);
2415 types = g_new0 (MonoType *, count);
2417 for (i = 0; i < count; i++) {
2418 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2419 types [i] = t->type;
2422 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2427 return mono_type_get_object (mono_object_domain (type), geninst);
2431 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2434 MONO_ARCH_SAVE_REGS;
2436 if (type->type->byref)
2439 klass = mono_class_from_mono_type (type->type);
2441 return klass->generic_class != NULL;
2445 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2448 MONO_ARCH_SAVE_REGS;
2450 if (!IS_MONOTYPE (type))
2453 if (type->type->byref)
2456 klass = mono_class_from_mono_type (type->type);
2457 return klass->generic_class != NULL || klass->generic_container != NULL;
2461 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2463 MONO_ARCH_SAVE_REGS;
2465 if (!IS_MONOTYPE (type))
2468 if (is_generic_parameter (type->type))
2469 return mono_type_get_generic_param_num (type->type);
2473 static GenericParameterAttributes
2474 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2476 MONO_ARCH_SAVE_REGS;
2478 g_assert (IS_MONOTYPE (type));
2479 g_assert (is_generic_parameter (type->type));
2480 return mono_generic_param_info (type->type->data.generic_param)->flags;
2484 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2486 MonoGenericParamInfo *param_info;
2492 MONO_ARCH_SAVE_REGS;
2494 g_assert (IS_MONOTYPE (type));
2496 domain = mono_object_domain (type);
2497 param_info = mono_generic_param_info (type->type->data.generic_param);
2498 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2501 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2502 for (i = 0; i < count; i++)
2503 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2510 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2512 MONO_ARCH_SAVE_REGS;
2513 return is_generic_parameter (type->type);
2517 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2519 MONO_ARCH_SAVE_REGS;
2520 return is_generic_parameter (tb->type.type);
2524 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2525 MonoReflectionType *t)
2527 enumtype->type = t->type;
2530 static MonoReflectionMethod*
2531 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2532 MonoReflectionMethod* generic)
2539 MONO_ARCH_SAVE_REGS;
2541 domain = ((MonoObject *)type)->vtable->domain;
2543 klass = mono_class_from_mono_type (type->type);
2544 mono_class_init_or_throw (klass);
2547 while ((method = mono_class_get_methods (klass, &iter))) {
2548 if (method->token == generic->method->token)
2549 return mono_method_get_object (domain, method, klass);
2557 static MonoReflectionMethod *
2558 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2561 MonoType *type = ref_type->type;
2563 MONO_ARCH_SAVE_REGS;
2565 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2566 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2567 if (type->type == MONO_TYPE_VAR)
2570 method = mono_type_get_generic_param_owner (type)->owner.method;
2572 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2575 static MonoReflectionDllImportAttribute*
2576 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2578 static MonoClass *DllImportAttributeClass = NULL;
2579 MonoDomain *domain = mono_domain_get ();
2580 MonoReflectionDllImportAttribute *attr;
2581 MonoImage *image = method->klass->image;
2582 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2583 MonoTableInfo *tables = image->tables;
2584 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2585 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2586 guint32 im_cols [MONO_IMPLMAP_SIZE];
2587 guint32 scope_token;
2588 const char *import = NULL;
2589 const char *scope = NULL;
2592 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2595 if (!DllImportAttributeClass) {
2596 DllImportAttributeClass =
2597 mono_class_from_name (mono_defaults.corlib,
2598 "System.Runtime.InteropServices", "DllImportAttribute");
2599 g_assert (DllImportAttributeClass);
2602 if (method->klass->image->dynamic) {
2603 MonoReflectionMethodAux *method_aux =
2604 g_hash_table_lookup (
2605 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2607 import = method_aux->dllentry;
2608 scope = method_aux->dll;
2611 if (!import || !scope) {
2612 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2617 if (piinfo->implmap_idx) {
2618 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2620 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2621 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2622 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2623 scope = mono_metadata_string_heap (image, scope_token);
2626 flags = piinfo->piflags;
2628 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2630 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2631 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2632 attr->call_conv = (flags & 0x700) >> 8;
2633 attr->charset = ((flags & 0x6) >> 1) + 1;
2634 if (attr->charset == 1)
2636 attr->exact_spelling = (flags & 0x1) != 0;
2637 attr->set_last_error = (flags & 0x40) != 0;
2638 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2639 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2640 attr->preserve_sig = FALSE;
2645 static MonoReflectionMethod *
2646 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2648 MonoMethodInflated *imethod;
2651 MONO_ARCH_SAVE_REGS;
2653 if (method->method->is_generic)
2656 if (!method->method->is_inflated)
2659 imethod = (MonoMethodInflated *) method->method;
2661 result = imethod->declaring;
2662 /* Not a generic method. */
2663 if (!result->is_generic)
2666 if (method->method->klass->image->dynamic) {
2667 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2668 MonoReflectionMethod *res;
2671 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2672 * the dynamic case as well ?
2674 mono_loader_lock ();
2675 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2676 mono_loader_unlock ();
2682 if (imethod->context.class_inst) {
2683 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2684 /*Generic methods gets the context of the GTD.*/
2685 if (mono_class_get_context (klass))
2686 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2689 return mono_method_get_object (mono_object_domain (method), result, NULL);
2693 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2695 MONO_ARCH_SAVE_REGS;
2697 return mono_method_signature (method->method)->generic_param_count != 0;
2701 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2703 MONO_ARCH_SAVE_REGS;
2705 return method->method->is_generic;
2709 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2714 MONO_ARCH_SAVE_REGS;
2716 domain = mono_object_domain (method);
2718 if (method->method->is_inflated) {
2719 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2722 count = inst->type_argc;
2723 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2725 for (i = 0; i < count; i++)
2726 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2732 count = mono_method_signature (method->method)->generic_param_count;
2733 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2735 for (i = 0; i < count; i++) {
2736 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2737 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2738 MonoClass *pklass = mono_class_from_generic_parameter (
2739 param, method->method->klass->image, TRUE);
2740 mono_array_setref (res, i,
2741 mono_type_get_object (domain, &pklass->byval_arg));
2748 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2751 * Invoke from reflection is supposed to always be a virtual call (the API
2752 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2753 * greater flexibility.
2755 MonoMethod *m = method->method;
2759 MONO_ARCH_SAVE_REGS;
2763 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2764 mono_security_core_clr_ensure_reflection_access_method (m);
2766 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2767 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2768 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2773 if (!mono_object_isinst (this, m->klass)) {
2774 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2777 m = mono_object_get_virtual_method (this, m);
2778 /* must pass the pointer to the value for valuetype methods */
2779 if (m->klass->valuetype)
2780 obj = mono_object_unbox (this);
2781 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2782 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2787 pcount = params? mono_array_length (params): 0;
2788 if (pcount != mono_method_signature (m)->param_count) {
2789 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2793 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2794 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."));
2798 if (m->klass->image->assembly->ref_only) {
2799 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."));
2803 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2806 intptr_t *lower_bounds;
2807 pcount = mono_array_length (params);
2808 lengths = alloca (sizeof (uintptr_t) * pcount);
2809 /* Note: the synthetized array .ctors have int32 as argument type */
2810 for (i = 0; i < pcount; ++i)
2811 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2813 if (m->klass->rank == pcount) {
2814 /* Only lengths provided. */
2815 lower_bounds = NULL;
2817 g_assert (pcount == (m->klass->rank * 2));
2818 /* lower bounds are first. */
2819 lower_bounds = (intptr_t*)lengths;
2820 lengths += m->klass->rank;
2823 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2825 return mono_runtime_invoke_array (m, obj, params, NULL);
2829 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2831 MonoDomain *domain = mono_object_domain (method);
2832 MonoMethod *m = method->method;
2833 MonoMethodSignature *sig = mono_method_signature (m);
2834 MonoArray *out_args;
2836 int i, j, outarg_count = 0;
2838 MONO_ARCH_SAVE_REGS;
2840 if (m->klass == mono_defaults.object_class) {
2842 if (!strcmp (m->name, "FieldGetter")) {
2843 MonoClass *k = this->vtable->klass;
2847 /* If this is a proxy, then it must be a CBO */
2848 if (k == mono_defaults.transparent_proxy_class) {
2849 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2850 this = tp->rp->unwrapped_server;
2852 k = this->vtable->klass;
2855 name = mono_array_get (params, MonoString *, 1);
2856 str = mono_string_to_utf8 (name);
2859 MonoClassField* field = mono_class_get_field_from_name (k, str);
2861 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2862 if (field_klass->valuetype)
2863 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2865 result = *((gpointer *)((char *)this + field->offset));
2867 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2868 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2869 mono_array_setref (out_args, 0, result);
2877 g_assert_not_reached ();
2879 } else if (!strcmp (m->name, "FieldSetter")) {
2880 MonoClass *k = this->vtable->klass;
2886 /* If this is a proxy, then it must be a CBO */
2887 if (k == mono_defaults.transparent_proxy_class) {
2888 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2889 this = tp->rp->unwrapped_server;
2891 k = this->vtable->klass;
2894 name = mono_array_get (params, MonoString *, 1);
2895 str = mono_string_to_utf8 (name);
2898 MonoClassField* field = mono_class_get_field_from_name (k, str);
2900 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2901 MonoObject *val = mono_array_get (params, gpointer, 2);
2903 if (field_klass->valuetype) {
2904 size = mono_type_size (field->type, &align);
2905 g_assert (size == mono_class_value_size (field_klass, NULL));
2906 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2908 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2911 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2912 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2922 g_assert_not_reached ();
2927 for (i = 0; i < mono_array_length (params); i++) {
2928 if (sig->params [i]->byref)
2932 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2934 /* handle constructors only for objects already allocated */
2935 if (!strcmp (method->method->name, ".ctor"))
2938 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2939 g_assert (!method->method->klass->valuetype);
2940 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2942 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2943 if (sig->params [i]->byref) {
2945 arg = mono_array_get (params, gpointer, i);
2946 mono_array_setref (out_args, j, arg);
2951 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2957 read_enum_value (char *mem, int type)
2961 return *(guint8*)mem;
2963 return *(gint8*)mem;
2965 return *(guint16*)mem;
2967 return *(gint16*)mem;
2969 return *(guint32*)mem;
2971 return *(gint32*)mem;
2973 return *(guint64*)mem;
2975 return *(gint64*)mem;
2977 g_assert_not_reached ();
2983 write_enum_value (char *mem, int type, guint64 value)
2987 case MONO_TYPE_I1: {
2988 guint8 *p = (guint8*)mem;
2993 case MONO_TYPE_I2: {
2994 guint16 *p = (void*)mem;
2999 case MONO_TYPE_I4: {
3000 guint32 *p = (void*)mem;
3005 case MONO_TYPE_I8: {
3006 guint64 *p = (void*)mem;
3011 g_assert_not_reached ();
3017 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3020 MonoClass *enumc, *objc;
3025 MONO_ARCH_SAVE_REGS;
3027 MONO_CHECK_ARG_NULL (enumType);
3028 MONO_CHECK_ARG_NULL (value);
3030 domain = mono_object_domain (enumType);
3031 enumc = mono_class_from_mono_type (enumType->type);
3033 mono_class_init_or_throw (enumc);
3035 objc = value->vtable->klass;
3037 if (!enumc->enumtype)
3038 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3039 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3040 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."));
3042 etype = mono_class_enum_basetype (enumc);
3044 /* MS throws this for typebuilders */
3045 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3047 res = mono_object_new (domain, enumc);
3048 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3049 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3055 ves_icall_System_Enum_get_value (MonoObject *this)
3063 MONO_ARCH_SAVE_REGS;
3068 g_assert (this->vtable->klass->enumtype);
3070 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3071 res = mono_object_new (mono_object_domain (this), enumc);
3072 dst = (char *)res + sizeof (MonoObject);
3073 src = (char *)this + sizeof (MonoObject);
3074 size = mono_class_value_size (enumc, NULL);
3076 memcpy (dst, src, size);
3081 static MonoReflectionType *
3082 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3087 MONO_ARCH_SAVE_REGS;
3089 klass = mono_class_from_mono_type (type->type);
3090 mono_class_init_or_throw (klass);
3092 etype = mono_class_enum_basetype (klass);
3094 /* MS throws this for typebuilders */
3095 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3097 return mono_type_get_object (mono_object_domain (type), etype);
3101 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3103 gpointer tdata = (char *)this + sizeof (MonoObject);
3104 gpointer odata = (char *)other + sizeof (MonoObject);
3105 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3106 g_assert (basetype);
3108 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3109 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3110 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3113 return me > other ? 1 : -1; \
3116 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3117 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3118 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3121 return me - other; \
3124 switch (basetype->type) {
3126 COMPARE_ENUM_VALUES (guint8);
3128 COMPARE_ENUM_VALUES (gint8);
3129 case MONO_TYPE_CHAR:
3131 COMPARE_ENUM_VALUES_RANGE (guint16);
3133 COMPARE_ENUM_VALUES (gint16);
3135 COMPARE_ENUM_VALUES (guint32);
3137 COMPARE_ENUM_VALUES (gint32);
3139 COMPARE_ENUM_VALUES (guint64);
3141 COMPARE_ENUM_VALUES (gint64);
3143 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3145 #undef COMPARE_ENUM_VALUES_RANGE
3146 #undef COMPARE_ENUM_VALUES
3151 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3153 gpointer data = (char *)this + sizeof (MonoObject);
3154 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3155 g_assert (basetype);
3157 switch (basetype->type) {
3159 return *((gint8*)data);
3161 return *((guint8*)data);
3162 case MONO_TYPE_CHAR:
3164 return *((guint16*)data);
3167 return *((gint16*)data);
3169 return *((guint32*)data);
3171 return *((gint32*)data);
3173 case MONO_TYPE_I8: {
3174 gint64 value = *((gint64*)data);
3175 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3178 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3184 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3186 MonoDomain *domain = mono_object_domain (type);
3187 MonoClass *enumc = mono_class_from_mono_type (type->type);
3188 guint j = 0, nvalues, crow;
3190 MonoClassField *field;
3192 MONO_ARCH_SAVE_REGS;
3194 mono_class_init_or_throw (enumc);
3196 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3197 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3198 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3199 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3203 while ((field = mono_class_get_fields (enumc, &iter))) {
3206 MonoTypeEnum def_type;
3208 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3210 if (mono_field_is_deleted (field))
3212 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3214 p = mono_class_get_field_default_value (field, &def_type);
3215 len = mono_metadata_decode_blob_size (p, &p);
3216 switch (mono_class_enum_basetype (enumc)->type) {
3219 mono_array_set (info->values, gchar, j, *p);
3221 case MONO_TYPE_CHAR:
3224 mono_array_set (info->values, gint16, j, read16 (p));
3228 mono_array_set (info->values, gint32, j, read32 (p));
3232 mono_array_set (info->values, gint64, j, read64 (p));
3235 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3242 BFLAGS_IgnoreCase = 1,
3243 BFLAGS_DeclaredOnly = 2,
3244 BFLAGS_Instance = 4,
3246 BFLAGS_Public = 0x10,
3247 BFLAGS_NonPublic = 0x20,
3248 BFLAGS_FlattenHierarchy = 0x40,
3249 BFLAGS_InvokeMethod = 0x100,
3250 BFLAGS_CreateInstance = 0x200,
3251 BFLAGS_GetField = 0x400,
3252 BFLAGS_SetField = 0x800,
3253 BFLAGS_GetProperty = 0x1000,
3254 BFLAGS_SetProperty = 0x2000,
3255 BFLAGS_ExactBinding = 0x10000,
3256 BFLAGS_SuppressChangeType = 0x20000,
3257 BFLAGS_OptionalParamBinding = 0x40000
3260 static MonoReflectionField *
3261 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3264 MonoClass *startklass, *klass;
3266 MonoClassField *field;
3269 int (*compare_func) (const char *s1, const char *s2) = NULL;
3270 domain = ((MonoObject *)type)->vtable->domain;
3271 klass = startklass = mono_class_from_mono_type (type->type);
3272 mono_class_init_or_throw (klass);
3275 mono_raise_exception (mono_get_exception_argument_null ("name"));
3276 if (type->type->byref)
3279 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3282 if (klass->exception_type != MONO_EXCEPTION_NONE)
3283 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3286 while ((field = mono_class_get_fields (klass, &iter))) {
3289 if (field->type == NULL)
3291 if (mono_field_is_deleted (field))
3293 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3294 if (bflags & BFLAGS_Public)
3296 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3297 if (bflags & BFLAGS_NonPublic) {
3304 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3305 if (bflags & BFLAGS_Static)
3306 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3309 if (bflags & BFLAGS_Instance)
3316 utf8_name = mono_string_to_utf8 (name);
3318 if (compare_func (mono_field_get_name (field), utf8_name)) {
3324 return mono_field_get_object (domain, klass, field);
3326 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3333 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3336 MonoClass *startklass, *klass, *refklass;
3341 MonoClassField *field;
3342 MonoPtrArray tmp_array;
3344 MONO_ARCH_SAVE_REGS;
3346 domain = ((MonoObject *)type)->vtable->domain;
3347 if (type->type->byref)
3348 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3349 klass = startklass = mono_class_from_mono_type (type->type);
3350 refklass = mono_class_from_mono_type (reftype->type);
3352 mono_ptr_array_init (tmp_array, 2);
3355 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3356 mono_ptr_array_destroy (tmp_array);
3357 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3361 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3362 guint32 flags = mono_field_get_flags (field);
3364 if (mono_field_is_deleted_with_flags (field, flags))
3366 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3367 if (bflags & BFLAGS_Public)
3369 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3370 if (bflags & BFLAGS_NonPublic) {
3377 if (flags & FIELD_ATTRIBUTE_STATIC) {
3378 if (bflags & BFLAGS_Static)
3379 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3382 if (bflags & BFLAGS_Instance)
3388 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3389 mono_ptr_array_append (tmp_array, member);
3391 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3394 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3396 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3397 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3399 mono_ptr_array_destroy (tmp_array);
3405 method_nonpublic (MonoMethod* method, gboolean start_klass)
3407 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3408 case METHOD_ATTRIBUTE_ASSEM:
3409 return (start_klass || mono_defaults.generic_ilist_class);
3410 case METHOD_ATTRIBUTE_PRIVATE:
3412 case METHOD_ATTRIBUTE_PUBLIC:
3420 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3422 static MonoClass *MethodInfo_array;
3424 MonoClass *startklass, *klass, *refklass;
3429 int i, len, match, nslots;
3430 /*FIXME, use MonoBitSet*/
3431 guint32 method_slots_default [8];
3432 guint32 *method_slots = NULL;
3433 gchar *mname = NULL;
3434 int (*compare_func) (const char *s1, const char *s2) = NULL;
3435 MonoVTable *array_vtable;
3437 MonoPtrArray tmp_array;
3439 mono_ptr_array_init (tmp_array, 4);
3441 if (!MethodInfo_array) {
3442 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3443 mono_memory_barrier ();
3444 MethodInfo_array = klass;
3447 domain = ((MonoObject *)type)->vtable->domain;
3448 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3449 if (type->type->byref)
3450 return mono_array_new_specific (array_vtable, 0);
3451 klass = startklass = mono_class_from_mono_type (type->type);
3452 refklass = mono_class_from_mono_type (reftype->type);
3456 mname = mono_string_to_utf8 (name);
3457 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3460 /* An optimization for calls made from Delegate:CreateDelegate () */
3461 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3462 method = mono_get_delegate_invoke (klass);
3463 if (mono_loader_get_last_error ())
3466 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3468 res = mono_array_new_specific (array_vtable, 1);
3469 mono_array_setref (res, 0, member);
3474 mono_class_setup_vtable (klass);
3475 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3478 if (is_generic_parameter (type->type))
3479 nslots = mono_class_get_vtable_size (klass->parent);
3481 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3482 if (nslots >= sizeof (method_slots_default) * 8) {
3483 method_slots = g_new0 (guint32, nslots / 32 + 1);
3485 method_slots = method_slots_default;
3486 memset (method_slots, 0, sizeof (method_slots_default));
3489 mono_class_setup_vtable (klass);
3490 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3494 while ((method = mono_class_get_methods (klass, &iter))) {
3496 if (method->slot != -1) {
3497 g_assert (method->slot < nslots);
3498 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3500 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3501 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3504 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3506 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3507 if (bflags & BFLAGS_Public)
3509 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3515 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3516 if (bflags & BFLAGS_Static)
3517 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3520 if (bflags & BFLAGS_Instance)
3528 if (compare_func (mname, method->name))
3534 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3536 mono_ptr_array_append (tmp_array, member);
3538 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3542 if (method_slots != method_slots_default)
3543 g_free (method_slots);
3545 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3547 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3548 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3550 mono_ptr_array_destroy (tmp_array);
3555 if (method_slots != method_slots_default)
3556 g_free (method_slots);
3557 mono_ptr_array_destroy (tmp_array);
3558 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3559 ex = mono_class_get_exception_for_failure (klass);
3561 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3562 mono_loader_clear_error ();
3564 mono_raise_exception (ex);
3569 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3572 static MonoClass *System_Reflection_ConstructorInfo;
3573 MonoClass *startklass, *klass, *refklass;
3578 gpointer iter = NULL;
3579 MonoPtrArray tmp_array;
3581 MONO_ARCH_SAVE_REGS;
3583 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3585 domain = ((MonoObject *)type)->vtable->domain;
3586 if (type->type->byref)
3587 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3588 klass = startklass = mono_class_from_mono_type (type->type);
3589 refklass = mono_class_from_mono_type (reftype->type);
3591 if (!System_Reflection_ConstructorInfo)
3592 System_Reflection_ConstructorInfo = mono_class_from_name (
3593 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3596 while ((method = mono_class_get_methods (klass, &iter))) {
3598 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3600 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3601 if (bflags & BFLAGS_Public)
3604 if (bflags & BFLAGS_NonPublic)
3610 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3611 if (bflags & BFLAGS_Static)
3612 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3615 if (bflags & BFLAGS_Instance)
3621 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3623 mono_ptr_array_append (tmp_array, member);
3626 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3628 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3629 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3631 mono_ptr_array_destroy (tmp_array);
3637 property_hash (gconstpointer data)
3639 MonoProperty *prop = (MonoProperty*)data;
3641 return g_str_hash (prop->name);
3645 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3647 // Properties are hide-by-name-and-signature
3648 if (!g_str_equal (prop1->name, prop2->name))
3651 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3653 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3659 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3664 return method_nonpublic (accessor, start_klass);
3668 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3672 static MonoClass *System_Reflection_PropertyInfo;
3673 MonoClass *startklass, *klass;
3679 gchar *propname = NULL;
3680 int (*compare_func) (const char *s1, const char *s2) = NULL;
3682 GHashTable *properties = NULL;
3683 MonoPtrArray tmp_array;
3685 MONO_ARCH_SAVE_REGS;
3687 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3689 if (!System_Reflection_PropertyInfo)
3690 System_Reflection_PropertyInfo = mono_class_from_name (
3691 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3693 domain = ((MonoObject *)type)->vtable->domain;
3694 if (type->type->byref)
3695 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3696 klass = startklass = mono_class_from_mono_type (type->type);
3699 propname = mono_string_to_utf8 (name);
3700 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3703 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3705 mono_class_setup_vtable (klass);
3706 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3710 while ((prop = mono_class_get_properties (klass, &iter))) {
3716 flags = method->flags;
3719 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3720 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3721 if (bflags & BFLAGS_Public)
3723 } else if (bflags & BFLAGS_NonPublic) {
3724 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3725 property_accessor_nonpublic(prop->set, startklass == klass)) {
3732 if (flags & METHOD_ATTRIBUTE_STATIC) {
3733 if (bflags & BFLAGS_Static)
3734 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3737 if (bflags & BFLAGS_Instance)
3746 if (compare_func (propname, prop->name))
3750 if (g_hash_table_lookup (properties, prop))
3753 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3755 g_hash_table_insert (properties, prop, prop);
3757 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3760 g_hash_table_destroy (properties);
3763 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3764 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3765 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3767 mono_ptr_array_destroy (tmp_array);
3773 g_hash_table_destroy (properties);
3776 mono_ptr_array_destroy (tmp_array);
3778 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3779 ex = mono_class_get_exception_for_failure (klass);
3781 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3782 mono_loader_clear_error ();
3784 mono_raise_exception (ex);
3788 static MonoReflectionEvent *
3789 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3792 MonoClass *klass, *startklass;
3797 int (*compare_func) (const char *s1, const char *s2);
3799 MONO_ARCH_SAVE_REGS;
3801 event_name = mono_string_to_utf8 (name);
3802 if (type->type->byref)
3804 klass = startklass = mono_class_from_mono_type (type->type);
3805 domain = mono_object_domain (type);
3807 mono_class_init_or_throw (klass);
3809 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3811 if (klass->exception_type != MONO_EXCEPTION_NONE)
3812 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3815 while ((event = mono_class_get_events (klass, &iter))) {
3816 if (compare_func (event->name, event_name))
3819 method = event->add;
3821 method = event->remove;
3823 method = event->raise;
3825 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3826 if (!(bflags & BFLAGS_Public))
3829 if (!(bflags & BFLAGS_NonPublic))
3831 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3835 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3836 if (!(bflags & BFLAGS_Static))
3838 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3841 if (!(bflags & BFLAGS_Instance))
3845 if (!(bflags & BFLAGS_NonPublic))
3848 g_free (event_name);
3849 return mono_event_get_object (domain, startklass, event);
3852 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3855 g_free (event_name);
3860 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3864 static MonoClass *System_Reflection_EventInfo;
3865 MonoClass *startklass, *klass;
3872 MonoPtrArray tmp_array;
3874 MONO_ARCH_SAVE_REGS;
3876 mono_ptr_array_init (tmp_array, 4);
3878 if (!System_Reflection_EventInfo)
3879 System_Reflection_EventInfo = mono_class_from_name (
3880 mono_defaults.corlib, "System.Reflection", "EventInfo");
3882 domain = mono_object_domain (type);
3883 if (type->type->byref)
3884 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3885 klass = startklass = mono_class_from_mono_type (type->type);
3888 mono_class_setup_vtable (klass);
3889 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3893 while ((event = mono_class_get_events (klass, &iter))) {
3895 method = event->add;
3897 method = event->remove;
3899 method = event->raise;
3901 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3902 if (bflags & BFLAGS_Public)
3904 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3905 if (bflags & BFLAGS_NonPublic)
3910 if (bflags & BFLAGS_NonPublic)
3916 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3917 if (bflags & BFLAGS_Static)
3918 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3921 if (bflags & BFLAGS_Instance)
3926 if (bflags & BFLAGS_Instance)
3930 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3932 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3935 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3937 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3938 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3940 mono_ptr_array_destroy (tmp_array);
3945 mono_ptr_array_destroy (tmp_array);
3946 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3947 ex = mono_class_get_exception_for_failure (klass);
3949 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3950 mono_loader_clear_error ();
3952 mono_raise_exception (ex);
3956 static MonoReflectionType *
3957 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3965 MONO_ARCH_SAVE_REGS;
3968 mono_raise_exception (mono_get_exception_argument_null ("name"));
3970 domain = ((MonoObject *)type)->vtable->domain;
3971 if (type->type->byref)
3973 klass = mono_class_from_mono_type (type->type);
3975 str = mono_string_to_utf8 (name);
3978 if (klass->exception_type != MONO_EXCEPTION_NONE)
3979 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3982 * If a nested type is generic, return its generic type definition.
3983 * Note that this means that the return value is essentially a
3984 * nested type of the generic type definition of @klass.
3986 * A note in MSDN claims that a generic type definition can have
3987 * nested types that aren't generic. In any case, the container of that
3988 * nested type would be the generic type definition.
3990 if (klass->generic_class)
3991 klass = klass->generic_class->container_class;
3994 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3996 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3997 if (bflags & BFLAGS_Public)
4000 if (bflags & BFLAGS_NonPublic)
4005 if (strcmp (nested->name, str) == 0){
4007 return mono_type_get_object (domain, &nested->byval_arg);
4010 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4017 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4026 MonoPtrArray tmp_array;
4028 MONO_ARCH_SAVE_REGS;
4030 domain = ((MonoObject *)type)->vtable->domain;
4031 if (type->type->byref)
4032 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4033 klass = mono_class_from_mono_type (type->type);
4036 * If a nested type is generic, return its generic type definition.
4037 * Note that this means that the return value is essentially the set
4038 * of nested types of the generic type definition of @klass.
4040 * A note in MSDN claims that a generic type definition can have
4041 * nested types that aren't generic. In any case, the container of that
4042 * nested type would be the generic type definition.
4044 if (klass->generic_class)
4045 klass = klass->generic_class->container_class;
4047 mono_ptr_array_init (tmp_array, 1);
4049 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4051 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4052 if (bflags & BFLAGS_Public)
4055 if (bflags & BFLAGS_NonPublic)
4060 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4061 mono_ptr_array_append (tmp_array, member);
4064 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4066 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4067 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4069 mono_ptr_array_destroy (tmp_array);
4074 static MonoReflectionType*
4075 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4078 MonoType *type = NULL;
4079 MonoTypeNameParse info;
4080 gboolean type_resolve;
4082 MONO_ARCH_SAVE_REGS;
4084 /* On MS.NET, this does not fire a TypeResolve event */
4085 type_resolve = TRUE;
4086 str = mono_string_to_utf8 (name);
4087 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4088 if (!mono_reflection_parse_type (str, &info)) {
4090 mono_reflection_free_type_info (&info);
4091 if (throwOnError) /* uhm: this is a parse error, though... */
4092 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4093 /*g_print ("failed parse\n");*/
4097 if (info.assembly.name) {
4099 mono_reflection_free_type_info (&info);
4101 /* 1.0 and 2.0 throw different exceptions */
4102 if (mono_defaults.generic_ilist_class)
4103 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4105 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4110 if (module != NULL) {
4112 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4117 if (assembly->assembly->dynamic) {
4118 /* Enumerate all modules */
4119 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4123 if (abuilder->modules) {
4124 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4125 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4126 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4132 if (!type && abuilder->loaded_modules) {
4133 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4134 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4135 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4142 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4144 mono_reflection_free_type_info (&info);
4146 MonoException *e = NULL;
4149 e = mono_get_exception_type_load (name, NULL);
4151 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4152 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4154 mono_loader_clear_error ();
4157 mono_raise_exception (e);
4160 } else if (mono_loader_get_last_error ()) {
4162 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4163 mono_loader_clear_error ();
4166 if (type->type == MONO_TYPE_CLASS) {
4167 MonoClass *klass = mono_type_get_class (type);
4169 if (mono_is_security_manager_active () && !klass->exception_type)
4170 /* Some security problems are detected during generic vtable construction */
4171 mono_class_setup_vtable (klass);
4172 /* need to report exceptions ? */
4173 if (throwOnError && klass->exception_type) {
4174 /* report SecurityException (or others) that occured when loading the assembly */
4175 MonoException *exc = mono_class_get_exception_for_failure (klass);
4176 mono_loader_clear_error ();
4177 mono_raise_exception (exc);
4178 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4183 /* g_print ("got it\n"); */
4184 return mono_type_get_object (mono_object_domain (assembly), type);
4188 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4191 gchar *shadow_ini_file;
4194 /* Check for shadow-copied assembly */
4195 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4196 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4198 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4199 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4205 g_free (shadow_ini_file);
4206 if (content != NULL) {
4209 *filename = content;
4217 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4219 MonoDomain *domain = mono_object_domain (assembly);
4220 MonoAssembly *mass = assembly->assembly;
4221 MonoString *res = NULL;
4226 MONO_ARCH_SAVE_REGS;
4228 if (g_path_is_absolute (mass->image->name)) {
4229 absolute = g_strdup (mass->image->name);
4230 dirname = g_path_get_dirname (absolute);
4232 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4233 dirname = g_strdup (mass->basedir);
4236 replace_shadow_path (domain, dirname, &absolute);
4241 for (i = strlen (absolute) - 1; i >= 0; i--)
4242 if (absolute [i] == '\\')
4247 uri = g_filename_to_uri (absolute, NULL, NULL);
4249 const char *prepend = "file://";
4251 if (*absolute == '/' && *(absolute + 1) == '/') {
4254 prepend = "file:///";
4257 uri = g_strconcat (prepend, absolute, NULL);
4261 res = mono_string_new (domain, uri);
4269 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4271 MonoAssembly *mass = assembly->assembly;
4273 MONO_ARCH_SAVE_REGS;
4275 return mass->in_gac;
4278 static MonoReflectionAssembly*
4279 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4283 MonoImageOpenStatus status;
4285 MONO_ARCH_SAVE_REGS;
4287 name = mono_string_to_utf8 (mname);
4288 res = mono_assembly_load_with_partial_name (name, &status);
4294 return mono_assembly_get_object (mono_domain_get (), res);
4298 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4300 MonoDomain *domain = mono_object_domain (assembly);
4303 MONO_ARCH_SAVE_REGS;
4305 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4311 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4313 MONO_ARCH_SAVE_REGS;
4315 return assembly->assembly->ref_only;
4319 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4321 MonoDomain *domain = mono_object_domain (assembly);
4323 MONO_ARCH_SAVE_REGS;
4325 return mono_string_new (domain, assembly->assembly->image->version);
4328 static MonoReflectionMethod*
4329 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4331 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4333 MONO_ARCH_SAVE_REGS;
4337 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4340 static MonoReflectionModule*
4341 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4343 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4347 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4349 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4350 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4354 MONO_ARCH_SAVE_REGS;
4356 for (i = 0; i < table->rows; ++i) {
4357 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4358 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4364 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4366 static MonoClass *System_Version = NULL;
4367 static MonoMethod *create_version = NULL;
4371 if (!System_Version) {
4372 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4373 g_assert (System_Version);
4376 if (!create_version) {
4377 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4378 create_version = mono_method_desc_search_in_class (desc, System_Version);
4379 g_assert (create_version);
4380 mono_method_desc_free (desc);
4386 args [3] = &revision;
4387 result = mono_object_new (domain, System_Version);
4388 mono_runtime_invoke (create_version, result, args, NULL);
4394 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4396 static MonoClass *System_Reflection_AssemblyName;
4398 MonoDomain *domain = mono_object_domain (assembly);
4400 static MonoMethod *create_culture = NULL;
4401 MonoImage *image = assembly->assembly->image;
4404 MONO_ARCH_SAVE_REGS;
4406 if (!System_Reflection_AssemblyName)
4407 System_Reflection_AssemblyName = mono_class_from_name (
4408 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4410 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4413 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4415 if (count > 0 && !create_culture) {
4416 MonoMethodDesc *desc = mono_method_desc_new (
4417 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4418 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4419 g_assert (create_culture);
4420 mono_method_desc_free (desc);
4423 for (i = 0; i < count; i++) {
4424 MonoReflectionAssemblyName *aname;
4425 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4427 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4429 aname = (MonoReflectionAssemblyName *) mono_object_new (
4430 domain, System_Reflection_AssemblyName);
4432 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4434 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4435 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4436 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4437 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4438 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4439 aname->versioncompat = 1; /* SameMachine (default) */
4440 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4441 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4443 if (create_culture) {
4445 MonoBoolean assembly_ref = 1;
4446 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4447 args [1] = &assembly_ref;
4448 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4451 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4452 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4453 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4455 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4456 /* public key token isn't copied - the class library will
4457 automatically generate it from the public key if required */
4458 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4459 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4461 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4462 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4465 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4468 /* note: this function doesn't return the codebase on purpose (i.e. it can
4469 be used under partial trust as path information isn't present). */
4471 mono_array_setref (result, i, aname);
4482 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4484 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4486 mono_array_setref (info->res, info->idx, name);
4491 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4493 MonoImage *img = assembly->assembly->image;
4498 MONO_ARCH_SAVE_REGS;
4500 mono_image_lock (img);
4501 mono_image_init_name_cache (img);
4504 len = g_hash_table_size (img->name_cache);
4505 mono_image_unlock (img);
4507 /*we can't create objects holding the image lock */
4508 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4510 mono_image_lock (img);
4511 /*len might have changed, create a new array*/
4512 if (len != g_hash_table_size (img->name_cache))
4517 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4518 mono_image_unlock (img);
4523 /* move this in some file in mono/util/ */
4525 g_concat_dir_and_file (const char *dir, const char *file)
4527 g_return_val_if_fail (dir != NULL, NULL);
4528 g_return_val_if_fail (file != NULL, NULL);
4531 * If the directory name doesn't have a / on the end, we need
4532 * to add one so we get a proper path to the file
4534 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4535 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4537 return g_strconcat (dir, file, NULL);
4541 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4543 char *n = mono_string_to_utf8 (name);
4544 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4546 guint32 cols [MONO_MANIFEST_SIZE];
4547 guint32 impl, file_idx;
4551 MONO_ARCH_SAVE_REGS;
4553 for (i = 0; i < table->rows; ++i) {
4554 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4555 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4556 if (strcmp (val, n) == 0)
4560 if (i == table->rows)
4563 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4566 * this code should only be called after obtaining the
4567 * ResourceInfo and handling the other cases.
4569 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4570 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4572 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4577 module = assembly->assembly->image;
4579 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4581 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4585 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4587 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4589 guint32 cols [MONO_MANIFEST_SIZE];
4590 guint32 file_cols [MONO_FILE_SIZE];
4594 MONO_ARCH_SAVE_REGS;
4596 n = mono_string_to_utf8 (name);
4597 for (i = 0; i < table->rows; ++i) {
4598 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4599 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4600 if (strcmp (val, n) == 0)
4604 if (i == table->rows)
4607 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4608 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4611 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4612 case MONO_IMPLEMENTATION_FILE:
4613 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4614 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4615 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4616 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4617 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4618 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4621 info->location = RESOURCE_LOCATION_EMBEDDED;
4624 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4625 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4626 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4627 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4628 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4629 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4631 mono_raise_exception (ex);
4633 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4635 /* Obtain info recursively */
4636 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4637 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4640 case MONO_IMPLEMENTATION_EXP_TYPE:
4641 g_assert_not_reached ();
4650 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4652 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4653 MonoArray *result = NULL;
4658 MONO_ARCH_SAVE_REGS;
4660 /* check hash if needed */
4662 n = mono_string_to_utf8 (name);
4663 for (i = 0; i < table->rows; ++i) {
4664 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4665 if (strcmp (val, n) == 0) {
4668 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4669 fn = mono_string_new (mono_object_domain (assembly), n);
4671 return (MonoObject*)fn;
4679 for (i = 0; i < table->rows; ++i) {
4680 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4684 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4687 for (i = 0; i < table->rows; ++i) {
4688 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4689 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4690 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4691 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4696 return (MonoObject*)result;
4700 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4702 MonoDomain *domain = mono_domain_get();
4705 int i, j, file_count = 0;
4706 MonoImage **modules;
4707 guint32 module_count, real_module_count;
4708 MonoTableInfo *table;
4709 guint32 cols [MONO_FILE_SIZE];
4710 MonoImage *image = assembly->assembly->image;
4712 g_assert (image != NULL);
4713 g_assert (!assembly->assembly->dynamic);
4715 table = &image->tables [MONO_TABLE_FILE];
4716 file_count = table->rows;
4718 modules = image->modules;
4719 module_count = image->module_count;
4721 real_module_count = 0;
4722 for (i = 0; i < module_count; ++i)
4724 real_module_count ++;
4726 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4727 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4729 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4731 for (i = 0; i < module_count; ++i)
4733 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4737 for (i = 0; i < file_count; ++i, ++j) {
4738 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4739 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4740 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4742 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4744 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4745 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4747 mono_array_setref (res, j, mono_module_get_object (domain, m));
4754 static MonoReflectionMethod*
4755 ves_icall_GetCurrentMethod (void)
4757 MonoMethod *m = mono_method_get_last_managed ();
4759 while (m->is_inflated)
4760 m = ((MonoMethodInflated*)m)->declaring;
4762 return mono_method_get_object (mono_domain_get (), m, NULL);
4767 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4770 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4771 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4772 //method is inflated, we should inflate it on the other class
4773 MonoGenericContext ctx;
4774 ctx.method_inst = inflated->context.method_inst;
4775 ctx.class_inst = inflated->context.class_inst;
4776 if (klass->generic_class)
4777 ctx.class_inst = klass->generic_class->context.class_inst;
4778 else if (klass->generic_container)
4779 ctx.class_inst = klass->generic_container->context.class_inst;
4780 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4783 mono_class_setup_methods (method->klass);
4784 if (method->klass->exception_type)
4786 for (i = 0; i < method->klass->method.count; ++i) {
4787 if (method->klass->methods [i] == method) {
4792 mono_class_setup_methods (klass);
4793 if (klass->exception_type)
4795 g_assert (offset >= 0 && offset < klass->method.count);
4796 return klass->methods [offset];
4799 static MonoReflectionMethod*
4800 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4804 klass = mono_class_from_mono_type (type);
4805 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4807 if (method->klass != klass) {
4808 method = mono_method_get_equivalent_method (method, klass);
4813 klass = method->klass;
4814 return mono_method_get_object (mono_domain_get (), method, klass);
4817 static MonoReflectionMethod*
4818 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4820 return mono_method_get_object (mono_domain_get (), method, NULL);
4823 static MonoReflectionMethodBody*
4824 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4826 return mono_method_body_get_object (mono_domain_get (), method);
4829 static MonoReflectionAssembly*
4830 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4832 MonoMethod *dest = NULL;
4834 MONO_ARCH_SAVE_REGS;
4836 mono_stack_walk_no_il (get_executing, &dest);
4837 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4841 static MonoReflectionAssembly*
4842 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4844 MonoDomain* domain = mono_domain_get ();
4846 MONO_ARCH_SAVE_REGS;
4848 if (!domain->entry_assembly)
4851 return mono_assembly_get_object (domain, domain->entry_assembly);
4854 static MonoReflectionAssembly*
4855 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4860 MONO_ARCH_SAVE_REGS;
4863 mono_stack_walk_no_il (get_executing, &dest);
4865 mono_stack_walk_no_il (get_caller, &dest);
4868 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4872 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4873 gboolean assembly_qualified)
4875 MonoDomain *domain = mono_object_domain (object);
4876 MonoTypeNameFormat format;
4881 format = assembly_qualified ?
4882 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4883 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4885 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4887 name = mono_type_get_name_full (object->type, format);
4891 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4896 res = mono_string_new (domain, name);
4903 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4905 MonoClass *klass = mono_class_from_mono_type (this->type);
4906 mono_class_init_or_throw (klass);
4907 return mono_security_core_clr_class_level (klass);
4911 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4913 static MonoMethod *create_culture = NULL;
4916 const char *pkey_ptr;
4918 MonoBoolean assembly_ref = 0;
4920 MONO_ARCH_SAVE_REGS;
4922 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4923 aname->major = name->major;
4924 aname->minor = name->minor;
4925 aname->build = name->build;
4926 aname->flags = name->flags;
4927 aname->revision = name->revision;
4928 aname->hashalg = name->hash_alg;
4929 aname->versioncompat = 1; /* SameMachine (default) */
4931 if (by_default_version)
4932 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4935 if (absolute != NULL && *absolute != '\0') {
4936 const gchar *prepend = "file://";
4939 codebase = g_strdup (absolute);
4944 for (i = strlen (codebase) - 1; i >= 0; i--)
4945 if (codebase [i] == '\\')
4948 if (*codebase == '/' && *(codebase + 1) == '/') {
4951 prepend = "file:///";
4955 result = g_strconcat (prepend, codebase, NULL);
4961 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4965 if (!create_culture) {
4966 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4967 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4968 g_assert (create_culture);
4969 mono_method_desc_free (desc);
4972 if (name->culture) {
4973 args [0] = mono_string_new (domain, name->culture);
4974 args [1] = &assembly_ref;
4975 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4978 if (name->public_key) {
4979 pkey_ptr = (char*)name->public_key;
4980 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4982 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4983 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4984 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4985 } else if (default_publickey) {
4986 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4987 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4990 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4991 if (name->public_key_token [0]) {
4995 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4996 p = mono_array_addr (aname->keyToken, char, 0);
4998 for (i = 0, j = 0; i < 8; i++) {
4999 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5000 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5003 } else if (default_token) {
5004 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5009 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5011 MonoDomain *domain = mono_object_domain (assembly);
5012 MonoAssembly *mass = assembly->assembly;
5016 name = g_strdup_printf (
5017 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5019 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5020 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5021 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5022 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5024 res = mono_string_new (domain, name);
5031 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5034 MonoAssembly *mass = assembly->assembly;
5036 MONO_ARCH_SAVE_REGS;
5038 if (g_path_is_absolute (mass->image->name)) {
5039 fill_reflection_assembly_name (mono_object_domain (assembly),
5040 aname, &mass->aname, mass->image->name, TRUE,
5044 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5046 fill_reflection_assembly_name (mono_object_domain (assembly),
5047 aname, &mass->aname, absolute, TRUE, TRUE,
5054 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5057 MonoImageOpenStatus status = MONO_IMAGE_OK;
5060 MonoAssemblyName name;
5063 MONO_ARCH_SAVE_REGS;
5065 filename = mono_string_to_utf8 (fname);
5067 dirname = g_path_get_dirname (filename);
5068 replace_shadow_path (mono_domain_get (), dirname, &filename);
5071 image = mono_image_open (filename, &status);
5077 if (status == MONO_IMAGE_IMAGE_INVALID)
5078 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5080 exc = mono_get_exception_file_not_found2 (NULL, fname);
5081 mono_raise_exception (exc);
5084 res = mono_assembly_fill_assembly_name (image, &name);
5086 mono_image_close (image);
5088 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5091 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5095 mono_image_close (image);
5099 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5100 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5102 MonoBoolean result = FALSE;
5103 MonoDeclSecurityEntry entry;
5105 /* SecurityAction.RequestMinimum */
5106 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5107 *minimum = entry.blob;
5108 *minLength = entry.size;
5111 /* SecurityAction.RequestOptional */
5112 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5113 *optional = entry.blob;
5114 *optLength = entry.size;
5117 /* SecurityAction.RequestRefuse */
5118 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5119 *refused = entry.blob;
5120 *refLength = entry.size;
5128 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5132 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5134 guint32 attrs, visibility;
5136 /* we start the count from 1 because we skip the special type <Module> */
5139 for (i = 1; i < tdef->rows; ++i) {
5140 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5141 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5142 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5146 count = tdef->rows - 1;
5148 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5149 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5151 for (i = 1; i < tdef->rows; ++i) {
5152 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5153 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5154 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5155 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5157 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5159 MonoLoaderError *error;
5162 error = mono_loader_get_last_error ();
5163 g_assert (error != NULL);
5165 ex = mono_loader_error_prepare_exception (error);
5166 mono_array_setref (*exceptions, count, ex);
5168 if (mono_loader_get_last_error ())
5169 mono_loader_clear_error ();
5178 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5180 MonoArray *res = NULL;
5181 MonoArray *exceptions = NULL;
5182 MonoImage *image = NULL;
5183 MonoTableInfo *table = NULL;
5186 int i, len, ex_count;
5188 MONO_ARCH_SAVE_REGS;
5190 domain = mono_object_domain (assembly);
5192 g_assert (!assembly->assembly->dynamic);
5193 image = assembly->assembly->image;
5194 table = &image->tables [MONO_TABLE_FILE];
5195 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5197 /* Append data from all modules in the assembly */
5198 for (i = 0; i < table->rows; ++i) {
5199 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5200 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5203 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5204 /* Append the new types to the end of the array */
5205 if (mono_array_length (res2) > 0) {
5207 MonoArray *res3, *ex3;
5209 len1 = mono_array_length (res);
5210 len2 = mono_array_length (res2);
5212 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5213 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5214 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5217 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5218 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5219 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5226 /* the ReflectionTypeLoadException must have all the types (Types property),
5227 * NULL replacing types which throws an exception. The LoaderException must
5228 * contain all exceptions for NULL items.
5231 len = mono_array_length (res);
5234 for (i = 0; i < len; i++) {
5235 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5239 klass = mono_type_get_class (t->type);
5240 if ((klass != NULL) && klass->exception_type) {
5241 /* keep the class in the list */
5242 list = g_list_append (list, klass);
5243 /* and replace Type with NULL */
5244 mono_array_setref (res, i, NULL);
5251 if (list || ex_count) {
5253 MonoException *exc = NULL;
5254 MonoArray *exl = NULL;
5255 int j, length = g_list_length (list) + ex_count;
5257 mono_loader_clear_error ();
5259 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5260 /* Types for which mono_class_get () succeeded */
5261 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5262 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5263 mono_array_setref (exl, i, exc);
5265 /* Types for which it don't */
5266 for (j = 0; j < mono_array_length (exceptions); ++j) {
5267 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5269 g_assert (i < length);
5270 mono_array_setref (exl, i, exc);
5277 exc = mono_get_exception_reflection_type_load (res, exl);
5278 mono_loader_clear_error ();
5279 mono_raise_exception (exc);
5286 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5288 MonoAssemblyName aname;
5289 MonoDomain *domain = mono_object_domain (name);
5291 gboolean is_version_defined;
5292 gboolean is_token_defined;
5294 aname.public_key = NULL;
5295 val = mono_string_to_utf8 (assname);
5296 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5297 g_free ((guint8*) aname.public_key);
5302 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5303 FALSE, is_token_defined);
5305 mono_assembly_name_free (&aname);
5306 g_free ((guint8*) aname.public_key);
5312 static MonoReflectionType*
5313 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5315 MonoDomain *domain = mono_object_domain (module);
5318 MONO_ARCH_SAVE_REGS;
5320 g_assert (module->image);
5322 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5323 /* These images do not have a global type */
5326 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5327 return mono_type_get_object (domain, &klass->byval_arg);
5331 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5333 /*if (module->image)
5334 mono_image_close (module->image);*/
5338 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5340 MonoDomain *domain = mono_object_domain (module);
5342 MONO_ARCH_SAVE_REGS;
5344 g_assert (module->image);
5345 return mono_string_new (domain, module->image->guid);
5349 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5352 if (module->image && module->image->is_module_handle)
5353 return module->image->raw_data;
5356 return (gpointer) (-1);
5360 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5362 if (image->dynamic) {
5363 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5364 *pe_kind = dyn->pe_kind;
5365 *machine = dyn->machine;
5368 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5369 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5374 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5376 return (image->md_version_major << 16) | (image->md_version_minor);
5380 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5382 MonoArray *exceptions;
5385 MONO_ARCH_SAVE_REGS;
5388 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5390 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5391 for (i = 0; i < mono_array_length (exceptions); ++i) {
5392 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5394 mono_raise_exception (ex);
5401 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5403 guint32 cols [MONO_MEMBERREF_SIZE];
5405 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5406 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5407 mono_metadata_decode_blob_size (sig, &sig);
5408 return (*sig != 0x6);
5412 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5415 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5416 mono_array_addr (type_args, MonoType*, 0));
5418 context->class_inst = NULL;
5420 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5421 mono_array_addr (method_args, MonoType*, 0));
5423 context->method_inst = NULL;
5427 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5430 int table = mono_metadata_token_table (token);
5431 int index = mono_metadata_token_index (token);
5432 MonoGenericContext context;
5434 *error = ResolveTokenError_Other;
5436 /* Validate token */
5437 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5438 (table != MONO_TABLE_TYPESPEC)) {
5439 *error = ResolveTokenError_BadTable;
5443 if (image->dynamic) {
5444 if (type_args || method_args)
5445 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5446 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5449 return &klass->byval_arg;
5452 if ((index <= 0) || (index > image->tables [table].rows)) {
5453 *error = ResolveTokenError_OutOfRange;
5457 init_generic_context_from_args (&context, type_args, method_args);
5458 klass = mono_class_get_full (image, token, &context);
5460 if (mono_loader_get_last_error ())
5461 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5464 return &klass->byval_arg;
5470 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5472 int table = mono_metadata_token_table (token);
5473 int index = mono_metadata_token_index (token);
5474 MonoGenericContext context;
5477 *error = ResolveTokenError_Other;
5479 /* Validate token */
5480 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5481 (table != MONO_TABLE_MEMBERREF)) {
5482 *error = ResolveTokenError_BadTable;
5486 if (image->dynamic) {
5487 if (type_args || method_args)
5488 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5489 /* FIXME: validate memberref token type */
5490 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5493 if ((index <= 0) || (index > image->tables [table].rows)) {
5494 *error = ResolveTokenError_OutOfRange;
5497 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5498 *error = ResolveTokenError_BadTable;
5502 init_generic_context_from_args (&context, type_args, method_args);
5503 method = mono_get_method_full (image, token, NULL, &context);
5505 if (mono_loader_get_last_error ())
5506 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5512 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5514 int index = mono_metadata_token_index (token);
5516 *error = ResolveTokenError_Other;
5518 /* Validate token */
5519 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5520 *error = ResolveTokenError_BadTable;
5525 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5527 if ((index <= 0) || (index >= image->heap_us.size)) {
5528 *error = ResolveTokenError_OutOfRange;
5532 /* FIXME: What to do if the index points into the middle of a string ? */
5534 return mono_ldstr (mono_domain_get (), image, index);
5537 static MonoClassField*
5538 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5541 int table = mono_metadata_token_table (token);
5542 int index = mono_metadata_token_index (token);
5543 MonoGenericContext context;
5544 MonoClassField *field;
5546 *error = ResolveTokenError_Other;
5548 /* Validate token */
5549 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5550 *error = ResolveTokenError_BadTable;
5554 if (image->dynamic) {
5555 if (type_args || method_args)
5556 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5557 /* FIXME: validate memberref token type */
5558 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5561 if ((index <= 0) || (index > image->tables [table].rows)) {
5562 *error = ResolveTokenError_OutOfRange;
5565 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5566 *error = ResolveTokenError_BadTable;
5570 init_generic_context_from_args (&context, type_args, method_args);
5571 field = mono_field_from_token (image, token, &klass, &context);
5573 if (mono_loader_get_last_error ())
5574 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5581 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5583 int table = mono_metadata_token_table (token);
5585 *error = ResolveTokenError_Other;
5588 case MONO_TABLE_TYPEDEF:
5589 case MONO_TABLE_TYPEREF:
5590 case MONO_TABLE_TYPESPEC: {
5591 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5593 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5597 case MONO_TABLE_METHOD:
5598 case MONO_TABLE_METHODSPEC: {
5599 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5601 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5605 case MONO_TABLE_FIELD: {
5606 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5608 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5612 case MONO_TABLE_MEMBERREF:
5613 if (mono_metadata_memberref_is_method (image, token)) {
5614 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5616 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5621 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5623 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5630 *error = ResolveTokenError_BadTable;
5637 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5639 int table = mono_metadata_token_table (token);
5640 int idx = mono_metadata_token_index (token);
5641 MonoTableInfo *tables = image->tables;
5646 *error = ResolveTokenError_OutOfRange;
5648 /* FIXME: Support other tables ? */
5649 if (table != MONO_TABLE_STANDALONESIG)
5655 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5658 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5660 ptr = mono_metadata_blob_heap (image, sig);
5661 len = mono_metadata_decode_blob_size (ptr, &ptr);
5663 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5664 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5668 static MonoReflectionType*
5669 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5672 int isbyref = 0, rank;
5673 char *str = mono_string_to_utf8 (smodifiers);
5676 MONO_ARCH_SAVE_REGS;
5678 klass = mono_class_from_mono_type (tb->type.type);
5680 /* logic taken from mono_reflection_parse_type(): keep in sync */
5684 if (isbyref) { /* only one level allowed by the spec */
5691 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5694 klass = mono_ptr_class_get (&klass->byval_arg);
5695 mono_class_init (klass);
5706 else if (*p != '*') { /* '*' means unknown lower bound */
5717 klass = mono_array_class_get (klass, rank);
5718 mono_class_init (klass);
5725 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5729 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5734 MONO_ARCH_SAVE_REGS;
5737 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5743 check_for_invalid_type (MonoClass *klass)
5747 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5750 name = mono_type_get_full_name (klass);
5751 str = mono_string_new (mono_domain_get (), name);
5753 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5756 static MonoReflectionType *
5757 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5759 MonoClass *klass, *aklass;
5761 MONO_ARCH_SAVE_REGS;
5763 klass = mono_class_from_mono_type (type->type);
5764 mono_class_init_or_throw (klass);
5765 check_for_invalid_type (klass);
5767 if (rank == 0) //single dimentional array
5768 aklass = mono_array_class_get (klass, 1);
5770 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5772 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5775 static MonoReflectionType *
5776 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5780 MONO_ARCH_SAVE_REGS;
5782 klass = mono_class_from_mono_type (type->type);
5783 mono_class_init_or_throw (klass);
5784 check_for_invalid_type (klass);
5786 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5789 static MonoReflectionType *
5790 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5792 MonoClass *klass, *pklass;
5794 klass = mono_class_from_mono_type (type->type);
5795 mono_class_init_or_throw (klass);
5796 check_for_invalid_type (klass);
5798 pklass = mono_ptr_class_get (type->type);
5800 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5804 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5805 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5807 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5808 MonoObject *delegate;
5810 MonoMethod *method = info->method;
5812 MONO_ARCH_SAVE_REGS;
5814 mono_class_init_or_throw (delegate_class);
5816 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5818 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5819 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5823 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5825 if (method->dynamic) {
5826 /* Creating a trampoline would leak memory */
5827 func = mono_compile_method (method);
5829 func = mono_create_ftnptr (mono_domain_get (),
5830 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5833 mono_delegate_ctor_with_method (delegate, target, func, method);
5839 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5841 /* Reset the invoke impl to the default one */
5842 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5846 * Magic number to convert a time which is relative to
5847 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5849 #define EPOCH_ADJUST ((guint64)62135596800LL)
5852 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5854 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5857 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5859 convert_to_absolute_date(SYSTEMTIME *date)
5861 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5862 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5863 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5864 /* from the calendar FAQ */
5865 int a = (14 - date->wMonth) / 12;
5866 int y = date->wYear - a;
5867 int m = date->wMonth + 12 * a - 2;
5868 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5870 /* d is now the day of the week for the first of the month (0 == Sunday) */
5872 int day_of_week = date->wDayOfWeek;
5874 /* set day_in_month to the first day in the month which falls on day_of_week */
5875 int day_in_month = 1 + (day_of_week - d);
5876 if (day_in_month <= 0)
5879 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5880 date->wDay = day_in_month + (date->wDay - 1) * 7;
5881 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5888 * Return's the offset from GMT of a local time.
5890 * tm is a local time
5891 * t is the same local time as seconds.
5894 gmt_offset(struct tm *tm, time_t t)
5896 #if defined (HAVE_TM_GMTOFF)
5897 return tm->tm_gmtoff;
5902 g.tm_isdst = tm->tm_isdst;
5904 return (int)difftime(t, t2);
5909 * This is heavily based on zdump.c from glibc 2.2.
5911 * * data[0]: start of daylight saving time (in DateTime ticks).
5912 * * data[1]: end of daylight saving time (in DateTime ticks).
5913 * * data[2]: utcoffset (in TimeSpan ticks).
5914 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5915 * * name[0]: name of this timezone when not daylight saving.
5916 * * name[1]: name of this timezone when daylight saving.
5918 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5919 * the class library allows years between 1 and 9999.
5921 * Returns true on success and zero on failure.
5924 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5927 MonoDomain *domain = mono_domain_get ();
5928 struct tm start, tt;
5932 int is_daylight = 0, day;
5935 MONO_ARCH_SAVE_REGS;
5937 MONO_CHECK_ARG_NULL (data);
5938 MONO_CHECK_ARG_NULL (names);
5940 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5941 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5944 * no info is better than crashing: we'll need our own tz data
5945 * to make this work properly, anyway. The range is probably
5946 * reduced to 1970 .. 2037 because that is what mktime is
5947 * guaranteed to support (we get into an infinite loop
5951 memset (&start, 0, sizeof (start));
5954 start.tm_year = year-1900;
5956 t = mktime (&start);
5958 if ((year < 1970) || (year > 2037) || (t == -1)) {
5960 tt = *localtime (&t);
5961 strftime (tzone, sizeof (tzone), "%Z", &tt);
5962 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5963 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5967 gmtoff = gmt_offset (&start, t);
5969 /* For each day of the year, calculate the tm_gmtoff. */
5970 for (day = 0; day < 365; day++) {
5973 tt = *localtime (&t);
5975 /* Daylight saving starts or ends here. */
5976 if (gmt_offset (&tt, t) != gmtoff) {
5980 /* Try to find the exact hour when daylight saving starts/ends. */
5984 tt1 = *localtime (&t1);
5985 } while (gmt_offset (&tt1, t1) != gmtoff);
5987 /* Try to find the exact minute when daylight saving starts/ends. */
5990 tt1 = *localtime (&t1);
5991 } while (gmt_offset (&tt1, t1) == gmtoff);
5993 strftime (tzone, sizeof (tzone), "%Z", &tt);
5995 /* Write data, if we're already in daylight saving, we're done. */
5997 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5998 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6001 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6002 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6006 /* This is only set once when we enter daylight saving. */
6007 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6008 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6010 gmtoff = gmt_offset (&tt, t);
6015 strftime (tzone, sizeof (tzone), "%Z", &tt);
6016 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6017 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6018 mono_array_set ((*data), gint64, 0, 0);
6019 mono_array_set ((*data), gint64, 1, 0);
6020 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6021 mono_array_set ((*data), gint64, 3, 0);
6026 MonoDomain *domain = mono_domain_get ();
6027 TIME_ZONE_INFORMATION tz_info;
6032 tz_id = GetTimeZoneInformation (&tz_info);
6033 if (tz_id == TIME_ZONE_ID_INVALID)
6036 MONO_CHECK_ARG_NULL (data);
6037 MONO_CHECK_ARG_NULL (names);
6039 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6040 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6042 for (i = 0; i < 32; ++i)
6043 if (!tz_info.DaylightName [i])
6045 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6046 for (i = 0; i < 32; ++i)
6047 if (!tz_info.StandardName [i])
6049 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6051 if ((year <= 1601) || (year > 30827)) {
6053 * According to MSDN, the MS time functions can't handle dates outside
6059 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6060 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6061 tz_info.StandardDate.wYear = year;
6062 convert_to_absolute_date(&tz_info.StandardDate);
6063 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6068 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6069 tz_info.DaylightDate.wYear = year;
6070 convert_to_absolute_date(&tz_info.DaylightDate);
6071 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6076 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6078 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6079 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6086 ves_icall_System_Object_obj_address (MonoObject *this)
6088 MONO_ARCH_SAVE_REGS;
6095 static inline gint32
6096 mono_array_get_byte_length (MonoArray *array)
6102 klass = array->obj.vtable->klass;
6104 if (array->bounds == NULL)
6105 length = array->max_length;
6108 for (i = 0; i < klass->rank; ++ i)
6109 length *= array->bounds [i].length;
6112 switch (klass->element_class->byval_arg.type) {
6115 case MONO_TYPE_BOOLEAN:
6119 case MONO_TYPE_CHAR:
6127 return length * sizeof (gpointer);
6138 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6140 MONO_ARCH_SAVE_REGS;
6142 return mono_array_get_byte_length (array);
6146 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6148 MONO_ARCH_SAVE_REGS;
6150 return mono_array_get (array, gint8, idx);
6154 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6156 MONO_ARCH_SAVE_REGS;
6158 mono_array_set (array, gint8, idx, value);
6162 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6164 guint8 *src_buf, *dest_buf;
6166 MONO_ARCH_SAVE_REGS;
6168 /* watch out for integer overflow */
6169 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6172 src_buf = (guint8 *)src->vector + src_offset;
6173 dest_buf = (guint8 *)dest->vector + dest_offset;
6176 memcpy (dest_buf, src_buf, count);
6178 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6184 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6186 MonoDomain *domain = mono_object_domain (this);
6188 MonoRealProxy *rp = ((MonoRealProxy *)this);
6189 MonoTransparentProxy *tp;
6193 MONO_ARCH_SAVE_REGS;
6195 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6196 tp = (MonoTransparentProxy*) res;
6198 MONO_OBJECT_SETREF (tp, rp, rp);
6199 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6200 klass = mono_class_from_mono_type (type);
6202 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6203 tp->remote_class = mono_remote_class (domain, class_name, klass);
6205 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6209 static MonoReflectionType *
6210 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6212 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6215 /* System.Environment */
6218 ves_icall_System_Environment_get_UserName (void)
6220 MONO_ARCH_SAVE_REGS;
6222 /* using glib is more portable */
6223 return mono_string_new (mono_domain_get (), g_get_user_name ());
6228 ves_icall_System_Environment_get_MachineName (void)
6230 #if defined (HOST_WIN32)
6235 len = MAX_COMPUTERNAME_LENGTH + 1;
6236 buf = g_new (gunichar2, len);
6239 if (GetComputerName (buf, (PDWORD) &len))
6240 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6244 #elif !defined(DISABLE_SOCKETS)
6248 if (gethostname (buf, sizeof (buf)) == 0)
6249 result = mono_string_new (mono_domain_get (), buf);
6255 return mono_string_new (mono_domain_get (), "mono");
6260 ves_icall_System_Environment_get_Platform (void)
6262 #if defined (TARGET_WIN32)
6265 #elif defined(__MACH__)
6268 // For compatibility with our client code, this will be 4 for a while.
6269 // We will eventually move to 6 to match .NET, but it requires all client
6270 // code to be updated and the documentation everywhere to be updated
6281 ves_icall_System_Environment_get_NewLine (void)
6283 MONO_ARCH_SAVE_REGS;
6285 #if defined (HOST_WIN32)
6286 return mono_string_new (mono_domain_get (), "\r\n");
6288 return mono_string_new (mono_domain_get (), "\n");
6293 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6298 MONO_ARCH_SAVE_REGS;
6303 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6304 value = g_getenv (utf8_name);
6311 return mono_string_new (mono_domain_get (), value);
6315 * There is no standard way to get at environ.
6318 #ifndef __MINGW32_VERSION
6319 #if defined(__APPLE__) && !defined (__arm__)
6320 /* Apple defines this in crt_externs.h but doesn't provide that header for
6321 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6322 * in fact exist on all implementations (so far)
6324 gchar ***_NSGetEnviron(void);
6325 #define environ (*_NSGetEnviron())
6334 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6345 env_strings = GetEnvironmentStrings();
6348 env_string = env_strings;
6349 while (*env_string != '\0') {
6350 /* weird case that MS seems to skip */
6351 if (*env_string != '=')
6353 while (*env_string != '\0')
6359 domain = mono_domain_get ();
6360 names = mono_array_new (domain, mono_defaults.string_class, n);
6364 env_string = env_strings;
6365 while (*env_string != '\0') {
6366 /* weird case that MS seems to skip */
6367 if (*env_string != '=') {
6368 equal_str = wcschr(env_string, '=');
6369 g_assert(equal_str);
6370 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6371 mono_array_setref (names, n, str);
6374 while (*env_string != '\0')
6379 FreeEnvironmentStrings (env_strings);
6391 MONO_ARCH_SAVE_REGS;
6394 for (e = environ; *e != 0; ++ e)
6397 domain = mono_domain_get ();
6398 names = mono_array_new (domain, mono_defaults.string_class, n);
6401 for (e = environ; *e != 0; ++ e) {
6402 parts = g_strsplit (*e, "=", 2);
6404 str = mono_string_new (domain, *parts);
6405 mono_array_setref (names, n, str);
6418 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6420 #if !GLIB_CHECK_VERSION(2,4,0)
6421 #define g_setenv(a,b,c) setenv(a,b,c)
6422 #define g_unsetenv(a) unsetenv(a)
6426 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6431 gunichar2 *utf16_name, *utf16_value;
6433 gchar *utf8_name, *utf8_value;
6436 MONO_ARCH_SAVE_REGS;
6439 utf16_name = mono_string_to_utf16 (name);
6440 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6441 SetEnvironmentVariable (utf16_name, NULL);
6442 g_free (utf16_name);
6446 utf16_value = mono_string_to_utf16 (value);
6448 SetEnvironmentVariable (utf16_name, utf16_value);
6450 g_free (utf16_name);
6451 g_free (utf16_value);
6453 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6455 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6456 g_unsetenv (utf8_name);
6461 utf8_value = mono_string_to_utf8_checked (value, &error);
6462 if (!mono_error_ok (&error)) {
6464 mono_error_raise_exception (&error);
6466 g_setenv (utf8_name, utf8_value, TRUE);
6469 g_free (utf8_value);
6474 ves_icall_System_Environment_Exit (int result)
6476 MONO_ARCH_SAVE_REGS;
6478 mono_threads_set_shutting_down ();
6480 mono_runtime_set_shutting_down ();
6482 /* This will kill the tp threads which cannot be suspended */
6483 mono_thread_pool_cleanup ();
6485 /* Suspend all managed threads since the runtime is going away */
6486 mono_thread_suspend_all_other_threads ();
6488 mono_runtime_quit ();
6490 /* we may need to do some cleanup here... */
6495 ves_icall_System_Environment_GetGacPath (void)
6497 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6501 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6503 #if defined (HOST_WIN32)
6504 #ifndef CSIDL_FLAG_CREATE
6505 #define CSIDL_FLAG_CREATE 0x8000
6508 WCHAR path [MAX_PATH];
6509 /* Create directory if no existing */
6510 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6514 return mono_string_new_utf16 (mono_domain_get (), path, len);
6517 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6519 return mono_string_new (mono_domain_get (), "");
6523 ves_icall_System_Environment_GetLogicalDrives (void)
6525 gunichar2 buf [256], *ptr, *dname;
6527 guint initial_size = 127, size = 128;
6530 MonoString *drivestr;
6531 MonoDomain *domain = mono_domain_get ();
6534 MONO_ARCH_SAVE_REGS;
6539 while (size > initial_size) {
6540 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6541 if (size > initial_size) {
6544 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6545 initial_size = size;
6559 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6564 while (*u16) { u16++; len ++; }
6565 drivestr = mono_string_new_utf16 (domain, dname, len);
6566 mono_array_setref (result, ndrives++, drivestr);
6577 ves_icall_System_Environment_InternalGetHome (void)
6579 MONO_ARCH_SAVE_REGS;
6581 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6584 static const char *encodings [] = {
6586 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6587 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6588 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6590 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6591 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6592 "x_unicode_2_0_utf_7",
6594 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6595 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6597 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6600 "unicodefffe", "utf_16be",
6607 * Returns the internal codepage, if the value of "int_code_page" is
6608 * 1 at entry, and we can not compute a suitable code page number,
6609 * returns the code page as a string
6612 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6617 char *codepage = NULL;
6619 int want_name = *int_code_page;
6622 *int_code_page = -1;
6623 MONO_ARCH_SAVE_REGS;
6625 g_get_charset (&cset);
6626 c = codepage = strdup (cset);
6627 for (c = codepage; *c; c++){
6628 if (isascii (*c) && isalpha (*c))
6633 /* g_print ("charset: %s\n", cset); */
6635 /* handle some common aliases */
6638 for (i = 0; p != 0; ){
6639 if ((gssize) p < 7){
6641 p = encodings [++i];
6644 if (strcmp (p, codepage) == 0){
6645 *int_code_page = code;
6648 p = encodings [++i];
6651 if (strstr (codepage, "utf_8") != NULL)
6652 *int_code_page |= 0x10000000;
6655 if (want_name && *int_code_page == -1)
6656 return mono_string_new (mono_domain_get (), cset);
6662 ves_icall_System_Environment_get_HasShutdownStarted (void)
6664 if (mono_runtime_is_shutting_down ())
6667 if (mono_domain_is_unloading (mono_domain_get ()))
6674 ves_icall_System_Environment_BroadcastSettingChange (void)
6677 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6682 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6683 MonoReflectionMethod *method,
6684 MonoArray *out_args)
6686 MONO_ARCH_SAVE_REGS;
6688 mono_message_init (mono_object_domain (this), this, method, out_args);
6692 ves_icall_IsTransparentProxy (MonoObject *proxy)
6694 MONO_ARCH_SAVE_REGS;
6699 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6705 static MonoReflectionMethod *
6706 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6707 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6711 MonoMethod **vtable;
6712 MonoMethod *res = NULL;
6714 MONO_CHECK_ARG_NULL (rtype);
6715 MONO_CHECK_ARG_NULL (rmethod);
6717 method = rmethod->method;
6718 klass = mono_class_from_mono_type (rtype->type);
6719 mono_class_init_or_throw (klass);
6721 if (MONO_CLASS_IS_INTERFACE (klass))
6724 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6727 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6728 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6734 mono_class_setup_vtable (klass);
6735 vtable = klass->vtable;
6737 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6738 gboolean variance_used = FALSE;
6739 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6740 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6742 res = vtable [offs + method->slot];
6744 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6747 if (method->slot != -1)
6748 res = vtable [method->slot];
6754 return mono_method_get_object (mono_domain_get (), res, NULL);
6758 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6763 MONO_ARCH_SAVE_REGS;
6765 klass = mono_class_from_mono_type (type->type);
6766 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6768 if (enable) vtable->remote = 1;
6769 else vtable->remote = 0;
6773 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6778 MONO_ARCH_SAVE_REGS;
6780 domain = mono_object_domain (type);
6781 klass = mono_class_from_mono_type (type->type);
6782 mono_class_init_or_throw (klass);
6784 if (klass->rank >= 1) {
6785 g_assert (klass->rank == 1);
6786 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6788 /* Bypass remoting object creation check */
6789 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6794 ves_icall_System_IO_get_temp_path (void)
6796 MONO_ARCH_SAVE_REGS;
6798 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6801 #ifndef PLATFORM_NO_DRIVEINFO
6803 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6804 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6808 ULARGE_INTEGER wapi_free_bytes_avail;
6809 ULARGE_INTEGER wapi_total_number_of_bytes;
6810 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6812 MONO_ARCH_SAVE_REGS;
6814 *error = ERROR_SUCCESS;
6815 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6816 &wapi_total_number_of_free_bytes);
6819 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6820 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6821 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6823 *free_bytes_avail = 0;
6824 *total_number_of_bytes = 0;
6825 *total_number_of_free_bytes = 0;
6826 *error = GetLastError ();
6833 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6835 MONO_ARCH_SAVE_REGS;
6837 return GetDriveType (mono_string_chars (root_path_name));
6842 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6844 MONO_ARCH_SAVE_REGS;
6846 return mono_compile_method (method);
6850 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6855 MONO_ARCH_SAVE_REGS;
6857 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6859 #if defined (HOST_WIN32)
6860 /* Avoid mixing '/' and '\\' */
6863 for (i = strlen (path) - 1; i >= 0; i--)
6864 if (path [i] == '/')
6868 mcpath = mono_string_new (mono_domain_get (), path);
6875 get_bundled_app_config (void)
6877 const gchar *app_config;
6884 MONO_ARCH_SAVE_REGS;
6886 domain = mono_domain_get ();
6887 file = domain->setup->configuration_file;
6891 // Retrieve config file and remove the extension
6892 config_file = mono_string_to_utf8 (file);
6893 len = strlen (config_file) - strlen (".config");
6894 module = g_malloc0 (len + 1);
6895 memcpy (module, config_file, len);
6896 // Get the config file from the module name
6897 app_config = mono_config_string_for_assembly_file (module);
6900 g_free (config_file);
6905 return mono_string_new (mono_domain_get (), app_config);
6909 get_bundled_machine_config (void)
6911 const gchar *machine_config;
6913 MONO_ARCH_SAVE_REGS;
6915 machine_config = mono_get_machine_config ();
6917 if (!machine_config)
6920 return mono_string_new (mono_domain_get (), machine_config);
6924 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6929 MONO_ARCH_SAVE_REGS;
6931 path = g_path_get_dirname (mono_get_config_dir ());
6933 #if defined (HOST_WIN32)
6934 /* Avoid mixing '/' and '\\' */
6937 for (i = strlen (path) - 1; i >= 0; i--)
6938 if (path [i] == '/')
6942 ipath = mono_string_new (mono_domain_get (), path);
6949 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6951 MonoPEResourceDataEntry *entry;
6954 MONO_ARCH_SAVE_REGS;
6956 if (!assembly || !result || !size)
6961 image = assembly->assembly->image;
6962 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6966 *result = mono_image_rva_map (image, entry->rde_data_offset);
6971 *size = entry->rde_size;
6977 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6979 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6983 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6985 #if defined (HOST_WIN32)
6986 OutputDebugString (mono_string_chars (message));
6988 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6992 /* Only used for value types */
6994 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6999 MONO_ARCH_SAVE_REGS;
7001 domain = mono_object_domain (type);
7002 klass = mono_class_from_mono_type (type->type);
7003 mono_class_init_or_throw (klass);
7005 if (mono_class_is_nullable (klass))
7006 /* No arguments -> null */
7009 return mono_object_new (domain, klass);
7012 static MonoReflectionMethod *
7013 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7015 MonoClass *klass, *parent;
7016 MonoMethod *method = m->method;
7017 MonoMethod *result = NULL;
7019 MONO_ARCH_SAVE_REGS;
7021 if (method->klass == NULL)
7024 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7025 MONO_CLASS_IS_INTERFACE (method->klass) ||
7026 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7029 klass = method->klass;
7030 if (klass->generic_class)
7031 klass = klass->generic_class->container_class;
7034 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7035 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7036 mono_class_setup_vtable (parent);
7037 if (parent->vtable_size <= method->slot)
7042 klass = klass->parent;
7047 if (klass == method->klass)
7050 /*This is possible if definition == FALSE.
7051 * Do it here to be really sure we don't read invalid memory.
7053 if (method->slot >= klass->vtable_size)
7056 result = klass->vtable [method->slot];
7057 if (result == NULL) {
7058 /* It is an abstract method */
7059 gpointer iter = NULL;
7060 while ((result = mono_class_get_methods (klass, &iter)))
7061 if (result->slot == method->slot)
7068 return mono_method_get_object (mono_domain_get (), result, NULL);
7072 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7074 MonoMethod *method = m->method;
7076 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7081 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7083 MONO_ARCH_SAVE_REGS;
7085 iter->sig = *(MonoMethodSignature**)argsp;
7087 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7088 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7091 /* FIXME: it's not documented what start is exactly... */
7095 iter->args = argsp + sizeof (gpointer);
7097 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7099 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7103 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7105 guint32 i, arg_size;
7108 MONO_ARCH_SAVE_REGS;
7110 i = iter->sig->sentinelpos + iter->next_arg;
7112 g_assert (i < iter->sig->param_count);
7114 res.type = iter->sig->params [i];
7115 res.klass = mono_class_from_mono_type (res.type);
7116 res.value = iter->args;
7117 arg_size = mono_type_stack_size (res.type, &align);
7118 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7119 if (arg_size <= sizeof (gpointer)) {
7121 int padding = arg_size - mono_type_size (res.type, &dummy);
7122 res.value = (guint8*)res.value + padding;
7125 iter->args = (char*)iter->args + arg_size;
7128 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7134 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7136 guint32 i, arg_size;
7139 MONO_ARCH_SAVE_REGS;
7141 i = iter->sig->sentinelpos + iter->next_arg;
7143 g_assert (i < iter->sig->param_count);
7145 while (i < iter->sig->param_count) {
7146 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7148 res.type = iter->sig->params [i];
7149 res.klass = mono_class_from_mono_type (res.type);
7150 /* FIXME: endianess issue... */
7151 res.value = iter->args;
7152 arg_size = mono_type_stack_size (res.type, &align);
7153 iter->args = (char*)iter->args + arg_size;
7155 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7158 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7167 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7170 MONO_ARCH_SAVE_REGS;
7172 i = iter->sig->sentinelpos + iter->next_arg;
7174 g_assert (i < iter->sig->param_count);
7176 return iter->sig->params [i];
7180 mono_TypedReference_ToObject (MonoTypedRef tref)
7182 MONO_ARCH_SAVE_REGS;
7184 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7185 MonoObject** objp = tref.value;
7189 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7193 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7195 MONO_ARCH_SAVE_REGS;
7197 if (MONO_TYPE_IS_REFERENCE (type)) {
7198 MonoObject** objp = value;
7202 return mono_value_box (mono_domain_get (), klass, value);
7206 prelink_method (MonoMethod *method)
7208 const char *exc_class, *exc_arg;
7209 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7211 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7213 mono_raise_exception(
7214 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7216 /* create the wrapper, too? */
7220 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7222 MONO_ARCH_SAVE_REGS;
7223 prelink_method (method->method);
7227 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7229 MonoClass *klass = mono_class_from_mono_type (type->type);
7231 gpointer iter = NULL;
7232 MONO_ARCH_SAVE_REGS;
7234 mono_class_init_or_throw (klass);
7236 while ((m = mono_class_get_methods (klass, &iter)))
7240 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7242 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7243 gint32 const **exponents,
7244 gunichar2 const **digitLowerTable,
7245 gunichar2 const **digitUpperTable,
7246 gint64 const **tenPowersList,
7247 gint32 const **decHexDigits)
7249 *mantissas = Formatter_MantissaBitsTable;
7250 *exponents = Formatter_TensExponentTable;
7251 *digitLowerTable = Formatter_DigitLowerTable;
7252 *digitUpperTable = Formatter_DigitUpperTable;
7253 *tenPowersList = Formatter_TenPowersList;
7254 *decHexDigits = Formatter_DecHexDigits;
7257 /* These parameters are "readonly" in corlib/System/Char.cs */
7259 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7260 guint8 const **numeric_data,
7261 gdouble const **numeric_data_values,
7262 guint16 const **to_lower_data_low,
7263 guint16 const **to_lower_data_high,
7264 guint16 const **to_upper_data_low,
7265 guint16 const **to_upper_data_high)
7267 *category_data = CategoryData;
7268 *numeric_data = NumericData;
7269 *numeric_data_values = NumericDataValues;
7270 *to_lower_data_low = ToLowerDataLow;
7271 *to_lower_data_high = ToLowerDataHigh;
7272 *to_upper_data_low = ToUpperDataLow;
7273 *to_upper_data_high = ToUpperDataHigh;
7277 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7279 return method->method->token;
7283 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7284 * and avoid useless allocations.
7287 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7291 for (i = 0; i < type->num_mods; ++i) {
7292 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7297 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7299 for (i = 0; i < type->num_mods; ++i) {
7300 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7301 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7302 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7310 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7312 MonoType *type = param->ClassImpl->type;
7313 MonoClass *member_class = mono_object_class (param->MemberImpl);
7314 MonoMethod *method = NULL;
7317 MonoMethodSignature *sig;
7319 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7320 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7321 method = rmethod->method;
7322 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7323 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7324 if (!(method = prop->property->get))
7325 method = prop->property->set;
7328 char *type_name = mono_type_get_full_name (member_class);
7329 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7330 MonoException *ex = mono_get_exception_not_supported (msg);
7333 mono_raise_exception (ex);
7336 image = method->klass->image;
7337 pos = param->PositionImpl;
7338 sig = mono_method_signature (method);
7342 type = sig->params [pos];
7344 return type_array_from_modifiers (image, type, optional);
7348 get_property_type (MonoProperty *prop)
7350 MonoMethodSignature *sig;
7352 sig = mono_method_signature (prop->get);
7354 } else if (prop->set) {
7355 sig = mono_method_signature (prop->set);
7356 return sig->params [sig->param_count - 1];
7362 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7364 MonoType *type = get_property_type (property->property);
7365 MonoImage *image = property->klass->image;
7369 return type_array_from_modifiers (image, type, optional);
7373 *Construct a MonoType suited to be used to decode a constant blob object.
7375 * @type is the target type which will be constructed
7376 * @blob_type is the blob type, for example, that comes from the constant table
7377 * @real_type is the expected constructed type.
7380 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7382 type->type = blob_type;
7383 type->data.klass = NULL;
7384 if (blob_type == MONO_TYPE_CLASS)
7385 type->data.klass = mono_defaults.object_class;
7386 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7387 /* For enums, we need to use the base type */
7388 type->type = MONO_TYPE_VALUETYPE;
7389 type->data.klass = mono_class_from_mono_type (real_type);
7391 type->data.klass = mono_class_from_mono_type (real_type);
7395 property_info_get_default_value (MonoReflectionProperty *property)
7398 MonoProperty *prop = property->property;
7399 MonoType *type = get_property_type (prop);
7400 MonoDomain *domain = mono_object_domain (property);
7401 MonoTypeEnum def_type;
7402 const char *def_value;
7405 mono_class_init (prop->parent);
7407 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7408 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7410 def_value = mono_class_get_property_default_value (prop, &def_type);
7412 mono_type_from_blob_type (&blob_type, def_type, type);
7413 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7419 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7421 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7422 MonoCustomAttrInfo *cinfo;
7425 mono_class_init_or_throw (attr_class);
7427 cinfo = mono_reflection_get_custom_attrs_info (obj);
7430 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7432 mono_custom_attrs_free (cinfo);
7437 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7439 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7443 mono_class_init_or_throw (attr_class);
7445 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7447 if (mono_loader_get_last_error ()) {
7448 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7449 g_assert_not_reached ();
7458 ves_icall_Mono_Runtime_GetDisplayName (void)
7461 MonoString *display_name;
7463 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7464 display_name = mono_string_new (mono_domain_get (), info);
7466 return display_name;
7470 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7472 MonoString *message;
7476 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7477 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7480 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7482 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7490 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7491 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7492 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7493 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7494 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7495 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7496 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7497 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7501 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7506 gunichar2 last, prev_last, prev2_last;
7514 last = prev_last = 0, prev2_last = 0;
7515 for (i = 0; i < ilength; i++) {
7517 if (c >= sizeof (dbase64)) {
7518 exc = mono_exception_from_name_msg (mono_get_corlib (),
7519 "System", "FormatException",
7520 "Invalid character found.");
7521 mono_raise_exception (exc);
7522 } else if (isspace (c)) {
7525 prev2_last = prev_last;
7531 olength = ilength - ignored;
7533 if (allowWhitespaceOnly && olength == 0) {
7534 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7537 if ((olength & 3) != 0 || olength <= 0) {
7538 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7539 "FormatException", "Invalid length.");
7540 mono_raise_exception (exc);
7543 if (prev2_last == '=') {
7544 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7545 mono_raise_exception (exc);
7548 olength = (olength * 3) / 4;
7552 if (prev_last == '=')
7555 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7556 res_ptr = mono_array_addr (result, guchar, 0);
7557 for (i = 0; i < ilength; ) {
7560 for (k = 0; k < 4 && i < ilength;) {
7566 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7567 exc = mono_exception_from_name_msg (mono_get_corlib (),
7568 "System", "FormatException",
7569 "Invalid character found.");
7570 mono_raise_exception (exc);
7575 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7577 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7579 *res_ptr++ = (b [2] << 6) | b [3];
7581 while (i < ilength && isspace (start [i]))
7589 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7591 MONO_ARCH_SAVE_REGS;
7593 return base64_to_byte_array (mono_string_chars (str),
7594 mono_string_length (str), allowWhitespaceOnly);
7598 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7600 MONO_ARCH_SAVE_REGS;
7602 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7606 #define ICALL_TYPE(id,name,first)
7607 #define ICALL(id,name,func) Icall_ ## id,
7610 #include "metadata/icall-def.h"
7616 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7617 #define ICALL(id,name,func)
7619 #include "metadata/icall-def.h"
7625 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7626 #define ICALL(id,name,func)
7628 guint16 first_icall;
7631 static const IcallTypeDesc
7632 icall_type_descs [] = {
7633 #include "metadata/icall-def.h"
7637 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7640 #define ICALL_TYPE(id,name,first)
7643 #ifdef HAVE_ARRAY_ELEM_INIT
7644 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7645 #define MSGSTRFIELD1(line) str##line
7647 static const struct msgstrtn_t {
7648 #define ICALL(id,name,func)
7650 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7651 #include "metadata/icall-def.h"
7653 } icall_type_names_str = {
7654 #define ICALL_TYPE(id,name,first) (name),
7655 #include "metadata/icall-def.h"
7658 static const guint16 icall_type_names_idx [] = {
7659 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7660 #include "metadata/icall-def.h"
7663 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7665 static const struct msgstr_t {
7667 #define ICALL_TYPE(id,name,first)
7668 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7669 #include "metadata/icall-def.h"
7671 } icall_names_str = {
7672 #define ICALL(id,name,func) (name),
7673 #include "metadata/icall-def.h"
7676 static const guint16 icall_names_idx [] = {
7677 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7678 #include "metadata/icall-def.h"
7681 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7687 #define ICALL_TYPE(id,name,first) name,
7688 #define ICALL(id,name,func)
7689 static const char* const
7690 icall_type_names [] = {
7691 #include "metadata/icall-def.h"
7695 #define icall_type_name_get(id) (icall_type_names [(id)])
7699 #define ICALL_TYPE(id,name,first)
7700 #define ICALL(id,name,func) name,
7701 static const char* const
7703 #include "metadata/icall-def.h"
7706 #define icall_name_get(id) icall_names [(id)]
7708 #endif /* !HAVE_ARRAY_ELEM_INIT */
7712 #define ICALL_TYPE(id,name,first)
7713 #define ICALL(id,name,func) func,
7714 static const gconstpointer
7715 icall_functions [] = {
7716 #include "metadata/icall-def.h"
7720 static GHashTable *icall_hash = NULL;
7721 static GHashTable *jit_icall_hash_name = NULL;
7722 static GHashTable *jit_icall_hash_addr = NULL;
7725 mono_icall_init (void)
7729 /* check that tables are sorted: disable in release */
7732 const char *prev_class = NULL;
7733 const char *prev_method;
7735 for (i = 0; i < Icall_type_num; ++i) {
7736 const IcallTypeDesc *desc;
7739 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7740 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7741 prev_class = icall_type_name_get (i);
7742 desc = &icall_type_descs [i];
7743 num_icalls = icall_desc_num_icalls (desc);
7744 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7745 for (j = 0; j < num_icalls; ++j) {
7746 const char *methodn = icall_name_get (desc->first_icall + j);
7747 if (prev_method && strcmp (prev_method, methodn) >= 0)
7748 g_print ("method %s should come before method %s\n", methodn, prev_method);
7749 prev_method = methodn;
7754 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7758 mono_icall_cleanup (void)
7760 g_hash_table_destroy (icall_hash);
7761 g_hash_table_destroy (jit_icall_hash_name);
7762 g_hash_table_destroy (jit_icall_hash_addr);
7766 mono_add_internal_call (const char *name, gconstpointer method)
7768 mono_loader_lock ();
7770 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7772 mono_loader_unlock ();
7775 #ifdef HAVE_ARRAY_ELEM_INIT
7777 compare_method_imap (const void *key, const void *elem)
7779 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7780 return strcmp (key, method_name);
7784 find_method_icall (const IcallTypeDesc *imap, const char *name)
7786 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7789 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7793 compare_class_imap (const void *key, const void *elem)
7795 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7796 return strcmp (key, class_name);
7799 static const IcallTypeDesc*
7800 find_class_icalls (const char *name)
7802 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7805 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7810 compare_method_imap (const void *key, const void *elem)
7812 const char** method_name = (const char**)elem;
7813 return strcmp (key, *method_name);
7817 find_method_icall (const IcallTypeDesc *imap, const char *name)
7819 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7822 return (gpointer)icall_functions [(nameslot - icall_names)];
7826 compare_class_imap (const void *key, const void *elem)
7828 const char** class_name = (const char**)elem;
7829 return strcmp (key, *class_name);
7832 static const IcallTypeDesc*
7833 find_class_icalls (const char *name)
7835 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7838 return &icall_type_descs [nameslot - icall_type_names];
7844 * we should probably export this as an helper (handle nested types).
7845 * Returns the number of chars written in buf.
7848 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7850 int nspacelen, cnamelen;
7851 nspacelen = strlen (klass->name_space);
7852 cnamelen = strlen (klass->name);
7853 if (nspacelen + cnamelen + 2 > bufsize)
7856 memcpy (buf, klass->name_space, nspacelen);
7857 buf [nspacelen ++] = '.';
7859 memcpy (buf + nspacelen, klass->name, cnamelen);
7860 buf [nspacelen + cnamelen] = 0;
7861 return nspacelen + cnamelen;
7865 mono_lookup_internal_call (MonoMethod *method)
7870 int typelen = 0, mlen, siglen;
7872 const IcallTypeDesc *imap;
7874 g_assert (method != NULL);
7876 if (method->is_inflated)
7877 method = ((MonoMethodInflated *) method)->declaring;
7879 if (method->klass->nested_in) {
7880 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7884 mname [pos++] = '/';
7887 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7893 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7898 imap = find_class_icalls (mname);
7900 mname [typelen] = ':';
7901 mname [typelen + 1] = ':';
7903 mlen = strlen (method->name);
7904 memcpy (mname + typelen + 2, method->name, mlen);
7905 sigstart = mname + typelen + 2 + mlen;
7908 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7909 siglen = strlen (tmpsig);
7910 if (typelen + mlen + siglen + 6 > sizeof (mname))
7913 memcpy (sigstart + 1, tmpsig, siglen);
7914 sigstart [siglen + 1] = ')';
7915 sigstart [siglen + 2] = 0;
7918 mono_loader_lock ();
7920 res = g_hash_table_lookup (icall_hash, mname);
7922 mono_loader_unlock ();
7925 /* try without signature */
7927 res = g_hash_table_lookup (icall_hash, mname);
7929 mono_loader_unlock ();
7933 /* it wasn't found in the static call tables */
7935 mono_loader_unlock ();
7938 res = find_method_icall (imap, sigstart - mlen);
7940 mono_loader_unlock ();
7943 /* try _with_ signature */
7945 res = find_method_icall (imap, sigstart - mlen);
7947 mono_loader_unlock ();
7951 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7952 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7953 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7954 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7955 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");
7956 g_print ("If you see other errors or faults after this message they are probably related\n");
7957 g_print ("and you need to fix your mono install first.\n");
7959 mono_loader_unlock ();
7965 type_from_typename (char *typename)
7967 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7969 if (!strcmp (typename, "int"))
7970 klass = mono_defaults.int_class;
7971 else if (!strcmp (typename, "ptr"))
7972 klass = mono_defaults.int_class;
7973 else if (!strcmp (typename, "void"))
7974 klass = mono_defaults.void_class;
7975 else if (!strcmp (typename, "int32"))
7976 klass = mono_defaults.int32_class;
7977 else if (!strcmp (typename, "uint32"))
7978 klass = mono_defaults.uint32_class;
7979 else if (!strcmp (typename, "int8"))
7980 klass = mono_defaults.sbyte_class;
7981 else if (!strcmp (typename, "uint8"))
7982 klass = mono_defaults.byte_class;
7983 else if (!strcmp (typename, "int16"))
7984 klass = mono_defaults.int16_class;
7985 else if (!strcmp (typename, "uint16"))
7986 klass = mono_defaults.uint16_class;
7987 else if (!strcmp (typename, "long"))
7988 klass = mono_defaults.int64_class;
7989 else if (!strcmp (typename, "ulong"))
7990 klass = mono_defaults.uint64_class;
7991 else if (!strcmp (typename, "float"))
7992 klass = mono_defaults.single_class;
7993 else if (!strcmp (typename, "double"))
7994 klass = mono_defaults.double_class;
7995 else if (!strcmp (typename, "object"))
7996 klass = mono_defaults.object_class;
7997 else if (!strcmp (typename, "obj"))
7998 klass = mono_defaults.object_class;
7999 else if (!strcmp (typename, "string"))
8000 klass = mono_defaults.string_class;
8001 else if (!strcmp (typename, "bool"))
8002 klass = mono_defaults.boolean_class;
8003 else if (!strcmp (typename, "boolean"))
8004 klass = mono_defaults.boolean_class;
8006 g_error ("%s", typename);
8007 g_assert_not_reached ();
8009 return &klass->byval_arg;
8012 MonoMethodSignature*
8013 mono_create_icall_signature (const char *sigstr)
8018 MonoMethodSignature *res;
8020 mono_loader_lock ();
8021 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8023 mono_loader_unlock ();
8027 parts = g_strsplit (sigstr, " ", 256);
8036 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8041 * Under windows, the default pinvoke calling convention is STDCALL but
8044 res->call_convention = MONO_CALL_C;
8047 res->ret = type_from_typename (parts [0]);
8048 for (i = 1; i < len; ++i) {
8049 res->params [i - 1] = type_from_typename (parts [i]);
8054 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8056 mono_loader_unlock ();
8062 mono_find_jit_icall_by_name (const char *name)
8064 MonoJitICallInfo *info;
8065 g_assert (jit_icall_hash_name);
8067 mono_loader_lock ();
8068 info = g_hash_table_lookup (jit_icall_hash_name, name);
8069 mono_loader_unlock ();
8074 mono_find_jit_icall_by_addr (gconstpointer addr)
8076 MonoJitICallInfo *info;
8077 g_assert (jit_icall_hash_addr);
8079 mono_loader_lock ();
8080 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8081 mono_loader_unlock ();
8087 * mono_get_jit_icall_info:
8089 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8090 * caller should access it while holding the loader lock.
8093 mono_get_jit_icall_info (void)
8095 return jit_icall_hash_name;
8099 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8101 mono_loader_lock ();
8102 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8103 mono_loader_unlock ();
8107 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8109 MonoJitICallInfo *info;
8114 mono_loader_lock ();
8116 if (!jit_icall_hash_name) {
8117 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8118 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8121 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8122 g_warning ("jit icall already defined \"%s\"\n", name);
8123 g_assert_not_reached ();
8126 info = g_new0 (MonoJitICallInfo, 1);
8133 info->wrapper = func;
8135 info->wrapper = NULL;
8138 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8139 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8141 mono_loader_unlock ();