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, gboolean create_open_instance)
1176 MONO_ARCH_SAVE_REGS;
1178 MONO_CHECK_ARG_NULL (obj);
1180 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, 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 vell_icall_get_method_attributes (MonoMethod *method)
1700 return method->flags;
1704 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1707 MonoDomain *domain = mono_domain_get ();
1708 MonoMethodSignature* sig;
1709 MONO_ARCH_SAVE_REGS;
1711 sig = mono_method_signature_checked (method, &error);
1712 if (!mono_error_ok (&error))
1713 mono_error_raise_exception (&error);
1716 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1717 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1718 info->attrs = method->flags;
1719 info->implattrs = method->iflags;
1720 if (sig->call_convention == MONO_CALL_DEFAULT)
1721 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1723 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1728 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1732 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1734 MonoDomain *domain = mono_domain_get ();
1736 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1739 static MonoReflectionMarshal*
1740 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1742 MonoDomain *domain = mono_domain_get ();
1743 MonoReflectionMarshal* res = NULL;
1744 MonoMarshalSpec **mspecs;
1747 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1748 mono_method_get_marshal_info (method, mspecs);
1751 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1753 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1755 mono_metadata_free_marshal_spec (mspecs [i]);
1762 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1764 MonoClass *parent = field->field->parent;
1765 if (!parent->size_inited)
1766 mono_class_init (parent);
1768 return field->field->offset - sizeof (MonoObject);
1771 static MonoReflectionType*
1772 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1775 MONO_ARCH_SAVE_REGS;
1777 parent = declaring? field->field->parent: field->klass;
1779 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1783 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1785 MonoClass *fklass = field->klass;
1786 MonoClassField *cf = field->field;
1787 MonoDomain *domain = mono_object_domain (field);
1789 if (fklass->image->assembly->ref_only)
1790 mono_raise_exception (mono_get_exception_invalid_operation (
1791 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1793 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1794 mono_security_core_clr_ensure_reflection_access_field (cf);
1796 return mono_field_get_value_object (domain, cf, obj);
1800 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1803 MonoClassField *cf = field->field;
1807 MONO_ARCH_SAVE_REGS;
1809 if (field->klass->image->assembly->ref_only)
1810 mono_raise_exception (mono_get_exception_invalid_operation (
1811 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1813 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1814 mono_security_core_clr_ensure_reflection_access_field (cf);
1816 type = mono_field_get_type_checked (cf, &error);
1817 if (!mono_error_ok (&error))
1818 mono_error_raise_exception (&error);
1820 v = (gchar *) value;
1822 switch (type->type) {
1825 case MONO_TYPE_BOOLEAN:
1828 case MONO_TYPE_CHAR:
1837 case MONO_TYPE_VALUETYPE:
1840 v += sizeof (MonoObject);
1842 case MONO_TYPE_STRING:
1843 case MONO_TYPE_OBJECT:
1844 case MONO_TYPE_CLASS:
1845 case MONO_TYPE_ARRAY:
1846 case MONO_TYPE_SZARRAY:
1849 case MONO_TYPE_GENERICINST: {
1850 MonoGenericClass *gclass = type->data.generic_class;
1851 g_assert (!gclass->context.class_inst->is_open);
1853 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1854 MonoClass *nklass = mono_class_from_mono_type (type);
1855 MonoObject *nullable;
1858 * Convert the boxed vtype into a Nullable structure.
1859 * This is complicated by the fact that Nullables have
1860 * a variable structure.
1862 nullable = mono_object_new (mono_domain_get (), nklass);
1864 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1866 v = mono_object_unbox (nullable);
1869 if (gclass->container_class->valuetype && (v != NULL))
1870 v += sizeof (MonoObject);
1874 g_error ("type 0x%x not handled in "
1875 "ves_icall_FieldInfo_SetValueInternal", type->type);
1880 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1881 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1882 if (!vtable->initialized)
1883 mono_runtime_class_init (vtable);
1884 mono_field_static_set_value (vtable, cf, v);
1886 mono_field_set_value (obj, cf, v);
1891 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1893 MonoObject *o = NULL;
1894 MonoClassField *field = this->field;
1896 MonoDomain *domain = mono_object_domain (this);
1898 MonoTypeEnum def_type;
1899 const char *def_value;
1901 MONO_ARCH_SAVE_REGS;
1903 mono_class_init (field->parent);
1905 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1906 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1908 if (field->parent->image->dynamic) {
1910 g_assert_not_reached ();
1913 def_value = mono_class_get_field_default_value (field, &def_type);
1915 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1919 case MONO_TYPE_BOOLEAN:
1922 case MONO_TYPE_CHAR:
1930 case MONO_TYPE_R8: {
1933 /* boxed value type */
1934 t = g_new0 (MonoType, 1);
1936 klass = mono_class_from_mono_type (t);
1938 o = mono_object_new (domain, klass);
1939 v = ((gchar *) o) + sizeof (MonoObject);
1940 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1943 case MONO_TYPE_STRING:
1944 case MONO_TYPE_CLASS:
1945 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1948 g_assert_not_reached ();
1954 static MonoReflectionType*
1955 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1958 MonoClassField *field = ref_field->field;
1959 MonoType *type = mono_field_get_type_checked (field, &error);
1960 if (!mono_error_ok (&error))
1961 mono_error_raise_exception (&error);
1962 return mono_type_get_object (mono_object_domain (ref_field), type);
1965 static MonoReflectionType*
1966 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1968 MonoMethod *method = rmethod->method.method;
1970 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1973 /* From MonoProperty.cs */
1975 PInfo_Attributes = 1,
1976 PInfo_GetMethod = 1 << 1,
1977 PInfo_SetMethod = 1 << 2,
1978 PInfo_ReflectedType = 1 << 3,
1979 PInfo_DeclaringType = 1 << 4,
1984 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1986 MonoDomain *domain = mono_object_domain (property);
1988 MONO_ARCH_SAVE_REGS;
1990 if ((req_info & PInfo_ReflectedType) != 0)
1991 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1992 if ((req_info & PInfo_DeclaringType) != 0)
1993 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1995 if ((req_info & PInfo_Name) != 0)
1996 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1998 if ((req_info & PInfo_Attributes) != 0)
1999 info->attrs = property->property->attrs;
2001 if ((req_info & PInfo_GetMethod) != 0)
2002 MONO_STRUCT_SETREF (info, get, property->property->get ?
2003 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2005 if ((req_info & PInfo_SetMethod) != 0)
2006 MONO_STRUCT_SETREF (info, set, property->property->set ?
2007 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2009 * There may be other methods defined for properties, though, it seems they are not exposed
2010 * in the reflection API
2015 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2017 MonoDomain *domain = mono_object_domain (event);
2019 MONO_ARCH_SAVE_REGS;
2021 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2022 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2024 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2025 info->attrs = event->event->attrs;
2026 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2027 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2028 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2030 #ifndef MONO_SMALL_CONFIG
2031 if (event->event->other) {
2033 while (event->event->other [n])
2035 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2037 for (i = 0; i < n; i++)
2038 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2044 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2049 mono_class_setup_interfaces (klass, error);
2050 if (!mono_error_ok (error))
2053 for (i = 0; i < klass->interface_count; i++) {
2054 ic = klass->interfaces [i];
2055 g_hash_table_insert (ifaces, ic, ic);
2057 collect_interfaces (ic, ifaces, error);
2058 if (!mono_error_ok (error))
2064 MonoArray *iface_array;
2065 MonoGenericContext *context;
2069 } FillIfaceArrayData;
2072 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2074 FillIfaceArrayData *data = user_data;
2075 MonoClass *ic = key;
2076 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2078 if (!mono_error_ok (data->error))
2081 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2082 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2083 if (!mono_error_ok (data->error))
2087 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2090 mono_metadata_free_type (inflated);
2094 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2097 MonoClass *class = mono_class_from_mono_type (type->type);
2099 FillIfaceArrayData data = { 0 };
2102 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2104 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2105 data.context = mono_class_get_context (class);
2106 class = class->generic_class->container_class;
2109 for (parent = class; parent; parent = parent->parent) {
2110 mono_class_setup_interfaces (parent, &error);
2111 if (!mono_error_ok (&error))
2113 collect_interfaces (parent, iface_hash, &error);
2114 if (!mono_error_ok (&error))
2118 data.error = &error;
2119 data.domain = mono_object_domain (type);
2121 len = g_hash_table_size (iface_hash);
2123 g_hash_table_destroy (iface_hash);
2124 if (!data.domain->empty_types)
2125 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2126 return data.domain->empty_types;
2129 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2130 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2131 if (!mono_error_ok (&error))
2134 g_hash_table_destroy (iface_hash);
2135 return data.iface_array;
2138 g_hash_table_destroy (iface_hash);
2139 mono_error_raise_exception (&error);
2144 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2146 gboolean variance_used;
2147 MonoClass *class = mono_class_from_mono_type (type->type);
2148 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2149 MonoReflectionMethod *member;
2152 int i = 0, len, ioffset;
2155 MONO_ARCH_SAVE_REGS;
2156 mono_class_init_or_throw (class);
2157 mono_class_init_or_throw (iclass);
2159 mono_class_setup_vtable (class);
2161 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2165 len = mono_class_num_methods (iclass);
2166 domain = mono_object_domain (type);
2167 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2168 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2170 while ((method = mono_class_get_methods (iclass, &iter))) {
2171 member = mono_method_get_object (domain, method, iclass);
2172 mono_array_setref (*methods, i, member);
2173 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2174 mono_array_setref (*targets, i, member);
2181 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2183 MonoClass *klass = mono_class_from_mono_type (type->type);
2184 mono_class_init_or_throw (klass);
2186 if (klass->image->dynamic) {
2187 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2188 *packing = tb->packing_size;
2189 *size = tb->class_size;
2191 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2195 static MonoReflectionType*
2196 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2200 MONO_ARCH_SAVE_REGS;
2202 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2203 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2205 class = mono_class_from_mono_type (type->type);
2206 mono_class_init_or_throw (class);
2208 // GetElementType should only return a type for:
2209 // Array Pointer PassedByRef
2210 if (type->type->byref)
2211 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2212 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2213 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2214 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2215 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2220 static MonoReflectionType*
2221 ves_icall_get_type_parent (MonoReflectionType *type)
2223 MonoClass *class = mono_class_from_mono_type (type->type);
2224 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2228 ves_icall_type_ispointer (MonoReflectionType *type)
2230 MONO_ARCH_SAVE_REGS;
2232 return type->type->type == MONO_TYPE_PTR;
2236 ves_icall_type_isprimitive (MonoReflectionType *type)
2238 MONO_ARCH_SAVE_REGS;
2240 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)));
2244 ves_icall_type_isbyref (MonoReflectionType *type)
2246 MONO_ARCH_SAVE_REGS;
2248 return type->type->byref;
2252 ves_icall_type_iscomobject (MonoReflectionType *type)
2254 MonoClass *klass = mono_class_from_mono_type (type->type);
2255 mono_class_init_or_throw (klass);
2257 return (klass && klass->is_com_object);
2260 static MonoReflectionModule*
2261 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2263 MonoClass *class = mono_class_from_mono_type (type->type);
2264 return mono_module_get_object (mono_object_domain (type), class->image);
2267 static MonoReflectionAssembly*
2268 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2270 MonoDomain *domain = mono_domain_get ();
2271 MonoClass *class = mono_class_from_mono_type (type->type);
2272 return mono_assembly_get_object (domain, class->image->assembly);
2275 static MonoReflectionType*
2276 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2278 MonoDomain *domain = mono_domain_get ();
2281 MONO_ARCH_SAVE_REGS;
2283 if (type->type->byref)
2285 if (type->type->type == MONO_TYPE_VAR)
2286 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2287 else if (type->type->type == MONO_TYPE_MVAR)
2288 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2290 class = mono_class_from_mono_type (type->type)->nested_in;
2292 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2296 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2298 MonoDomain *domain = mono_domain_get ();
2299 MonoClass *class = mono_class_from_mono_type (type->type);
2301 if (type->type->byref) {
2302 char *n = g_strdup_printf ("%s&", class->name);
2303 MonoString *res = mono_string_new (domain, n);
2309 return mono_string_new (domain, class->name);
2314 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2316 MonoDomain *domain = mono_domain_get ();
2317 MonoClass *class = mono_class_from_mono_type (type->type);
2319 while (class->nested_in)
2320 class = class->nested_in;
2322 if (class->name_space [0] == '\0')
2325 return mono_string_new (domain, class->name_space);
2329 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2333 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2334 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2336 class = mono_class_from_mono_type (type->type);
2342 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2345 MonoClass *klass, *pklass;
2346 MonoDomain *domain = mono_object_domain (type);
2347 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2349 MONO_ARCH_SAVE_REGS;
2351 klass = mono_class_from_mono_type (type->type);
2353 if (klass->generic_container) {
2354 MonoGenericContainer *container = klass->generic_container;
2355 res = mono_array_new_specific (array_vtable, container->type_argc);
2356 for (i = 0; i < container->type_argc; ++i) {
2357 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2358 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2360 } else if (klass->generic_class) {
2361 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2362 res = mono_array_new_specific (array_vtable, inst->type_argc);
2363 for (i = 0; i < inst->type_argc; ++i)
2364 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2366 res = mono_array_new_specific (array_vtable, 0);
2372 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2375 MONO_ARCH_SAVE_REGS;
2377 if (!IS_MONOTYPE (type))
2380 if (type->type->byref)
2383 klass = mono_class_from_mono_type (type->type);
2384 return klass->generic_container != NULL;
2387 static MonoReflectionType*
2388 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2391 MONO_ARCH_SAVE_REGS;
2393 if (type->type->byref)
2396 klass = mono_class_from_mono_type (type->type);
2398 if (klass->generic_container) {
2399 return type; /* check this one */
2401 if (klass->generic_class) {
2402 MonoClass *generic_class = klass->generic_class->container_class;
2405 tb = mono_class_get_ref_info (generic_class);
2407 if (generic_class->wastypebuilder && tb)
2410 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2415 static MonoReflectionType*
2416 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2418 MonoType *geninst, **types;
2421 g_assert (IS_MONOTYPE (type));
2422 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2424 count = mono_array_length (type_array);
2425 types = g_new0 (MonoType *, count);
2427 for (i = 0; i < count; i++) {
2428 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2429 types [i] = t->type;
2432 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2437 return mono_type_get_object (mono_object_domain (type), geninst);
2441 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2444 MONO_ARCH_SAVE_REGS;
2446 if (type->type->byref)
2449 klass = mono_class_from_mono_type (type->type);
2451 return klass->generic_class != NULL;
2455 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2458 MONO_ARCH_SAVE_REGS;
2460 if (!IS_MONOTYPE (type))
2463 if (type->type->byref)
2466 klass = mono_class_from_mono_type (type->type);
2467 return klass->generic_class != NULL || klass->generic_container != NULL;
2471 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2473 MONO_ARCH_SAVE_REGS;
2475 if (!IS_MONOTYPE (type))
2478 if (is_generic_parameter (type->type))
2479 return mono_type_get_generic_param_num (type->type);
2483 static GenericParameterAttributes
2484 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2486 MONO_ARCH_SAVE_REGS;
2488 g_assert (IS_MONOTYPE (type));
2489 g_assert (is_generic_parameter (type->type));
2490 return mono_generic_param_info (type->type->data.generic_param)->flags;
2494 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2496 MonoGenericParamInfo *param_info;
2502 MONO_ARCH_SAVE_REGS;
2504 g_assert (IS_MONOTYPE (type));
2506 domain = mono_object_domain (type);
2507 param_info = mono_generic_param_info (type->type->data.generic_param);
2508 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2511 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2512 for (i = 0; i < count; i++)
2513 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2520 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2522 MONO_ARCH_SAVE_REGS;
2523 return is_generic_parameter (type->type);
2527 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2529 MONO_ARCH_SAVE_REGS;
2530 return is_generic_parameter (tb->type.type);
2534 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2535 MonoReflectionType *t)
2537 enumtype->type = t->type;
2540 static MonoReflectionMethod*
2541 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2542 MonoReflectionMethod* generic)
2549 MONO_ARCH_SAVE_REGS;
2551 domain = ((MonoObject *)type)->vtable->domain;
2553 klass = mono_class_from_mono_type (type->type);
2554 mono_class_init_or_throw (klass);
2557 while ((method = mono_class_get_methods (klass, &iter))) {
2558 if (method->token == generic->method->token)
2559 return mono_method_get_object (domain, method, klass);
2567 static MonoReflectionMethod *
2568 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2571 MonoType *type = ref_type->type;
2573 MONO_ARCH_SAVE_REGS;
2575 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2576 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2577 if (type->type == MONO_TYPE_VAR)
2580 method = mono_type_get_generic_param_owner (type)->owner.method;
2582 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2585 static MonoReflectionDllImportAttribute*
2586 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2588 static MonoClass *DllImportAttributeClass = NULL;
2589 MonoDomain *domain = mono_domain_get ();
2590 MonoReflectionDllImportAttribute *attr;
2591 MonoImage *image = method->klass->image;
2592 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2593 MonoTableInfo *tables = image->tables;
2594 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2595 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2596 guint32 im_cols [MONO_IMPLMAP_SIZE];
2597 guint32 scope_token;
2598 const char *import = NULL;
2599 const char *scope = NULL;
2602 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2605 if (!DllImportAttributeClass) {
2606 DllImportAttributeClass =
2607 mono_class_from_name (mono_defaults.corlib,
2608 "System.Runtime.InteropServices", "DllImportAttribute");
2609 g_assert (DllImportAttributeClass);
2612 if (method->klass->image->dynamic) {
2613 MonoReflectionMethodAux *method_aux =
2614 g_hash_table_lookup (
2615 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2617 import = method_aux->dllentry;
2618 scope = method_aux->dll;
2621 if (!import || !scope) {
2622 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2627 if (piinfo->implmap_idx) {
2628 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2630 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2631 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2632 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2633 scope = mono_metadata_string_heap (image, scope_token);
2636 flags = piinfo->piflags;
2638 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2640 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2641 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2642 attr->call_conv = (flags & 0x700) >> 8;
2643 attr->charset = ((flags & 0x6) >> 1) + 1;
2644 if (attr->charset == 1)
2646 attr->exact_spelling = (flags & 0x1) != 0;
2647 attr->set_last_error = (flags & 0x40) != 0;
2648 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2649 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2650 attr->preserve_sig = FALSE;
2655 static MonoReflectionMethod *
2656 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2658 MonoMethodInflated *imethod;
2661 MONO_ARCH_SAVE_REGS;
2663 if (method->method->is_generic)
2666 if (!method->method->is_inflated)
2669 imethod = (MonoMethodInflated *) method->method;
2671 result = imethod->declaring;
2672 /* Not a generic method. */
2673 if (!result->is_generic)
2676 if (method->method->klass->image->dynamic) {
2677 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2678 MonoReflectionMethod *res;
2681 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2682 * the dynamic case as well ?
2684 mono_loader_lock ();
2685 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2686 mono_loader_unlock ();
2692 if (imethod->context.class_inst) {
2693 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2694 /*Generic methods gets the context of the GTD.*/
2695 if (mono_class_get_context (klass))
2696 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2699 return mono_method_get_object (mono_object_domain (method), result, NULL);
2703 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2705 MONO_ARCH_SAVE_REGS;
2707 return mono_method_signature (method->method)->generic_param_count != 0;
2711 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2713 MONO_ARCH_SAVE_REGS;
2715 return method->method->is_generic;
2719 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2724 MONO_ARCH_SAVE_REGS;
2726 domain = mono_object_domain (method);
2728 if (method->method->is_inflated) {
2729 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2732 count = inst->type_argc;
2733 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2735 for (i = 0; i < count; i++)
2736 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2742 count = mono_method_signature (method->method)->generic_param_count;
2743 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2745 for (i = 0; i < count; i++) {
2746 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2747 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2748 MonoClass *pklass = mono_class_from_generic_parameter (
2749 param, method->method->klass->image, TRUE);
2750 mono_array_setref (res, i,
2751 mono_type_get_object (domain, &pklass->byval_arg));
2758 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2761 * Invoke from reflection is supposed to always be a virtual call (the API
2762 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2763 * greater flexibility.
2765 MonoMethod *m = method->method;
2769 MONO_ARCH_SAVE_REGS;
2773 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2774 mono_security_core_clr_ensure_reflection_access_method (m);
2776 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2777 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2778 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2783 if (!mono_object_isinst (this, m->klass)) {
2784 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2787 m = mono_object_get_virtual_method (this, m);
2788 /* must pass the pointer to the value for valuetype methods */
2789 if (m->klass->valuetype)
2790 obj = mono_object_unbox (this);
2791 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2792 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2797 pcount = params? mono_array_length (params): 0;
2798 if (pcount != mono_method_signature (m)->param_count) {
2799 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2803 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2804 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."));
2808 if (m->klass->image->assembly->ref_only) {
2809 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."));
2813 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2816 intptr_t *lower_bounds;
2817 pcount = mono_array_length (params);
2818 lengths = alloca (sizeof (uintptr_t) * pcount);
2819 /* Note: the synthetized array .ctors have int32 as argument type */
2820 for (i = 0; i < pcount; ++i)
2821 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2823 if (m->klass->rank == pcount) {
2824 /* Only lengths provided. */
2825 lower_bounds = NULL;
2827 g_assert (pcount == (m->klass->rank * 2));
2828 /* lower bounds are first. */
2829 lower_bounds = (intptr_t*)lengths;
2830 lengths += m->klass->rank;
2833 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2835 return mono_runtime_invoke_array (m, obj, params, NULL);
2839 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2841 MonoDomain *domain = mono_object_domain (method);
2842 MonoMethod *m = method->method;
2843 MonoMethodSignature *sig = mono_method_signature (m);
2844 MonoArray *out_args;
2846 int i, j, outarg_count = 0;
2848 MONO_ARCH_SAVE_REGS;
2850 if (m->klass == mono_defaults.object_class) {
2852 if (!strcmp (m->name, "FieldGetter")) {
2853 MonoClass *k = this->vtable->klass;
2857 /* If this is a proxy, then it must be a CBO */
2858 if (k == mono_defaults.transparent_proxy_class) {
2859 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2860 this = tp->rp->unwrapped_server;
2862 k = this->vtable->klass;
2865 name = mono_array_get (params, MonoString *, 1);
2866 str = mono_string_to_utf8 (name);
2869 MonoClassField* field = mono_class_get_field_from_name (k, str);
2871 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2872 if (field_klass->valuetype)
2873 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2875 result = *((gpointer *)((char *)this + field->offset));
2877 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2878 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2879 mono_array_setref (out_args, 0, result);
2887 g_assert_not_reached ();
2889 } else if (!strcmp (m->name, "FieldSetter")) {
2890 MonoClass *k = this->vtable->klass;
2896 /* If this is a proxy, then it must be a CBO */
2897 if (k == mono_defaults.transparent_proxy_class) {
2898 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2899 this = tp->rp->unwrapped_server;
2901 k = this->vtable->klass;
2904 name = mono_array_get (params, MonoString *, 1);
2905 str = mono_string_to_utf8 (name);
2908 MonoClassField* field = mono_class_get_field_from_name (k, str);
2910 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2911 MonoObject *val = mono_array_get (params, gpointer, 2);
2913 if (field_klass->valuetype) {
2914 size = mono_type_size (field->type, &align);
2915 g_assert (size == mono_class_value_size (field_klass, NULL));
2916 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2918 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2921 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2922 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2932 g_assert_not_reached ();
2937 for (i = 0; i < mono_array_length (params); i++) {
2938 if (sig->params [i]->byref)
2942 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2944 /* handle constructors only for objects already allocated */
2945 if (!strcmp (method->method->name, ".ctor"))
2948 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2949 g_assert (!method->method->klass->valuetype);
2950 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2952 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2953 if (sig->params [i]->byref) {
2955 arg = mono_array_get (params, gpointer, i);
2956 mono_array_setref (out_args, j, arg);
2961 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2967 read_enum_value (char *mem, int type)
2971 return *(guint8*)mem;
2973 return *(gint8*)mem;
2975 return *(guint16*)mem;
2977 return *(gint16*)mem;
2979 return *(guint32*)mem;
2981 return *(gint32*)mem;
2983 return *(guint64*)mem;
2985 return *(gint64*)mem;
2987 g_assert_not_reached ();
2993 write_enum_value (char *mem, int type, guint64 value)
2997 case MONO_TYPE_I1: {
2998 guint8 *p = (guint8*)mem;
3003 case MONO_TYPE_I2: {
3004 guint16 *p = (void*)mem;
3009 case MONO_TYPE_I4: {
3010 guint32 *p = (void*)mem;
3015 case MONO_TYPE_I8: {
3016 guint64 *p = (void*)mem;
3021 g_assert_not_reached ();
3027 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3030 MonoClass *enumc, *objc;
3035 MONO_ARCH_SAVE_REGS;
3037 MONO_CHECK_ARG_NULL (enumType);
3038 MONO_CHECK_ARG_NULL (value);
3040 domain = mono_object_domain (enumType);
3041 enumc = mono_class_from_mono_type (enumType->type);
3043 mono_class_init_or_throw (enumc);
3045 objc = value->vtable->klass;
3047 if (!enumc->enumtype)
3048 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3049 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3050 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."));
3052 etype = mono_class_enum_basetype (enumc);
3054 /* MS throws this for typebuilders */
3055 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3057 res = mono_object_new (domain, enumc);
3058 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3059 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3065 ves_icall_System_Enum_get_value (MonoObject *this)
3073 MONO_ARCH_SAVE_REGS;
3078 g_assert (this->vtable->klass->enumtype);
3080 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3081 res = mono_object_new (mono_object_domain (this), enumc);
3082 dst = (char *)res + sizeof (MonoObject);
3083 src = (char *)this + sizeof (MonoObject);
3084 size = mono_class_value_size (enumc, NULL);
3086 memcpy (dst, src, size);
3091 static MonoReflectionType *
3092 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3097 MONO_ARCH_SAVE_REGS;
3099 klass = mono_class_from_mono_type (type->type);
3100 mono_class_init_or_throw (klass);
3102 etype = mono_class_enum_basetype (klass);
3104 /* MS throws this for typebuilders */
3105 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3107 return mono_type_get_object (mono_object_domain (type), etype);
3111 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3113 gpointer tdata = (char *)this + sizeof (MonoObject);
3114 gpointer odata = (char *)other + sizeof (MonoObject);
3115 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3116 g_assert (basetype);
3118 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3119 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3120 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3123 return me > other ? 1 : -1; \
3126 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3127 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3128 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3131 return me - other; \
3134 switch (basetype->type) {
3136 COMPARE_ENUM_VALUES (guint8);
3138 COMPARE_ENUM_VALUES (gint8);
3139 case MONO_TYPE_CHAR:
3141 COMPARE_ENUM_VALUES_RANGE (guint16);
3143 COMPARE_ENUM_VALUES (gint16);
3145 COMPARE_ENUM_VALUES (guint32);
3147 COMPARE_ENUM_VALUES (gint32);
3149 COMPARE_ENUM_VALUES (guint64);
3151 COMPARE_ENUM_VALUES (gint64);
3153 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3155 #undef COMPARE_ENUM_VALUES_RANGE
3156 #undef COMPARE_ENUM_VALUES
3161 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3163 gpointer data = (char *)this + sizeof (MonoObject);
3164 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3165 g_assert (basetype);
3167 switch (basetype->type) {
3169 return *((gint8*)data);
3171 return *((guint8*)data);
3172 case MONO_TYPE_CHAR:
3174 return *((guint16*)data);
3177 return *((gint16*)data);
3179 return *((guint32*)data);
3181 return *((gint32*)data);
3183 case MONO_TYPE_I8: {
3184 gint64 value = *((gint64*)data);
3185 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3188 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3194 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3196 MonoDomain *domain = mono_object_domain (type);
3197 MonoClass *enumc = mono_class_from_mono_type (type->type);
3198 guint j = 0, nvalues, crow;
3200 MonoClassField *field;
3202 MONO_ARCH_SAVE_REGS;
3204 mono_class_init_or_throw (enumc);
3206 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3207 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3208 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3209 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3213 while ((field = mono_class_get_fields (enumc, &iter))) {
3216 MonoTypeEnum def_type;
3218 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3220 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3222 if (mono_field_is_deleted (field))
3224 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3226 p = mono_class_get_field_default_value (field, &def_type);
3227 len = mono_metadata_decode_blob_size (p, &p);
3228 switch (mono_class_enum_basetype (enumc)->type) {
3231 mono_array_set (info->values, gchar, j, *p);
3233 case MONO_TYPE_CHAR:
3236 mono_array_set (info->values, gint16, j, read16 (p));
3240 mono_array_set (info->values, gint32, j, read32 (p));
3244 mono_array_set (info->values, gint64, j, read64 (p));
3247 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3254 BFLAGS_IgnoreCase = 1,
3255 BFLAGS_DeclaredOnly = 2,
3256 BFLAGS_Instance = 4,
3258 BFLAGS_Public = 0x10,
3259 BFLAGS_NonPublic = 0x20,
3260 BFLAGS_FlattenHierarchy = 0x40,
3261 BFLAGS_InvokeMethod = 0x100,
3262 BFLAGS_CreateInstance = 0x200,
3263 BFLAGS_GetField = 0x400,
3264 BFLAGS_SetField = 0x800,
3265 BFLAGS_GetProperty = 0x1000,
3266 BFLAGS_SetProperty = 0x2000,
3267 BFLAGS_ExactBinding = 0x10000,
3268 BFLAGS_SuppressChangeType = 0x20000,
3269 BFLAGS_OptionalParamBinding = 0x40000
3272 static MonoReflectionField *
3273 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3276 MonoClass *startklass, *klass;
3278 MonoClassField *field;
3281 int (*compare_func) (const char *s1, const char *s2) = NULL;
3282 domain = ((MonoObject *)type)->vtable->domain;
3283 klass = startklass = mono_class_from_mono_type (type->type);
3286 mono_raise_exception (mono_get_exception_argument_null ("name"));
3287 if (type->type->byref)
3290 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3293 if (klass->exception_type != MONO_EXCEPTION_NONE)
3294 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3297 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3298 guint32 flags = mono_field_get_flags (field);
3301 if (mono_field_is_deleted_with_flags (field, flags))
3303 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3304 if (bflags & BFLAGS_Public)
3306 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3307 if (bflags & BFLAGS_NonPublic) {
3314 if (flags & FIELD_ATTRIBUTE_STATIC) {
3315 if (bflags & BFLAGS_Static)
3316 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3319 if (bflags & BFLAGS_Instance)
3326 utf8_name = mono_string_to_utf8 (name);
3328 if (compare_func (mono_field_get_name (field), utf8_name)) {
3334 return mono_field_get_object (domain, klass, field);
3336 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3343 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3346 MonoClass *startklass, *klass, *refklass;
3351 MonoClassField *field;
3352 MonoPtrArray tmp_array;
3354 MONO_ARCH_SAVE_REGS;
3356 domain = ((MonoObject *)type)->vtable->domain;
3357 if (type->type->byref)
3358 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3359 klass = startklass = mono_class_from_mono_type (type->type);
3360 refklass = mono_class_from_mono_type (reftype->type);
3362 mono_ptr_array_init (tmp_array, 2);
3365 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3366 mono_ptr_array_destroy (tmp_array);
3367 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3371 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3372 guint32 flags = mono_field_get_flags (field);
3374 if (mono_field_is_deleted_with_flags (field, flags))
3376 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3377 if (bflags & BFLAGS_Public)
3379 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3380 if (bflags & BFLAGS_NonPublic) {
3387 if (flags & FIELD_ATTRIBUTE_STATIC) {
3388 if (bflags & BFLAGS_Static)
3389 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3392 if (bflags & BFLAGS_Instance)
3398 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3399 mono_ptr_array_append (tmp_array, member);
3401 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3404 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3406 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3407 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3409 mono_ptr_array_destroy (tmp_array);
3415 method_nonpublic (MonoMethod* method, gboolean start_klass)
3417 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3418 case METHOD_ATTRIBUTE_ASSEM:
3419 return (start_klass || mono_defaults.generic_ilist_class);
3420 case METHOD_ATTRIBUTE_PRIVATE:
3422 case METHOD_ATTRIBUTE_PUBLIC:
3430 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3432 static MonoClass *MethodInfo_array;
3434 MonoClass *startklass, *klass, *refklass;
3439 int i, len, match, nslots;
3440 /*FIXME, use MonoBitSet*/
3441 guint32 method_slots_default [8];
3442 guint32 *method_slots = NULL;
3443 gchar *mname = NULL;
3444 int (*compare_func) (const char *s1, const char *s2) = NULL;
3445 MonoVTable *array_vtable;
3447 MonoPtrArray tmp_array;
3449 mono_ptr_array_init (tmp_array, 4);
3451 if (!MethodInfo_array) {
3452 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3453 mono_memory_barrier ();
3454 MethodInfo_array = klass;
3457 domain = ((MonoObject *)type)->vtable->domain;
3458 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3459 if (type->type->byref)
3460 return mono_array_new_specific (array_vtable, 0);
3461 klass = startklass = mono_class_from_mono_type (type->type);
3462 refklass = mono_class_from_mono_type (reftype->type);
3466 mname = mono_string_to_utf8 (name);
3467 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3470 /* An optimization for calls made from Delegate:CreateDelegate () */
3471 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3472 method = mono_get_delegate_invoke (klass);
3473 if (mono_loader_get_last_error ())
3476 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3478 res = mono_array_new_specific (array_vtable, 1);
3479 mono_array_setref (res, 0, member);
3484 mono_class_setup_vtable (klass);
3485 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3488 if (is_generic_parameter (type->type))
3489 nslots = mono_class_get_vtable_size (klass->parent);
3491 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3492 if (nslots >= sizeof (method_slots_default) * 8) {
3493 method_slots = g_new0 (guint32, nslots / 32 + 1);
3495 method_slots = method_slots_default;
3496 memset (method_slots, 0, sizeof (method_slots_default));
3499 mono_class_setup_vtable (klass);
3500 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3504 while ((method = mono_class_get_methods (klass, &iter))) {
3506 if (method->slot != -1) {
3507 g_assert (method->slot < nslots);
3508 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3510 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3511 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3514 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3516 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3517 if (bflags & BFLAGS_Public)
3519 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3525 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3526 if (bflags & BFLAGS_Static)
3527 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3530 if (bflags & BFLAGS_Instance)
3538 if (compare_func (mname, method->name))
3544 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3546 mono_ptr_array_append (tmp_array, member);
3548 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3552 if (method_slots != method_slots_default)
3553 g_free (method_slots);
3555 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3557 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3558 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3560 mono_ptr_array_destroy (tmp_array);
3565 if (method_slots != method_slots_default)
3566 g_free (method_slots);
3567 mono_ptr_array_destroy (tmp_array);
3568 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3569 ex = mono_class_get_exception_for_failure (klass);
3571 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3572 mono_loader_clear_error ();
3574 mono_raise_exception (ex);
3579 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3582 static MonoClass *System_Reflection_ConstructorInfo;
3583 MonoClass *startklass, *klass, *refklass;
3588 gpointer iter = NULL;
3589 MonoPtrArray tmp_array;
3591 MONO_ARCH_SAVE_REGS;
3593 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3595 domain = ((MonoObject *)type)->vtable->domain;
3596 if (type->type->byref)
3597 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3598 klass = startklass = mono_class_from_mono_type (type->type);
3599 refklass = mono_class_from_mono_type (reftype->type);
3601 if (!System_Reflection_ConstructorInfo)
3602 System_Reflection_ConstructorInfo = mono_class_from_name (
3603 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3606 while ((method = mono_class_get_methods (klass, &iter))) {
3608 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3610 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3611 if (bflags & BFLAGS_Public)
3614 if (bflags & BFLAGS_NonPublic)
3620 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3621 if (bflags & BFLAGS_Static)
3622 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3625 if (bflags & BFLAGS_Instance)
3631 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3633 mono_ptr_array_append (tmp_array, member);
3636 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3638 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3639 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3641 mono_ptr_array_destroy (tmp_array);
3647 property_hash (gconstpointer data)
3649 MonoProperty *prop = (MonoProperty*)data;
3651 return g_str_hash (prop->name);
3655 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3657 // Properties are hide-by-name-and-signature
3658 if (!g_str_equal (prop1->name, prop2->name))
3661 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3663 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3669 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3674 return method_nonpublic (accessor, start_klass);
3678 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3682 static MonoClass *System_Reflection_PropertyInfo;
3683 MonoClass *startklass, *klass;
3689 gchar *propname = NULL;
3690 int (*compare_func) (const char *s1, const char *s2) = NULL;
3692 GHashTable *properties = NULL;
3693 MonoPtrArray tmp_array;
3695 MONO_ARCH_SAVE_REGS;
3697 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3699 if (!System_Reflection_PropertyInfo)
3700 System_Reflection_PropertyInfo = mono_class_from_name (
3701 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3703 domain = ((MonoObject *)type)->vtable->domain;
3704 if (type->type->byref)
3705 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3706 klass = startklass = mono_class_from_mono_type (type->type);
3709 propname = mono_string_to_utf8 (name);
3710 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3713 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3715 mono_class_setup_vtable (klass);
3716 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3720 while ((prop = mono_class_get_properties (klass, &iter))) {
3726 flags = method->flags;
3729 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3730 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3731 if (bflags & BFLAGS_Public)
3733 } else if (bflags & BFLAGS_NonPublic) {
3734 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3735 property_accessor_nonpublic(prop->set, startklass == klass)) {
3742 if (flags & METHOD_ATTRIBUTE_STATIC) {
3743 if (bflags & BFLAGS_Static)
3744 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3747 if (bflags & BFLAGS_Instance)
3756 if (compare_func (propname, prop->name))
3760 if (g_hash_table_lookup (properties, prop))
3763 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3765 g_hash_table_insert (properties, prop, prop);
3767 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3770 g_hash_table_destroy (properties);
3773 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3774 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3775 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3777 mono_ptr_array_destroy (tmp_array);
3783 g_hash_table_destroy (properties);
3786 mono_ptr_array_destroy (tmp_array);
3788 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3789 ex = mono_class_get_exception_for_failure (klass);
3791 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3792 mono_loader_clear_error ();
3794 mono_raise_exception (ex);
3798 static MonoReflectionEvent *
3799 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3802 MonoClass *klass, *startklass;
3807 int (*compare_func) (const char *s1, const char *s2);
3809 MONO_ARCH_SAVE_REGS;
3811 event_name = mono_string_to_utf8 (name);
3812 if (type->type->byref)
3814 klass = startklass = mono_class_from_mono_type (type->type);
3815 domain = mono_object_domain (type);
3817 mono_class_init_or_throw (klass);
3819 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3821 if (klass->exception_type != MONO_EXCEPTION_NONE)
3822 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3825 while ((event = mono_class_get_events (klass, &iter))) {
3826 if (compare_func (event->name, event_name))
3829 method = event->add;
3831 method = event->remove;
3833 method = event->raise;
3835 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3836 if (!(bflags & BFLAGS_Public))
3839 if (!(bflags & BFLAGS_NonPublic))
3841 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3845 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3846 if (!(bflags & BFLAGS_Static))
3848 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3851 if (!(bflags & BFLAGS_Instance))
3855 if (!(bflags & BFLAGS_NonPublic))
3858 g_free (event_name);
3859 return mono_event_get_object (domain, startklass, event);
3862 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3865 g_free (event_name);
3870 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3874 static MonoClass *System_Reflection_EventInfo;
3875 MonoClass *startklass, *klass;
3882 MonoPtrArray tmp_array;
3884 MONO_ARCH_SAVE_REGS;
3886 mono_ptr_array_init (tmp_array, 4);
3888 if (!System_Reflection_EventInfo)
3889 System_Reflection_EventInfo = mono_class_from_name (
3890 mono_defaults.corlib, "System.Reflection", "EventInfo");
3892 domain = mono_object_domain (type);
3893 if (type->type->byref)
3894 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3895 klass = startklass = mono_class_from_mono_type (type->type);
3898 mono_class_setup_vtable (klass);
3899 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3903 while ((event = mono_class_get_events (klass, &iter))) {
3905 method = event->add;
3907 method = event->remove;
3909 method = event->raise;
3911 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3912 if (bflags & BFLAGS_Public)
3914 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3915 if (bflags & BFLAGS_NonPublic)
3920 if (bflags & BFLAGS_NonPublic)
3926 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3927 if (bflags & BFLAGS_Static)
3928 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3931 if (bflags & BFLAGS_Instance)
3936 if (bflags & BFLAGS_Instance)
3940 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3942 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3945 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3947 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3948 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3950 mono_ptr_array_destroy (tmp_array);
3955 mono_ptr_array_destroy (tmp_array);
3956 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3957 ex = mono_class_get_exception_for_failure (klass);
3959 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3960 mono_loader_clear_error ();
3962 mono_raise_exception (ex);
3966 static MonoReflectionType *
3967 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3975 MONO_ARCH_SAVE_REGS;
3978 mono_raise_exception (mono_get_exception_argument_null ("name"));
3980 domain = ((MonoObject *)type)->vtable->domain;
3981 if (type->type->byref)
3983 klass = mono_class_from_mono_type (type->type);
3985 str = mono_string_to_utf8 (name);
3988 if (klass->exception_type != MONO_EXCEPTION_NONE)
3989 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3992 * If a nested type is generic, return its generic type definition.
3993 * Note that this means that the return value is essentially a
3994 * nested type of the generic type definition of @klass.
3996 * A note in MSDN claims that a generic type definition can have
3997 * nested types that aren't generic. In any case, the container of that
3998 * nested type would be the generic type definition.
4000 if (klass->generic_class)
4001 klass = klass->generic_class->container_class;
4004 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4006 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4007 if (bflags & BFLAGS_Public)
4010 if (bflags & BFLAGS_NonPublic)
4015 if (strcmp (nested->name, str) == 0){
4017 return mono_type_get_object (domain, &nested->byval_arg);
4020 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4027 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4036 MonoPtrArray tmp_array;
4038 MONO_ARCH_SAVE_REGS;
4040 domain = ((MonoObject *)type)->vtable->domain;
4041 if (type->type->byref)
4042 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4043 klass = mono_class_from_mono_type (type->type);
4046 * If a nested type is generic, return its generic type definition.
4047 * Note that this means that the return value is essentially the set
4048 * of nested types of the generic type definition of @klass.
4050 * A note in MSDN claims that a generic type definition can have
4051 * nested types that aren't generic. In any case, the container of that
4052 * nested type would be the generic type definition.
4054 if (klass->generic_class)
4055 klass = klass->generic_class->container_class;
4057 mono_ptr_array_init (tmp_array, 1);
4059 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4061 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4062 if (bflags & BFLAGS_Public)
4065 if (bflags & BFLAGS_NonPublic)
4070 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4071 mono_ptr_array_append (tmp_array, member);
4074 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4076 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4077 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4079 mono_ptr_array_destroy (tmp_array);
4084 static MonoReflectionType*
4085 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4088 MonoType *type = NULL;
4089 MonoTypeNameParse info;
4090 gboolean type_resolve;
4092 MONO_ARCH_SAVE_REGS;
4094 /* On MS.NET, this does not fire a TypeResolve event */
4095 type_resolve = TRUE;
4096 str = mono_string_to_utf8 (name);
4097 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4098 if (!mono_reflection_parse_type (str, &info)) {
4100 mono_reflection_free_type_info (&info);
4101 if (throwOnError) /* uhm: this is a parse error, though... */
4102 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4103 /*g_print ("failed parse\n");*/
4107 if (info.assembly.name) {
4109 mono_reflection_free_type_info (&info);
4111 /* 1.0 and 2.0 throw different exceptions */
4112 if (mono_defaults.generic_ilist_class)
4113 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4115 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4120 if (module != NULL) {
4122 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4127 if (assembly->assembly->dynamic) {
4128 /* Enumerate all modules */
4129 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4133 if (abuilder->modules) {
4134 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4135 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4136 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4142 if (!type && abuilder->loaded_modules) {
4143 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4144 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4145 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4152 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4154 mono_reflection_free_type_info (&info);
4156 MonoException *e = NULL;
4159 e = mono_get_exception_type_load (name, NULL);
4161 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4162 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4164 mono_loader_clear_error ();
4167 mono_raise_exception (e);
4170 } else if (mono_loader_get_last_error ()) {
4172 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4173 mono_loader_clear_error ();
4176 if (type->type == MONO_TYPE_CLASS) {
4177 MonoClass *klass = mono_type_get_class (type);
4179 if (mono_is_security_manager_active () && !klass->exception_type)
4180 /* Some security problems are detected during generic vtable construction */
4181 mono_class_setup_vtable (klass);
4182 /* need to report exceptions ? */
4183 if (throwOnError && klass->exception_type) {
4184 /* report SecurityException (or others) that occured when loading the assembly */
4185 MonoException *exc = mono_class_get_exception_for_failure (klass);
4186 mono_loader_clear_error ();
4187 mono_raise_exception (exc);
4188 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4193 /* g_print ("got it\n"); */
4194 return mono_type_get_object (mono_object_domain (assembly), type);
4198 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4201 gchar *shadow_ini_file;
4204 /* Check for shadow-copied assembly */
4205 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4206 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4208 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4209 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4215 g_free (shadow_ini_file);
4216 if (content != NULL) {
4219 *filename = content;
4227 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4229 MonoDomain *domain = mono_object_domain (assembly);
4230 MonoAssembly *mass = assembly->assembly;
4231 MonoString *res = NULL;
4236 MONO_ARCH_SAVE_REGS;
4238 if (g_path_is_absolute (mass->image->name)) {
4239 absolute = g_strdup (mass->image->name);
4240 dirname = g_path_get_dirname (absolute);
4242 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4243 dirname = g_strdup (mass->basedir);
4246 replace_shadow_path (domain, dirname, &absolute);
4251 for (i = strlen (absolute) - 1; i >= 0; i--)
4252 if (absolute [i] == '\\')
4257 uri = g_filename_to_uri (absolute, NULL, NULL);
4259 const char *prepend = "file://";
4261 if (*absolute == '/' && *(absolute + 1) == '/') {
4264 prepend = "file:///";
4267 uri = g_strconcat (prepend, absolute, NULL);
4271 res = mono_string_new (domain, uri);
4279 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4281 MonoAssembly *mass = assembly->assembly;
4283 MONO_ARCH_SAVE_REGS;
4285 return mass->in_gac;
4288 static MonoReflectionAssembly*
4289 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4293 MonoImageOpenStatus status;
4295 MONO_ARCH_SAVE_REGS;
4297 name = mono_string_to_utf8 (mname);
4298 res = mono_assembly_load_with_partial_name (name, &status);
4304 return mono_assembly_get_object (mono_domain_get (), res);
4308 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4310 MonoDomain *domain = mono_object_domain (assembly);
4313 MONO_ARCH_SAVE_REGS;
4315 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4321 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4323 MONO_ARCH_SAVE_REGS;
4325 return assembly->assembly->ref_only;
4329 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4331 MonoDomain *domain = mono_object_domain (assembly);
4333 MONO_ARCH_SAVE_REGS;
4335 return mono_string_new (domain, assembly->assembly->image->version);
4338 static MonoReflectionMethod*
4339 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4341 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4343 MONO_ARCH_SAVE_REGS;
4347 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4350 static MonoReflectionModule*
4351 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4353 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4357 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4359 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4360 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4364 MONO_ARCH_SAVE_REGS;
4366 for (i = 0; i < table->rows; ++i) {
4367 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4368 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4374 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4376 static MonoClass *System_Version = NULL;
4377 static MonoMethod *create_version = NULL;
4381 if (!System_Version) {
4382 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4383 g_assert (System_Version);
4386 if (!create_version) {
4387 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4388 create_version = mono_method_desc_search_in_class (desc, System_Version);
4389 g_assert (create_version);
4390 mono_method_desc_free (desc);
4396 args [3] = &revision;
4397 result = mono_object_new (domain, System_Version);
4398 mono_runtime_invoke (create_version, result, args, NULL);
4404 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4406 static MonoClass *System_Reflection_AssemblyName;
4408 MonoDomain *domain = mono_object_domain (assembly);
4410 static MonoMethod *create_culture = NULL;
4411 MonoImage *image = assembly->assembly->image;
4414 MONO_ARCH_SAVE_REGS;
4416 if (!System_Reflection_AssemblyName)
4417 System_Reflection_AssemblyName = mono_class_from_name (
4418 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4420 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4423 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4425 if (count > 0 && !create_culture) {
4426 MonoMethodDesc *desc = mono_method_desc_new (
4427 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4428 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4429 g_assert (create_culture);
4430 mono_method_desc_free (desc);
4433 for (i = 0; i < count; i++) {
4434 MonoReflectionAssemblyName *aname;
4435 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4437 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4439 aname = (MonoReflectionAssemblyName *) mono_object_new (
4440 domain, System_Reflection_AssemblyName);
4442 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4444 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4445 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4446 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4447 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4448 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4449 aname->versioncompat = 1; /* SameMachine (default) */
4450 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4451 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4453 if (create_culture) {
4455 MonoBoolean assembly_ref = 1;
4456 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4457 args [1] = &assembly_ref;
4458 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4461 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4462 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4463 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4465 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4466 /* public key token isn't copied - the class library will
4467 automatically generate it from the public key if required */
4468 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4469 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4471 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4472 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4475 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4478 /* note: this function doesn't return the codebase on purpose (i.e. it can
4479 be used under partial trust as path information isn't present). */
4481 mono_array_setref (result, i, aname);
4492 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4494 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4496 mono_array_setref (info->res, info->idx, name);
4501 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4503 MonoImage *img = assembly->assembly->image;
4508 MONO_ARCH_SAVE_REGS;
4510 mono_image_lock (img);
4511 mono_image_init_name_cache (img);
4514 len = g_hash_table_size (img->name_cache);
4515 mono_image_unlock (img);
4517 /*we can't create objects holding the image lock */
4518 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4520 mono_image_lock (img);
4521 /*len might have changed, create a new array*/
4522 if (len != g_hash_table_size (img->name_cache))
4527 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4528 mono_image_unlock (img);
4533 /* move this in some file in mono/util/ */
4535 g_concat_dir_and_file (const char *dir, const char *file)
4537 g_return_val_if_fail (dir != NULL, NULL);
4538 g_return_val_if_fail (file != NULL, NULL);
4541 * If the directory name doesn't have a / on the end, we need
4542 * to add one so we get a proper path to the file
4544 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4545 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4547 return g_strconcat (dir, file, NULL);
4551 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4553 char *n = mono_string_to_utf8 (name);
4554 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4556 guint32 cols [MONO_MANIFEST_SIZE];
4557 guint32 impl, file_idx;
4561 MONO_ARCH_SAVE_REGS;
4563 for (i = 0; i < table->rows; ++i) {
4564 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4565 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4566 if (strcmp (val, n) == 0)
4570 if (i == table->rows)
4573 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4576 * this code should only be called after obtaining the
4577 * ResourceInfo and handling the other cases.
4579 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4580 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4582 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4587 module = assembly->assembly->image;
4589 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4591 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4595 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4597 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4599 guint32 cols [MONO_MANIFEST_SIZE];
4600 guint32 file_cols [MONO_FILE_SIZE];
4604 MONO_ARCH_SAVE_REGS;
4606 n = mono_string_to_utf8 (name);
4607 for (i = 0; i < table->rows; ++i) {
4608 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4609 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4610 if (strcmp (val, n) == 0)
4614 if (i == table->rows)
4617 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4618 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4621 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4622 case MONO_IMPLEMENTATION_FILE:
4623 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4624 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4625 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4626 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4627 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4628 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4631 info->location = RESOURCE_LOCATION_EMBEDDED;
4634 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4635 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4636 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4637 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4638 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4639 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4641 mono_raise_exception (ex);
4643 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4645 /* Obtain info recursively */
4646 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4647 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4650 case MONO_IMPLEMENTATION_EXP_TYPE:
4651 g_assert_not_reached ();
4660 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4662 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4663 MonoArray *result = NULL;
4668 MONO_ARCH_SAVE_REGS;
4670 /* check hash if needed */
4672 n = mono_string_to_utf8 (name);
4673 for (i = 0; i < table->rows; ++i) {
4674 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4675 if (strcmp (val, n) == 0) {
4678 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4679 fn = mono_string_new (mono_object_domain (assembly), n);
4681 return (MonoObject*)fn;
4689 for (i = 0; i < table->rows; ++i) {
4690 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4694 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4697 for (i = 0; i < table->rows; ++i) {
4698 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4699 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4700 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4701 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4706 return (MonoObject*)result;
4710 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4712 MonoDomain *domain = mono_domain_get();
4715 int i, j, file_count = 0;
4716 MonoImage **modules;
4717 guint32 module_count, real_module_count;
4718 MonoTableInfo *table;
4719 guint32 cols [MONO_FILE_SIZE];
4720 MonoImage *image = assembly->assembly->image;
4722 g_assert (image != NULL);
4723 g_assert (!assembly->assembly->dynamic);
4725 table = &image->tables [MONO_TABLE_FILE];
4726 file_count = table->rows;
4728 modules = image->modules;
4729 module_count = image->module_count;
4731 real_module_count = 0;
4732 for (i = 0; i < module_count; ++i)
4734 real_module_count ++;
4736 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4737 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4739 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4741 for (i = 0; i < module_count; ++i)
4743 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4747 for (i = 0; i < file_count; ++i, ++j) {
4748 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4749 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4750 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4752 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4754 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4755 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4757 mono_array_setref (res, j, mono_module_get_object (domain, m));
4764 static MonoReflectionMethod*
4765 ves_icall_GetCurrentMethod (void)
4767 MonoMethod *m = mono_method_get_last_managed ();
4769 while (m->is_inflated)
4770 m = ((MonoMethodInflated*)m)->declaring;
4772 return mono_method_get_object (mono_domain_get (), m, NULL);
4777 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4780 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4781 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4782 //method is inflated, we should inflate it on the other class
4783 MonoGenericContext ctx;
4784 ctx.method_inst = inflated->context.method_inst;
4785 ctx.class_inst = inflated->context.class_inst;
4786 if (klass->generic_class)
4787 ctx.class_inst = klass->generic_class->context.class_inst;
4788 else if (klass->generic_container)
4789 ctx.class_inst = klass->generic_container->context.class_inst;
4790 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4793 mono_class_setup_methods (method->klass);
4794 if (method->klass->exception_type)
4796 for (i = 0; i < method->klass->method.count; ++i) {
4797 if (method->klass->methods [i] == method) {
4802 mono_class_setup_methods (klass);
4803 if (klass->exception_type)
4805 g_assert (offset >= 0 && offset < klass->method.count);
4806 return klass->methods [offset];
4809 static MonoReflectionMethod*
4810 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4814 klass = mono_class_from_mono_type (type);
4815 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4817 if (method->klass != klass) {
4818 method = mono_method_get_equivalent_method (method, klass);
4823 klass = method->klass;
4824 return mono_method_get_object (mono_domain_get (), method, klass);
4827 static MonoReflectionMethod*
4828 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4830 return mono_method_get_object (mono_domain_get (), method, NULL);
4833 static MonoReflectionMethodBody*
4834 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4836 return mono_method_body_get_object (mono_domain_get (), method);
4839 static MonoReflectionAssembly*
4840 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4842 MonoMethod *dest = NULL;
4844 MONO_ARCH_SAVE_REGS;
4846 mono_stack_walk_no_il (get_executing, &dest);
4847 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4851 static MonoReflectionAssembly*
4852 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4854 MonoDomain* domain = mono_domain_get ();
4856 MONO_ARCH_SAVE_REGS;
4858 if (!domain->entry_assembly)
4861 return mono_assembly_get_object (domain, domain->entry_assembly);
4864 static MonoReflectionAssembly*
4865 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4870 MONO_ARCH_SAVE_REGS;
4873 mono_stack_walk_no_il (get_executing, &dest);
4875 mono_stack_walk_no_il (get_caller, &dest);
4878 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4882 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4883 gboolean assembly_qualified)
4885 MonoDomain *domain = mono_object_domain (object);
4886 MonoTypeNameFormat format;
4891 format = assembly_qualified ?
4892 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4893 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4895 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4897 name = mono_type_get_name_full (object->type, format);
4901 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4906 res = mono_string_new (domain, name);
4913 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4915 MonoClass *klass = mono_class_from_mono_type (this->type);
4916 mono_class_init_or_throw (klass);
4917 return mono_security_core_clr_class_level (klass);
4921 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4923 static MonoMethod *create_culture = NULL;
4926 const char *pkey_ptr;
4928 MonoBoolean assembly_ref = 0;
4930 MONO_ARCH_SAVE_REGS;
4932 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4933 aname->major = name->major;
4934 aname->minor = name->minor;
4935 aname->build = name->build;
4936 aname->flags = name->flags;
4937 aname->revision = name->revision;
4938 aname->hashalg = name->hash_alg;
4939 aname->versioncompat = 1; /* SameMachine (default) */
4940 aname->processor_architecture = name->arch;
4942 if (by_default_version)
4943 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4946 if (absolute != NULL && *absolute != '\0') {
4947 const gchar *prepend = "file://";
4950 codebase = g_strdup (absolute);
4955 for (i = strlen (codebase) - 1; i >= 0; i--)
4956 if (codebase [i] == '\\')
4959 if (*codebase == '/' && *(codebase + 1) == '/') {
4962 prepend = "file:///";
4966 result = g_strconcat (prepend, codebase, NULL);
4972 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4976 if (!create_culture) {
4977 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4978 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4979 g_assert (create_culture);
4980 mono_method_desc_free (desc);
4983 if (name->culture) {
4984 args [0] = mono_string_new (domain, name->culture);
4985 args [1] = &assembly_ref;
4986 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4989 if (name->public_key) {
4990 pkey_ptr = (char*)name->public_key;
4991 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4993 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4994 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4995 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4996 } else if (default_publickey) {
4997 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4998 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5001 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5002 if (name->public_key_token [0]) {
5006 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5007 p = mono_array_addr (aname->keyToken, char, 0);
5009 for (i = 0, j = 0; i < 8; i++) {
5010 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5011 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5014 } else if (default_token) {
5015 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5020 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5022 MonoDomain *domain = mono_object_domain (assembly);
5023 MonoAssembly *mass = assembly->assembly;
5027 name = mono_stringify_assembly_name (&mass->aname);
5028 res = mono_string_new (domain, name);
5035 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5038 MonoAssembly *mass = assembly->assembly;
5040 MONO_ARCH_SAVE_REGS;
5042 if (g_path_is_absolute (mass->image->name)) {
5043 fill_reflection_assembly_name (mono_object_domain (assembly),
5044 aname, &mass->aname, mass->image->name, TRUE,
5048 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5050 fill_reflection_assembly_name (mono_object_domain (assembly),
5051 aname, &mass->aname, absolute, TRUE, TRUE,
5058 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5061 MonoImageOpenStatus status = MONO_IMAGE_OK;
5064 MonoAssemblyName name;
5067 MONO_ARCH_SAVE_REGS;
5069 filename = mono_string_to_utf8 (fname);
5071 dirname = g_path_get_dirname (filename);
5072 replace_shadow_path (mono_domain_get (), dirname, &filename);
5075 image = mono_image_open (filename, &status);
5081 if (status == MONO_IMAGE_IMAGE_INVALID)
5082 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5084 exc = mono_get_exception_file_not_found2 (NULL, fname);
5085 mono_raise_exception (exc);
5088 res = mono_assembly_fill_assembly_name (image, &name);
5090 mono_image_close (image);
5092 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5095 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5099 mono_image_close (image);
5103 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5104 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5106 MonoBoolean result = FALSE;
5107 MonoDeclSecurityEntry entry;
5109 /* SecurityAction.RequestMinimum */
5110 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5111 *minimum = entry.blob;
5112 *minLength = entry.size;
5115 /* SecurityAction.RequestOptional */
5116 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5117 *optional = entry.blob;
5118 *optLength = entry.size;
5121 /* SecurityAction.RequestRefuse */
5122 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5123 *refused = entry.blob;
5124 *refLength = entry.size;
5132 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5136 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5138 guint32 attrs, visibility;
5140 /* we start the count from 1 because we skip the special type <Module> */
5143 for (i = 1; i < tdef->rows; ++i) {
5144 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5145 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5146 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5150 count = tdef->rows - 1;
5152 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5153 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5155 for (i = 1; i < tdef->rows; ++i) {
5156 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5157 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5158 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5159 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5161 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5163 MonoLoaderError *error;
5166 error = mono_loader_get_last_error ();
5167 g_assert (error != NULL);
5169 ex = mono_loader_error_prepare_exception (error);
5170 mono_array_setref (*exceptions, count, ex);
5172 if (mono_loader_get_last_error ())
5173 mono_loader_clear_error ();
5182 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5184 MonoArray *res = NULL;
5185 MonoArray *exceptions = NULL;
5186 MonoImage *image = NULL;
5187 MonoTableInfo *table = NULL;
5190 int i, len, ex_count;
5192 MONO_ARCH_SAVE_REGS;
5194 domain = mono_object_domain (assembly);
5196 g_assert (!assembly->assembly->dynamic);
5197 image = assembly->assembly->image;
5198 table = &image->tables [MONO_TABLE_FILE];
5199 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5201 /* Append data from all modules in the assembly */
5202 for (i = 0; i < table->rows; ++i) {
5203 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5204 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5207 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5208 /* Append the new types to the end of the array */
5209 if (mono_array_length (res2) > 0) {
5211 MonoArray *res3, *ex3;
5213 len1 = mono_array_length (res);
5214 len2 = mono_array_length (res2);
5216 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5217 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5218 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5221 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5222 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5223 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5230 /* the ReflectionTypeLoadException must have all the types (Types property),
5231 * NULL replacing types which throws an exception. The LoaderException must
5232 * contain all exceptions for NULL items.
5235 len = mono_array_length (res);
5238 for (i = 0; i < len; i++) {
5239 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5243 klass = mono_type_get_class (t->type);
5244 if ((klass != NULL) && klass->exception_type) {
5245 /* keep the class in the list */
5246 list = g_list_append (list, klass);
5247 /* and replace Type with NULL */
5248 mono_array_setref (res, i, NULL);
5255 if (list || ex_count) {
5257 MonoException *exc = NULL;
5258 MonoArray *exl = NULL;
5259 int j, length = g_list_length (list) + ex_count;
5261 mono_loader_clear_error ();
5263 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5264 /* Types for which mono_class_get () succeeded */
5265 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5266 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5267 mono_array_setref (exl, i, exc);
5269 /* Types for which it don't */
5270 for (j = 0; j < mono_array_length (exceptions); ++j) {
5271 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5273 g_assert (i < length);
5274 mono_array_setref (exl, i, exc);
5281 exc = mono_get_exception_reflection_type_load (res, exl);
5282 mono_loader_clear_error ();
5283 mono_raise_exception (exc);
5290 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5292 MonoAssemblyName aname;
5293 MonoDomain *domain = mono_object_domain (name);
5295 gboolean is_version_defined;
5296 gboolean is_token_defined;
5298 aname.public_key = NULL;
5299 val = mono_string_to_utf8 (assname);
5300 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5301 g_free ((guint8*) aname.public_key);
5306 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5307 FALSE, is_token_defined);
5309 mono_assembly_name_free (&aname);
5310 g_free ((guint8*) aname.public_key);
5316 static MonoReflectionType*
5317 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5319 MonoDomain *domain = mono_object_domain (module);
5322 MONO_ARCH_SAVE_REGS;
5324 g_assert (module->image);
5326 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5327 /* These images do not have a global type */
5330 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5331 return mono_type_get_object (domain, &klass->byval_arg);
5335 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5337 /*if (module->image)
5338 mono_image_close (module->image);*/
5342 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5344 MonoDomain *domain = mono_object_domain (module);
5346 MONO_ARCH_SAVE_REGS;
5348 g_assert (module->image);
5349 return mono_string_new (domain, module->image->guid);
5353 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5356 if (module->image && module->image->is_module_handle)
5357 return module->image->raw_data;
5360 return (gpointer) (-1);
5364 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5366 if (image->dynamic) {
5367 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5368 *pe_kind = dyn->pe_kind;
5369 *machine = dyn->machine;
5372 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5373 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5378 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5380 return (image->md_version_major << 16) | (image->md_version_minor);
5384 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5386 MonoArray *exceptions;
5389 MONO_ARCH_SAVE_REGS;
5392 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5394 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5395 for (i = 0; i < mono_array_length (exceptions); ++i) {
5396 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5398 mono_raise_exception (ex);
5405 mono_memberref_is_method (MonoImage *image, guint32 token)
5407 if (!image->dynamic) {
5408 guint32 cols [MONO_MEMBERREF_SIZE];
5410 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5411 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5412 mono_metadata_decode_blob_size (sig, &sig);
5413 return (*sig != 0x6);
5415 MonoClass *handle_class;
5417 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5420 return mono_defaults.methodhandle_class == handle_class;
5425 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5428 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5429 mono_array_addr (type_args, MonoType*, 0));
5431 context->class_inst = NULL;
5433 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5434 mono_array_addr (method_args, MonoType*, 0));
5436 context->method_inst = NULL;
5440 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5443 int table = mono_metadata_token_table (token);
5444 int index = mono_metadata_token_index (token);
5445 MonoGenericContext context;
5447 *error = ResolveTokenError_Other;
5449 /* Validate token */
5450 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5451 (table != MONO_TABLE_TYPESPEC)) {
5452 *error = ResolveTokenError_BadTable;
5456 if (image->dynamic) {
5457 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5458 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5459 return klass ? &klass->byval_arg : NULL;
5462 init_generic_context_from_args (&context, type_args, method_args);
5463 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5464 return klass ? &klass->byval_arg : NULL;
5467 if ((index <= 0) || (index > image->tables [table].rows)) {
5468 *error = ResolveTokenError_OutOfRange;
5472 init_generic_context_from_args (&context, type_args, method_args);
5473 klass = mono_class_get_full (image, token, &context);
5475 if (mono_loader_get_last_error ())
5476 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5479 return &klass->byval_arg;
5485 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5487 int table = mono_metadata_token_table (token);
5488 int index = mono_metadata_token_index (token);
5489 MonoGenericContext context;
5492 *error = ResolveTokenError_Other;
5494 /* Validate token */
5495 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5496 (table != MONO_TABLE_MEMBERREF)) {
5497 *error = ResolveTokenError_BadTable;
5501 if (image->dynamic) {
5502 if (table == MONO_TABLE_METHOD)
5503 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5505 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5506 *error = ResolveTokenError_BadTable;
5510 init_generic_context_from_args (&context, type_args, method_args);
5511 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5514 if ((index <= 0) || (index > image->tables [table].rows)) {
5515 *error = ResolveTokenError_OutOfRange;
5518 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5519 *error = ResolveTokenError_BadTable;
5523 init_generic_context_from_args (&context, type_args, method_args);
5524 method = mono_get_method_full (image, token, NULL, &context);
5526 if (mono_loader_get_last_error ())
5527 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5533 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5535 int index = mono_metadata_token_index (token);
5537 *error = ResolveTokenError_Other;
5539 /* Validate token */
5540 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5541 *error = ResolveTokenError_BadTable;
5546 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5548 if ((index <= 0) || (index >= image->heap_us.size)) {
5549 *error = ResolveTokenError_OutOfRange;
5553 /* FIXME: What to do if the index points into the middle of a string ? */
5555 return mono_ldstr (mono_domain_get (), image, index);
5558 static MonoClassField*
5559 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5562 int table = mono_metadata_token_table (token);
5563 int index = mono_metadata_token_index (token);
5564 MonoGenericContext context;
5565 MonoClassField *field;
5567 *error = ResolveTokenError_Other;
5569 /* Validate token */
5570 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5571 *error = ResolveTokenError_BadTable;
5575 if (image->dynamic) {
5576 if (table == MONO_TABLE_FIELD)
5577 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5579 if (mono_memberref_is_method (image, token)) {
5580 *error = ResolveTokenError_BadTable;
5584 init_generic_context_from_args (&context, type_args, method_args);
5585 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5588 if ((index <= 0) || (index > image->tables [table].rows)) {
5589 *error = ResolveTokenError_OutOfRange;
5592 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5593 *error = ResolveTokenError_BadTable;
5597 init_generic_context_from_args (&context, type_args, method_args);
5598 field = mono_field_from_token (image, token, &klass, &context);
5600 if (mono_loader_get_last_error ())
5601 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5608 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5610 int table = mono_metadata_token_table (token);
5612 *error = ResolveTokenError_Other;
5615 case MONO_TABLE_TYPEDEF:
5616 case MONO_TABLE_TYPEREF:
5617 case MONO_TABLE_TYPESPEC: {
5618 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5620 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5624 case MONO_TABLE_METHOD:
5625 case MONO_TABLE_METHODSPEC: {
5626 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5628 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5632 case MONO_TABLE_FIELD: {
5633 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5635 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5639 case MONO_TABLE_MEMBERREF:
5640 if (mono_memberref_is_method (image, token)) {
5641 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5643 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5648 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5650 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5657 *error = ResolveTokenError_BadTable;
5664 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5666 int table = mono_metadata_token_table (token);
5667 int idx = mono_metadata_token_index (token);
5668 MonoTableInfo *tables = image->tables;
5673 *error = ResolveTokenError_OutOfRange;
5675 /* FIXME: Support other tables ? */
5676 if (table != MONO_TABLE_STANDALONESIG)
5682 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5685 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5687 ptr = mono_metadata_blob_heap (image, sig);
5688 len = mono_metadata_decode_blob_size (ptr, &ptr);
5690 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5691 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5695 static MonoReflectionType*
5696 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5699 int isbyref = 0, rank;
5700 char *str = mono_string_to_utf8 (smodifiers);
5703 MONO_ARCH_SAVE_REGS;
5705 klass = mono_class_from_mono_type (tb->type.type);
5707 /* logic taken from mono_reflection_parse_type(): keep in sync */
5711 if (isbyref) { /* only one level allowed by the spec */
5718 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5721 klass = mono_ptr_class_get (&klass->byval_arg);
5722 mono_class_init (klass);
5733 else if (*p != '*') { /* '*' means unknown lower bound */
5744 klass = mono_array_class_get (klass, rank);
5745 mono_class_init (klass);
5752 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5756 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5761 MONO_ARCH_SAVE_REGS;
5764 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5770 check_for_invalid_type (MonoClass *klass)
5774 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5777 name = mono_type_get_full_name (klass);
5778 str = mono_string_new (mono_domain_get (), name);
5780 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5783 static MonoReflectionType *
5784 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5786 MonoClass *klass, *aklass;
5788 MONO_ARCH_SAVE_REGS;
5790 klass = mono_class_from_mono_type (type->type);
5791 check_for_invalid_type (klass);
5793 if (rank == 0) //single dimentional array
5794 aklass = mono_array_class_get (klass, 1);
5796 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5798 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5801 static MonoReflectionType *
5802 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5806 MONO_ARCH_SAVE_REGS;
5808 klass = mono_class_from_mono_type (type->type);
5809 mono_class_init_or_throw (klass);
5810 check_for_invalid_type (klass);
5812 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5815 static MonoReflectionType *
5816 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5818 MonoClass *klass, *pklass;
5820 klass = mono_class_from_mono_type (type->type);
5821 mono_class_init_or_throw (klass);
5822 check_for_invalid_type (klass);
5824 pklass = mono_ptr_class_get (type->type);
5826 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5830 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5831 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5833 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5834 MonoObject *delegate;
5836 MonoMethod *method = info->method;
5838 MONO_ARCH_SAVE_REGS;
5840 mono_class_init_or_throw (delegate_class);
5842 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5844 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5845 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5849 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5851 if (method->dynamic) {
5852 /* Creating a trampoline would leak memory */
5853 func = mono_compile_method (method);
5855 func = mono_create_ftnptr (mono_domain_get (),
5856 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5859 mono_delegate_ctor_with_method (delegate, target, func, method);
5865 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5867 /* Reset the invoke impl to the default one */
5868 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5872 * Magic number to convert a time which is relative to
5873 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5875 #define EPOCH_ADJUST ((guint64)62135596800LL)
5878 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5880 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5883 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5885 convert_to_absolute_date(SYSTEMTIME *date)
5887 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5888 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5889 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5890 /* from the calendar FAQ */
5891 int a = (14 - date->wMonth) / 12;
5892 int y = date->wYear - a;
5893 int m = date->wMonth + 12 * a - 2;
5894 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5896 /* d is now the day of the week for the first of the month (0 == Sunday) */
5898 int day_of_week = date->wDayOfWeek;
5900 /* set day_in_month to the first day in the month which falls on day_of_week */
5901 int day_in_month = 1 + (day_of_week - d);
5902 if (day_in_month <= 0)
5905 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5906 date->wDay = day_in_month + (date->wDay - 1) * 7;
5907 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5914 * Return's the offset from GMT of a local time.
5916 * tm is a local time
5917 * t is the same local time as seconds.
5920 gmt_offset(struct tm *tm, time_t t)
5922 #if defined (HAVE_TM_GMTOFF)
5923 return tm->tm_gmtoff;
5928 g.tm_isdst = tm->tm_isdst;
5930 return (int)difftime(t, t2);
5935 * This is heavily based on zdump.c from glibc 2.2.
5937 * * data[0]: start of daylight saving time (in DateTime ticks).
5938 * * data[1]: end of daylight saving time (in DateTime ticks).
5939 * * data[2]: utcoffset (in TimeSpan ticks).
5940 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5941 * * name[0]: name of this timezone when not daylight saving.
5942 * * name[1]: name of this timezone when daylight saving.
5944 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5945 * the class library allows years between 1 and 9999.
5947 * Returns true on success and zero on failure.
5950 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5953 MonoDomain *domain = mono_domain_get ();
5954 struct tm start, tt;
5958 int is_daylight = 0, day;
5961 MONO_ARCH_SAVE_REGS;
5963 MONO_CHECK_ARG_NULL (data);
5964 MONO_CHECK_ARG_NULL (names);
5966 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5967 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5970 * no info is better than crashing: we'll need our own tz data
5971 * to make this work properly, anyway. The range is probably
5972 * reduced to 1970 .. 2037 because that is what mktime is
5973 * guaranteed to support (we get into an infinite loop
5977 memset (&start, 0, sizeof (start));
5980 start.tm_year = year-1900;
5982 t = mktime (&start);
5984 if ((year < 1970) || (year > 2037) || (t == -1)) {
5986 tt = *localtime (&t);
5987 strftime (tzone, sizeof (tzone), "%Z", &tt);
5988 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5989 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5993 gmtoff = gmt_offset (&start, t);
5995 /* For each day of the year, calculate the tm_gmtoff. */
5996 for (day = 0; day < 365; day++) {
5999 tt = *localtime (&t);
6001 /* Daylight saving starts or ends here. */
6002 if (gmt_offset (&tt, t) != gmtoff) {
6006 /* Try to find the exact hour when daylight saving starts/ends. */
6010 tt1 = *localtime (&t1);
6011 } while (gmt_offset (&tt1, t1) != gmtoff);
6013 /* Try to find the exact minute when daylight saving starts/ends. */
6016 tt1 = *localtime (&t1);
6017 } while (gmt_offset (&tt1, t1) == gmtoff);
6019 strftime (tzone, sizeof (tzone), "%Z", &tt);
6021 /* Write data, if we're already in daylight saving, we're done. */
6023 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6024 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6027 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6028 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6032 /* This is only set once when we enter daylight saving. */
6033 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6034 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6036 gmtoff = gmt_offset (&tt, t);
6041 strftime (tzone, sizeof (tzone), "%Z", &tt);
6042 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6043 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6044 mono_array_set ((*data), gint64, 0, 0);
6045 mono_array_set ((*data), gint64, 1, 0);
6046 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6047 mono_array_set ((*data), gint64, 3, 0);
6052 MonoDomain *domain = mono_domain_get ();
6053 TIME_ZONE_INFORMATION tz_info;
6058 tz_id = GetTimeZoneInformation (&tz_info);
6059 if (tz_id == TIME_ZONE_ID_INVALID)
6062 MONO_CHECK_ARG_NULL (data);
6063 MONO_CHECK_ARG_NULL (names);
6065 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6066 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6068 for (i = 0; i < 32; ++i)
6069 if (!tz_info.DaylightName [i])
6071 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6072 for (i = 0; i < 32; ++i)
6073 if (!tz_info.StandardName [i])
6075 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6077 if ((year <= 1601) || (year > 30827)) {
6079 * According to MSDN, the MS time functions can't handle dates outside
6085 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6086 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6087 tz_info.StandardDate.wYear = year;
6088 convert_to_absolute_date(&tz_info.StandardDate);
6089 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6094 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6095 tz_info.DaylightDate.wYear = year;
6096 convert_to_absolute_date(&tz_info.DaylightDate);
6097 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6102 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6104 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6105 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6112 ves_icall_System_Object_obj_address (MonoObject *this)
6114 MONO_ARCH_SAVE_REGS;
6121 static inline gint32
6122 mono_array_get_byte_length (MonoArray *array)
6128 klass = array->obj.vtable->klass;
6130 if (array->bounds == NULL)
6131 length = array->max_length;
6134 for (i = 0; i < klass->rank; ++ i)
6135 length *= array->bounds [i].length;
6138 switch (klass->element_class->byval_arg.type) {
6141 case MONO_TYPE_BOOLEAN:
6145 case MONO_TYPE_CHAR:
6153 return length * sizeof (gpointer);
6164 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6166 MONO_ARCH_SAVE_REGS;
6168 return mono_array_get_byte_length (array);
6172 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6174 MONO_ARCH_SAVE_REGS;
6176 return mono_array_get (array, gint8, idx);
6180 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6182 MONO_ARCH_SAVE_REGS;
6184 mono_array_set (array, gint8, idx, value);
6188 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6190 guint8 *src_buf, *dest_buf;
6192 MONO_ARCH_SAVE_REGS;
6194 /* watch out for integer overflow */
6195 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6198 src_buf = (guint8 *)src->vector + src_offset;
6199 dest_buf = (guint8 *)dest->vector + dest_offset;
6202 memcpy (dest_buf, src_buf, count);
6204 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6210 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6212 MonoDomain *domain = mono_object_domain (this);
6214 MonoRealProxy *rp = ((MonoRealProxy *)this);
6215 MonoTransparentProxy *tp;
6219 MONO_ARCH_SAVE_REGS;
6221 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6222 tp = (MonoTransparentProxy*) res;
6224 MONO_OBJECT_SETREF (tp, rp, rp);
6225 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6226 klass = mono_class_from_mono_type (type);
6228 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6229 tp->remote_class = mono_remote_class (domain, class_name, klass);
6231 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6235 static MonoReflectionType *
6236 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6238 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6241 /* System.Environment */
6244 ves_icall_System_Environment_get_UserName (void)
6246 MONO_ARCH_SAVE_REGS;
6248 /* using glib is more portable */
6249 return mono_string_new (mono_domain_get (), g_get_user_name ());
6254 ves_icall_System_Environment_get_MachineName (void)
6256 #if defined (HOST_WIN32)
6261 len = MAX_COMPUTERNAME_LENGTH + 1;
6262 buf = g_new (gunichar2, len);
6265 if (GetComputerName (buf, (PDWORD) &len))
6266 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6270 #elif !defined(DISABLE_SOCKETS)
6274 if (gethostname (buf, sizeof (buf)) == 0)
6275 result = mono_string_new (mono_domain_get (), buf);
6281 return mono_string_new (mono_domain_get (), "mono");
6286 ves_icall_System_Environment_get_Platform (void)
6288 #if defined (TARGET_WIN32)
6291 #elif defined(__MACH__)
6294 // For compatibility with our client code, this will be 4 for a while.
6295 // We will eventually move to 6 to match .NET, but it requires all client
6296 // code to be updated and the documentation everywhere to be updated
6307 ves_icall_System_Environment_get_NewLine (void)
6309 MONO_ARCH_SAVE_REGS;
6311 #if defined (HOST_WIN32)
6312 return mono_string_new (mono_domain_get (), "\r\n");
6314 return mono_string_new (mono_domain_get (), "\n");
6319 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6324 MONO_ARCH_SAVE_REGS;
6329 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6330 value = g_getenv (utf8_name);
6337 return mono_string_new (mono_domain_get (), value);
6341 * There is no standard way to get at environ.
6344 #ifndef __MINGW32_VERSION
6345 #if defined(__APPLE__) && !defined (__arm__)
6346 /* Apple defines this in crt_externs.h but doesn't provide that header for
6347 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6348 * in fact exist on all implementations (so far)
6350 gchar ***_NSGetEnviron(void);
6351 #define environ (*_NSGetEnviron())
6360 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6371 env_strings = GetEnvironmentStrings();
6374 env_string = env_strings;
6375 while (*env_string != '\0') {
6376 /* weird case that MS seems to skip */
6377 if (*env_string != '=')
6379 while (*env_string != '\0')
6385 domain = mono_domain_get ();
6386 names = mono_array_new (domain, mono_defaults.string_class, n);
6390 env_string = env_strings;
6391 while (*env_string != '\0') {
6392 /* weird case that MS seems to skip */
6393 if (*env_string != '=') {
6394 equal_str = wcschr(env_string, '=');
6395 g_assert(equal_str);
6396 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6397 mono_array_setref (names, n, str);
6400 while (*env_string != '\0')
6405 FreeEnvironmentStrings (env_strings);
6417 MONO_ARCH_SAVE_REGS;
6420 for (e = environ; *e != 0; ++ e)
6423 domain = mono_domain_get ();
6424 names = mono_array_new (domain, mono_defaults.string_class, n);
6427 for (e = environ; *e != 0; ++ e) {
6428 parts = g_strsplit (*e, "=", 2);
6430 str = mono_string_new (domain, *parts);
6431 mono_array_setref (names, n, str);
6444 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6446 #if !GLIB_CHECK_VERSION(2,4,0)
6447 #define g_setenv(a,b,c) setenv(a,b,c)
6448 #define g_unsetenv(a) unsetenv(a)
6452 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6457 gunichar2 *utf16_name, *utf16_value;
6459 gchar *utf8_name, *utf8_value;
6462 MONO_ARCH_SAVE_REGS;
6465 utf16_name = mono_string_to_utf16 (name);
6466 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6467 SetEnvironmentVariable (utf16_name, NULL);
6468 g_free (utf16_name);
6472 utf16_value = mono_string_to_utf16 (value);
6474 SetEnvironmentVariable (utf16_name, utf16_value);
6476 g_free (utf16_name);
6477 g_free (utf16_value);
6479 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6481 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6482 g_unsetenv (utf8_name);
6487 utf8_value = mono_string_to_utf8_checked (value, &error);
6488 if (!mono_error_ok (&error)) {
6490 mono_error_raise_exception (&error);
6492 g_setenv (utf8_name, utf8_value, TRUE);
6495 g_free (utf8_value);
6500 ves_icall_System_Environment_Exit (int result)
6502 MONO_ARCH_SAVE_REGS;
6504 mono_threads_set_shutting_down ();
6506 mono_runtime_set_shutting_down ();
6508 /* This will kill the tp threads which cannot be suspended */
6509 mono_thread_pool_cleanup ();
6511 /* Suspend all managed threads since the runtime is going away */
6512 mono_thread_suspend_all_other_threads ();
6514 mono_runtime_quit ();
6516 /* we may need to do some cleanup here... */
6521 ves_icall_System_Environment_GetGacPath (void)
6523 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6527 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6529 #if defined (HOST_WIN32)
6530 #ifndef CSIDL_FLAG_CREATE
6531 #define CSIDL_FLAG_CREATE 0x8000
6534 WCHAR path [MAX_PATH];
6535 /* Create directory if no existing */
6536 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6540 return mono_string_new_utf16 (mono_domain_get (), path, len);
6543 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6545 return mono_string_new (mono_domain_get (), "");
6549 ves_icall_System_Environment_GetLogicalDrives (void)
6551 gunichar2 buf [256], *ptr, *dname;
6553 guint initial_size = 127, size = 128;
6556 MonoString *drivestr;
6557 MonoDomain *domain = mono_domain_get ();
6560 MONO_ARCH_SAVE_REGS;
6565 while (size > initial_size) {
6566 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6567 if (size > initial_size) {
6570 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6571 initial_size = size;
6585 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6590 while (*u16) { u16++; len ++; }
6591 drivestr = mono_string_new_utf16 (domain, dname, len);
6592 mono_array_setref (result, ndrives++, drivestr);
6603 ves_icall_System_Environment_InternalGetHome (void)
6605 MONO_ARCH_SAVE_REGS;
6607 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6610 static const char *encodings [] = {
6612 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6613 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6614 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6616 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6617 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6618 "x_unicode_2_0_utf_7",
6620 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6621 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6623 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6626 "unicodefffe", "utf_16be",
6633 * Returns the internal codepage, if the value of "int_code_page" is
6634 * 1 at entry, and we can not compute a suitable code page number,
6635 * returns the code page as a string
6638 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6643 char *codepage = NULL;
6645 int want_name = *int_code_page;
6648 *int_code_page = -1;
6649 MONO_ARCH_SAVE_REGS;
6651 g_get_charset (&cset);
6652 c = codepage = strdup (cset);
6653 for (c = codepage; *c; c++){
6654 if (isascii (*c) && isalpha (*c))
6659 /* g_print ("charset: %s\n", cset); */
6661 /* handle some common aliases */
6664 for (i = 0; p != 0; ){
6665 if ((gssize) p < 7){
6667 p = encodings [++i];
6670 if (strcmp (p, codepage) == 0){
6671 *int_code_page = code;
6674 p = encodings [++i];
6677 if (strstr (codepage, "utf_8") != NULL)
6678 *int_code_page |= 0x10000000;
6681 if (want_name && *int_code_page == -1)
6682 return mono_string_new (mono_domain_get (), cset);
6688 ves_icall_System_Environment_get_HasShutdownStarted (void)
6690 if (mono_runtime_is_shutting_down ())
6693 if (mono_domain_is_unloading (mono_domain_get ()))
6700 ves_icall_System_Environment_BroadcastSettingChange (void)
6703 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6708 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6709 MonoReflectionMethod *method,
6710 MonoArray *out_args)
6712 MONO_ARCH_SAVE_REGS;
6714 mono_message_init (mono_object_domain (this), this, method, out_args);
6718 ves_icall_IsTransparentProxy (MonoObject *proxy)
6720 MONO_ARCH_SAVE_REGS;
6725 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6731 static MonoReflectionMethod *
6732 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6733 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6737 MonoMethod **vtable;
6738 MonoMethod *res = NULL;
6740 MONO_CHECK_ARG_NULL (rtype);
6741 MONO_CHECK_ARG_NULL (rmethod);
6743 method = rmethod->method;
6744 klass = mono_class_from_mono_type (rtype->type);
6745 mono_class_init_or_throw (klass);
6747 if (MONO_CLASS_IS_INTERFACE (klass))
6750 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6753 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6754 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6760 mono_class_setup_vtable (klass);
6761 vtable = klass->vtable;
6763 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6764 gboolean variance_used = FALSE;
6765 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6766 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6768 res = vtable [offs + method->slot];
6770 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6773 if (method->slot != -1)
6774 res = vtable [method->slot];
6780 return mono_method_get_object (mono_domain_get (), res, NULL);
6784 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6789 MONO_ARCH_SAVE_REGS;
6791 klass = mono_class_from_mono_type (type->type);
6792 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6794 if (enable) vtable->remote = 1;
6795 else vtable->remote = 0;
6799 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6804 MONO_ARCH_SAVE_REGS;
6806 domain = mono_object_domain (type);
6807 klass = mono_class_from_mono_type (type->type);
6808 mono_class_init_or_throw (klass);
6810 if (klass->rank >= 1) {
6811 g_assert (klass->rank == 1);
6812 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6814 /* Bypass remoting object creation check */
6815 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6820 ves_icall_System_IO_get_temp_path (void)
6822 MONO_ARCH_SAVE_REGS;
6824 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6827 #ifndef PLATFORM_NO_DRIVEINFO
6829 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6830 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6834 ULARGE_INTEGER wapi_free_bytes_avail;
6835 ULARGE_INTEGER wapi_total_number_of_bytes;
6836 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6838 MONO_ARCH_SAVE_REGS;
6840 *error = ERROR_SUCCESS;
6841 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6842 &wapi_total_number_of_free_bytes);
6845 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6846 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6847 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6849 *free_bytes_avail = 0;
6850 *total_number_of_bytes = 0;
6851 *total_number_of_free_bytes = 0;
6852 *error = GetLastError ();
6859 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6861 MONO_ARCH_SAVE_REGS;
6863 return GetDriveType (mono_string_chars (root_path_name));
6868 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6870 MONO_ARCH_SAVE_REGS;
6872 return mono_compile_method (method);
6876 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6881 MONO_ARCH_SAVE_REGS;
6883 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6885 #if defined (HOST_WIN32)
6886 /* Avoid mixing '/' and '\\' */
6889 for (i = strlen (path) - 1; i >= 0; i--)
6890 if (path [i] == '/')
6894 mcpath = mono_string_new (mono_domain_get (), path);
6901 get_bundled_app_config (void)
6903 const gchar *app_config;
6910 MONO_ARCH_SAVE_REGS;
6912 domain = mono_domain_get ();
6913 file = domain->setup->configuration_file;
6917 // Retrieve config file and remove the extension
6918 config_file = mono_string_to_utf8 (file);
6919 len = strlen (config_file) - strlen (".config");
6920 module = g_malloc0 (len + 1);
6921 memcpy (module, config_file, len);
6922 // Get the config file from the module name
6923 app_config = mono_config_string_for_assembly_file (module);
6926 g_free (config_file);
6931 return mono_string_new (mono_domain_get (), app_config);
6935 get_bundled_machine_config (void)
6937 const gchar *machine_config;
6939 MONO_ARCH_SAVE_REGS;
6941 machine_config = mono_get_machine_config ();
6943 if (!machine_config)
6946 return mono_string_new (mono_domain_get (), machine_config);
6950 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6955 MONO_ARCH_SAVE_REGS;
6957 path = g_path_get_dirname (mono_get_config_dir ());
6959 #if defined (HOST_WIN32)
6960 /* Avoid mixing '/' and '\\' */
6963 for (i = strlen (path) - 1; i >= 0; i--)
6964 if (path [i] == '/')
6968 ipath = mono_string_new (mono_domain_get (), path);
6975 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6977 MonoPEResourceDataEntry *entry;
6980 MONO_ARCH_SAVE_REGS;
6982 if (!assembly || !result || !size)
6987 image = assembly->assembly->image;
6988 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6992 *result = mono_image_rva_map (image, entry->rde_data_offset);
6997 *size = entry->rde_size;
7003 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7005 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7009 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7011 #if defined (HOST_WIN32)
7012 OutputDebugString (mono_string_chars (message));
7014 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7018 /* Only used for value types */
7020 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7025 MONO_ARCH_SAVE_REGS;
7027 domain = mono_object_domain (type);
7028 klass = mono_class_from_mono_type (type->type);
7029 mono_class_init_or_throw (klass);
7031 if (mono_class_is_nullable (klass))
7032 /* No arguments -> null */
7035 return mono_object_new (domain, klass);
7038 static MonoReflectionMethod *
7039 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7041 MonoClass *klass, *parent;
7042 MonoMethod *method = m->method;
7043 MonoMethod *result = NULL;
7045 MONO_ARCH_SAVE_REGS;
7047 if (method->klass == NULL)
7050 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7051 MONO_CLASS_IS_INTERFACE (method->klass) ||
7052 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7055 klass = method->klass;
7056 if (klass->generic_class)
7057 klass = klass->generic_class->container_class;
7060 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7061 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7062 mono_class_setup_vtable (parent);
7063 if (parent->vtable_size <= method->slot)
7068 klass = klass->parent;
7073 if (klass == method->klass)
7076 /*This is possible if definition == FALSE.
7077 * Do it here to be really sure we don't read invalid memory.
7079 if (method->slot >= klass->vtable_size)
7082 result = klass->vtable [method->slot];
7083 if (result == NULL) {
7084 /* It is an abstract method */
7085 gpointer iter = NULL;
7086 while ((result = mono_class_get_methods (klass, &iter)))
7087 if (result->slot == method->slot)
7094 return mono_method_get_object (mono_domain_get (), result, NULL);
7098 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7100 MonoMethod *method = m->method;
7102 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7107 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7109 MONO_ARCH_SAVE_REGS;
7111 iter->sig = *(MonoMethodSignature**)argsp;
7113 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7114 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7117 /* FIXME: it's not documented what start is exactly... */
7121 iter->args = argsp + sizeof (gpointer);
7123 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7125 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7129 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7131 guint32 i, arg_size;
7134 MONO_ARCH_SAVE_REGS;
7136 i = iter->sig->sentinelpos + iter->next_arg;
7138 g_assert (i < iter->sig->param_count);
7140 res.type = iter->sig->params [i];
7141 res.klass = mono_class_from_mono_type (res.type);
7142 res.value = iter->args;
7143 arg_size = mono_type_stack_size (res.type, &align);
7144 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7145 if (arg_size <= sizeof (gpointer)) {
7147 int padding = arg_size - mono_type_size (res.type, &dummy);
7148 res.value = (guint8*)res.value + padding;
7151 iter->args = (char*)iter->args + arg_size;
7154 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7160 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7162 guint32 i, arg_size;
7165 MONO_ARCH_SAVE_REGS;
7167 i = iter->sig->sentinelpos + iter->next_arg;
7169 g_assert (i < iter->sig->param_count);
7171 while (i < iter->sig->param_count) {
7172 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7174 res.type = iter->sig->params [i];
7175 res.klass = mono_class_from_mono_type (res.type);
7176 /* FIXME: endianess issue... */
7177 res.value = iter->args;
7178 arg_size = mono_type_stack_size (res.type, &align);
7179 iter->args = (char*)iter->args + arg_size;
7181 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7184 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7193 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7196 MONO_ARCH_SAVE_REGS;
7198 i = iter->sig->sentinelpos + iter->next_arg;
7200 g_assert (i < iter->sig->param_count);
7202 return iter->sig->params [i];
7206 mono_TypedReference_ToObject (MonoTypedRef tref)
7208 MONO_ARCH_SAVE_REGS;
7210 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7211 MonoObject** objp = tref.value;
7215 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7219 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7221 MONO_ARCH_SAVE_REGS;
7223 if (MONO_TYPE_IS_REFERENCE (type)) {
7224 MonoObject** objp = value;
7228 return mono_value_box (mono_domain_get (), klass, value);
7232 prelink_method (MonoMethod *method)
7234 const char *exc_class, *exc_arg;
7235 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7237 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7239 mono_raise_exception(
7240 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7242 /* create the wrapper, too? */
7246 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7248 MONO_ARCH_SAVE_REGS;
7249 prelink_method (method->method);
7253 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7255 MonoClass *klass = mono_class_from_mono_type (type->type);
7257 gpointer iter = NULL;
7258 MONO_ARCH_SAVE_REGS;
7260 mono_class_init_or_throw (klass);
7262 while ((m = mono_class_get_methods (klass, &iter)))
7266 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7268 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7269 gint32 const **exponents,
7270 gunichar2 const **digitLowerTable,
7271 gunichar2 const **digitUpperTable,
7272 gint64 const **tenPowersList,
7273 gint32 const **decHexDigits)
7275 *mantissas = Formatter_MantissaBitsTable;
7276 *exponents = Formatter_TensExponentTable;
7277 *digitLowerTable = Formatter_DigitLowerTable;
7278 *digitUpperTable = Formatter_DigitUpperTable;
7279 *tenPowersList = Formatter_TenPowersList;
7280 *decHexDigits = Formatter_DecHexDigits;
7283 /* These parameters are "readonly" in corlib/System/Char.cs */
7285 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7286 guint8 const **numeric_data,
7287 gdouble const **numeric_data_values,
7288 guint16 const **to_lower_data_low,
7289 guint16 const **to_lower_data_high,
7290 guint16 const **to_upper_data_low,
7291 guint16 const **to_upper_data_high)
7293 *category_data = CategoryData;
7294 *numeric_data = NumericData;
7295 *numeric_data_values = NumericDataValues;
7296 *to_lower_data_low = ToLowerDataLow;
7297 *to_lower_data_high = ToLowerDataHigh;
7298 *to_upper_data_low = ToUpperDataLow;
7299 *to_upper_data_high = ToUpperDataHigh;
7303 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7305 return method->method->token;
7309 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7310 * and avoid useless allocations.
7313 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7317 for (i = 0; i < type->num_mods; ++i) {
7318 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7323 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7325 for (i = 0; i < type->num_mods; ++i) {
7326 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7327 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7328 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7336 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7338 MonoType *type = param->ClassImpl->type;
7339 MonoClass *member_class = mono_object_class (param->MemberImpl);
7340 MonoMethod *method = NULL;
7343 MonoMethodSignature *sig;
7345 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7346 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7347 method = rmethod->method;
7348 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7349 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7350 if (!(method = prop->property->get))
7351 method = prop->property->set;
7354 char *type_name = mono_type_get_full_name (member_class);
7355 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7356 MonoException *ex = mono_get_exception_not_supported (msg);
7359 mono_raise_exception (ex);
7362 image = method->klass->image;
7363 pos = param->PositionImpl;
7364 sig = mono_method_signature (method);
7368 type = sig->params [pos];
7370 return type_array_from_modifiers (image, type, optional);
7374 get_property_type (MonoProperty *prop)
7376 MonoMethodSignature *sig;
7378 sig = mono_method_signature (prop->get);
7380 } else if (prop->set) {
7381 sig = mono_method_signature (prop->set);
7382 return sig->params [sig->param_count - 1];
7388 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7390 MonoType *type = get_property_type (property->property);
7391 MonoImage *image = property->klass->image;
7395 return type_array_from_modifiers (image, type, optional);
7399 *Construct a MonoType suited to be used to decode a constant blob object.
7401 * @type is the target type which will be constructed
7402 * @blob_type is the blob type, for example, that comes from the constant table
7403 * @real_type is the expected constructed type.
7406 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7408 type->type = blob_type;
7409 type->data.klass = NULL;
7410 if (blob_type == MONO_TYPE_CLASS)
7411 type->data.klass = mono_defaults.object_class;
7412 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7413 /* For enums, we need to use the base type */
7414 type->type = MONO_TYPE_VALUETYPE;
7415 type->data.klass = mono_class_from_mono_type (real_type);
7417 type->data.klass = mono_class_from_mono_type (real_type);
7421 property_info_get_default_value (MonoReflectionProperty *property)
7424 MonoProperty *prop = property->property;
7425 MonoType *type = get_property_type (prop);
7426 MonoDomain *domain = mono_object_domain (property);
7427 MonoTypeEnum def_type;
7428 const char *def_value;
7431 mono_class_init (prop->parent);
7433 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7434 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7436 def_value = mono_class_get_property_default_value (prop, &def_type);
7438 mono_type_from_blob_type (&blob_type, def_type, type);
7439 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7445 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7447 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7448 MonoCustomAttrInfo *cinfo;
7451 mono_class_init_or_throw (attr_class);
7453 cinfo = mono_reflection_get_custom_attrs_info (obj);
7456 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7458 mono_custom_attrs_free (cinfo);
7463 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7465 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7469 mono_class_init_or_throw (attr_class);
7471 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7473 if (mono_loader_get_last_error ()) {
7474 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7475 g_assert_not_reached ();
7484 ves_icall_Mono_Runtime_GetDisplayName (void)
7487 MonoString *display_name;
7489 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7490 display_name = mono_string_new (mono_domain_get (), info);
7492 return display_name;
7496 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7498 MonoString *message;
7502 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7503 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7506 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7508 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7516 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7517 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7518 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7519 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7520 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7521 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7522 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7523 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7527 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7532 gunichar2 last, prev_last, prev2_last;
7540 last = prev_last = 0, prev2_last = 0;
7541 for (i = 0; i < ilength; i++) {
7543 if (c >= sizeof (dbase64)) {
7544 exc = mono_exception_from_name_msg (mono_get_corlib (),
7545 "System", "FormatException",
7546 "Invalid character found.");
7547 mono_raise_exception (exc);
7548 } else if (isspace (c)) {
7551 prev2_last = prev_last;
7557 olength = ilength - ignored;
7559 if (allowWhitespaceOnly && olength == 0) {
7560 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7563 if ((olength & 3) != 0 || olength <= 0) {
7564 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7565 "FormatException", "Invalid length.");
7566 mono_raise_exception (exc);
7569 if (prev2_last == '=') {
7570 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7571 mono_raise_exception (exc);
7574 olength = (olength * 3) / 4;
7578 if (prev_last == '=')
7581 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7582 res_ptr = mono_array_addr (result, guchar, 0);
7583 for (i = 0; i < ilength; ) {
7586 for (k = 0; k < 4 && i < ilength;) {
7592 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7593 exc = mono_exception_from_name_msg (mono_get_corlib (),
7594 "System", "FormatException",
7595 "Invalid character found.");
7596 mono_raise_exception (exc);
7601 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7603 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7605 *res_ptr++ = (b [2] << 6) | b [3];
7607 while (i < ilength && isspace (start [i]))
7615 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7617 MONO_ARCH_SAVE_REGS;
7619 return base64_to_byte_array (mono_string_chars (str),
7620 mono_string_length (str), allowWhitespaceOnly);
7624 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7626 MONO_ARCH_SAVE_REGS;
7628 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7632 #define ICALL_TYPE(id,name,first)
7633 #define ICALL(id,name,func) Icall_ ## id,
7636 #include "metadata/icall-def.h"
7642 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7643 #define ICALL(id,name,func)
7645 #include "metadata/icall-def.h"
7651 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7652 #define ICALL(id,name,func)
7654 guint16 first_icall;
7657 static const IcallTypeDesc
7658 icall_type_descs [] = {
7659 #include "metadata/icall-def.h"
7663 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7666 #define ICALL_TYPE(id,name,first)
7669 #ifdef HAVE_ARRAY_ELEM_INIT
7670 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7671 #define MSGSTRFIELD1(line) str##line
7673 static const struct msgstrtn_t {
7674 #define ICALL(id,name,func)
7676 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7677 #include "metadata/icall-def.h"
7679 } icall_type_names_str = {
7680 #define ICALL_TYPE(id,name,first) (name),
7681 #include "metadata/icall-def.h"
7684 static const guint16 icall_type_names_idx [] = {
7685 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7686 #include "metadata/icall-def.h"
7689 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7691 static const struct msgstr_t {
7693 #define ICALL_TYPE(id,name,first)
7694 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7695 #include "metadata/icall-def.h"
7697 } icall_names_str = {
7698 #define ICALL(id,name,func) (name),
7699 #include "metadata/icall-def.h"
7702 static const guint16 icall_names_idx [] = {
7703 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7704 #include "metadata/icall-def.h"
7707 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7713 #define ICALL_TYPE(id,name,first) name,
7714 #define ICALL(id,name,func)
7715 static const char* const
7716 icall_type_names [] = {
7717 #include "metadata/icall-def.h"
7721 #define icall_type_name_get(id) (icall_type_names [(id)])
7725 #define ICALL_TYPE(id,name,first)
7726 #define ICALL(id,name,func) name,
7727 static const char* const
7729 #include "metadata/icall-def.h"
7732 #define icall_name_get(id) icall_names [(id)]
7734 #endif /* !HAVE_ARRAY_ELEM_INIT */
7738 #define ICALL_TYPE(id,name,first)
7739 #define ICALL(id,name,func) func,
7740 static const gconstpointer
7741 icall_functions [] = {
7742 #include "metadata/icall-def.h"
7746 static GHashTable *icall_hash = NULL;
7747 static GHashTable *jit_icall_hash_name = NULL;
7748 static GHashTable *jit_icall_hash_addr = NULL;
7751 mono_icall_init (void)
7755 /* check that tables are sorted: disable in release */
7758 const char *prev_class = NULL;
7759 const char *prev_method;
7761 for (i = 0; i < Icall_type_num; ++i) {
7762 const IcallTypeDesc *desc;
7765 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7766 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7767 prev_class = icall_type_name_get (i);
7768 desc = &icall_type_descs [i];
7769 num_icalls = icall_desc_num_icalls (desc);
7770 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7771 for (j = 0; j < num_icalls; ++j) {
7772 const char *methodn = icall_name_get (desc->first_icall + j);
7773 if (prev_method && strcmp (prev_method, methodn) >= 0)
7774 g_print ("method %s should come before method %s\n", methodn, prev_method);
7775 prev_method = methodn;
7780 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7784 mono_icall_cleanup (void)
7786 g_hash_table_destroy (icall_hash);
7787 g_hash_table_destroy (jit_icall_hash_name);
7788 g_hash_table_destroy (jit_icall_hash_addr);
7792 mono_add_internal_call (const char *name, gconstpointer method)
7794 mono_loader_lock ();
7796 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7798 mono_loader_unlock ();
7801 #ifdef HAVE_ARRAY_ELEM_INIT
7803 compare_method_imap (const void *key, const void *elem)
7805 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7806 return strcmp (key, method_name);
7810 find_method_icall (const IcallTypeDesc *imap, const char *name)
7812 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7815 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7819 compare_class_imap (const void *key, const void *elem)
7821 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7822 return strcmp (key, class_name);
7825 static const IcallTypeDesc*
7826 find_class_icalls (const char *name)
7828 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7831 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7836 compare_method_imap (const void *key, const void *elem)
7838 const char** method_name = (const char**)elem;
7839 return strcmp (key, *method_name);
7843 find_method_icall (const IcallTypeDesc *imap, const char *name)
7845 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7848 return (gpointer)icall_functions [(nameslot - icall_names)];
7852 compare_class_imap (const void *key, const void *elem)
7854 const char** class_name = (const char**)elem;
7855 return strcmp (key, *class_name);
7858 static const IcallTypeDesc*
7859 find_class_icalls (const char *name)
7861 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7864 return &icall_type_descs [nameslot - icall_type_names];
7870 * we should probably export this as an helper (handle nested types).
7871 * Returns the number of chars written in buf.
7874 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7876 int nspacelen, cnamelen;
7877 nspacelen = strlen (klass->name_space);
7878 cnamelen = strlen (klass->name);
7879 if (nspacelen + cnamelen + 2 > bufsize)
7882 memcpy (buf, klass->name_space, nspacelen);
7883 buf [nspacelen ++] = '.';
7885 memcpy (buf + nspacelen, klass->name, cnamelen);
7886 buf [nspacelen + cnamelen] = 0;
7887 return nspacelen + cnamelen;
7891 mono_lookup_internal_call (MonoMethod *method)
7896 int typelen = 0, mlen, siglen;
7898 const IcallTypeDesc *imap;
7900 g_assert (method != NULL);
7902 if (method->is_inflated)
7903 method = ((MonoMethodInflated *) method)->declaring;
7905 if (method->klass->nested_in) {
7906 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7910 mname [pos++] = '/';
7913 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7919 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7924 imap = find_class_icalls (mname);
7926 mname [typelen] = ':';
7927 mname [typelen + 1] = ':';
7929 mlen = strlen (method->name);
7930 memcpy (mname + typelen + 2, method->name, mlen);
7931 sigstart = mname + typelen + 2 + mlen;
7934 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7935 siglen = strlen (tmpsig);
7936 if (typelen + mlen + siglen + 6 > sizeof (mname))
7939 memcpy (sigstart + 1, tmpsig, siglen);
7940 sigstart [siglen + 1] = ')';
7941 sigstart [siglen + 2] = 0;
7944 mono_loader_lock ();
7946 res = g_hash_table_lookup (icall_hash, mname);
7948 mono_loader_unlock ();
7951 /* try without signature */
7953 res = g_hash_table_lookup (icall_hash, mname);
7955 mono_loader_unlock ();
7959 /* it wasn't found in the static call tables */
7961 mono_loader_unlock ();
7964 res = find_method_icall (imap, sigstart - mlen);
7966 mono_loader_unlock ();
7969 /* try _with_ signature */
7971 res = find_method_icall (imap, sigstart - mlen);
7973 mono_loader_unlock ();
7977 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7978 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7979 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7980 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7981 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");
7982 g_print ("If you see other errors or faults after this message they are probably related\n");
7983 g_print ("and you need to fix your mono install first.\n");
7985 mono_loader_unlock ();
7991 type_from_typename (char *typename)
7993 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7995 if (!strcmp (typename, "int"))
7996 klass = mono_defaults.int_class;
7997 else if (!strcmp (typename, "ptr"))
7998 klass = mono_defaults.int_class;
7999 else if (!strcmp (typename, "void"))
8000 klass = mono_defaults.void_class;
8001 else if (!strcmp (typename, "int32"))
8002 klass = mono_defaults.int32_class;
8003 else if (!strcmp (typename, "uint32"))
8004 klass = mono_defaults.uint32_class;
8005 else if (!strcmp (typename, "int8"))
8006 klass = mono_defaults.sbyte_class;
8007 else if (!strcmp (typename, "uint8"))
8008 klass = mono_defaults.byte_class;
8009 else if (!strcmp (typename, "int16"))
8010 klass = mono_defaults.int16_class;
8011 else if (!strcmp (typename, "uint16"))
8012 klass = mono_defaults.uint16_class;
8013 else if (!strcmp (typename, "long"))
8014 klass = mono_defaults.int64_class;
8015 else if (!strcmp (typename, "ulong"))
8016 klass = mono_defaults.uint64_class;
8017 else if (!strcmp (typename, "float"))
8018 klass = mono_defaults.single_class;
8019 else if (!strcmp (typename, "double"))
8020 klass = mono_defaults.double_class;
8021 else if (!strcmp (typename, "object"))
8022 klass = mono_defaults.object_class;
8023 else if (!strcmp (typename, "obj"))
8024 klass = mono_defaults.object_class;
8025 else if (!strcmp (typename, "string"))
8026 klass = mono_defaults.string_class;
8027 else if (!strcmp (typename, "bool"))
8028 klass = mono_defaults.boolean_class;
8029 else if (!strcmp (typename, "boolean"))
8030 klass = mono_defaults.boolean_class;
8032 g_error ("%s", typename);
8033 g_assert_not_reached ();
8035 return &klass->byval_arg;
8038 MonoMethodSignature*
8039 mono_create_icall_signature (const char *sigstr)
8044 MonoMethodSignature *res;
8046 mono_loader_lock ();
8047 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8049 mono_loader_unlock ();
8053 parts = g_strsplit (sigstr, " ", 256);
8062 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8067 * Under windows, the default pinvoke calling convention is STDCALL but
8070 res->call_convention = MONO_CALL_C;
8073 res->ret = type_from_typename (parts [0]);
8074 for (i = 1; i < len; ++i) {
8075 res->params [i - 1] = type_from_typename (parts [i]);
8080 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8082 mono_loader_unlock ();
8088 mono_find_jit_icall_by_name (const char *name)
8090 MonoJitICallInfo *info;
8091 g_assert (jit_icall_hash_name);
8093 mono_loader_lock ();
8094 info = g_hash_table_lookup (jit_icall_hash_name, name);
8095 mono_loader_unlock ();
8100 mono_find_jit_icall_by_addr (gconstpointer addr)
8102 MonoJitICallInfo *info;
8103 g_assert (jit_icall_hash_addr);
8105 mono_loader_lock ();
8106 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8107 mono_loader_unlock ();
8113 * mono_get_jit_icall_info:
8115 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8116 * caller should access it while holding the loader lock.
8119 mono_get_jit_icall_info (void)
8121 return jit_icall_hash_name;
8125 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8127 mono_loader_lock ();
8128 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8129 mono_loader_unlock ();
8133 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8135 MonoJitICallInfo *info;
8140 mono_loader_lock ();
8142 if (!jit_icall_hash_name) {
8143 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8144 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8147 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8148 g_warning ("jit icall already defined \"%s\"\n", name);
8149 g_assert_not_reached ();
8152 info = g_new0 (MonoJitICallInfo, 1);
8159 info->wrapper = func;
8161 info->wrapper = NULL;
8164 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8165 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8167 mono_loader_unlock ();