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)
30 #if defined (HAVE_WCHAR_H)
34 #include "mono/utils/mono-membar.h"
35 #include <mono/metadata/object.h>
36 #include <mono/metadata/threads.h>
37 #include <mono/metadata/threads-types.h>
38 #include <mono/metadata/threadpool.h>
39 #include <mono/metadata/monitor.h>
40 #include <mono/metadata/reflection.h>
41 #include <mono/metadata/assembly.h>
42 #include <mono/metadata/tabledefs.h>
43 #include <mono/metadata/exception.h>
44 #include <mono/metadata/file-io.h>
45 #include <mono/metadata/console-io.h>
46 #include <mono/metadata/socket-io.h>
47 #include <mono/metadata/mono-endian.h>
48 #include <mono/metadata/tokentype.h>
49 #include <mono/metadata/domain-internals.h>
50 #include <mono/metadata/metadata-internals.h>
51 #include <mono/metadata/class-internals.h>
52 #include <mono/metadata/marshal.h>
53 #include <mono/metadata/gc-internal.h>
54 #include <mono/metadata/mono-gc.h>
55 #include <mono/metadata/rand.h>
56 #include <mono/metadata/sysmath.h>
57 #include <mono/metadata/string-icalls.h>
58 #include <mono/metadata/debug-helpers.h>
59 #include <mono/metadata/process.h>
60 #include <mono/metadata/environment.h>
61 #include <mono/metadata/profiler-private.h>
62 #include <mono/metadata/locales.h>
63 #include <mono/metadata/filewatcher.h>
64 #include <mono/metadata/char-conversions.h>
65 #include <mono/metadata/security.h>
66 #include <mono/metadata/mono-config.h>
67 #include <mono/metadata/cil-coff.h>
68 #include <mono/metadata/number-formatter.h>
69 #include <mono/metadata/security-manager.h>
70 #include <mono/metadata/security-core-clr.h>
71 #include <mono/metadata/mono-perfcounters.h>
72 #include <mono/metadata/mono-debug.h>
73 #include <mono/metadata/mono-ptr-array.h>
74 #include <mono/metadata/verify-internals.h>
75 #include <mono/io-layer/io-layer.h>
76 #include <mono/utils/strtod.h>
77 #include <mono/utils/monobitset.h>
78 #include <mono/utils/mono-time.h>
79 #include <mono/utils/mono-proclib.h>
80 #include <mono/utils/mono-string.h>
81 #include <mono/utils/mono-error-internals.h>
82 #include <mono/utils/mono-mmap.h>
83 #include <mono/utils/mono-io-portability.h>
85 #if defined (HOST_WIN32)
91 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
93 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
96 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
98 static inline MonoBoolean
99 is_generic_parameter (MonoType *type)
101 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
105 mono_class_init_or_throw (MonoClass *klass)
107 if (!mono_class_init (klass))
108 mono_raise_exception (mono_class_get_exception_for_failure (klass));
112 * We expect a pointer to a char, not a string
115 mono_double_ParseImpl (char *ptr, double *result)
117 gchar *endptr = NULL;
124 *result = strtod (ptr, &endptr);
127 /* mono_strtod () is not thread-safe */
128 EnterCriticalSection (&mono_strtod_mutex);
129 *result = mono_strtod (ptr, &endptr);
130 LeaveCriticalSection (&mono_strtod_mutex);
134 if (!*ptr || (endptr && *endptr))
141 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
150 ao = (MonoArray *)this;
151 ac = (MonoClass *)ao->obj.vtable->klass;
153 esize = mono_array_element_size (ac);
154 ea = (gpointer*)((char*)ao->vector + (pos * esize));
156 if (ac->element_class->valuetype)
157 return mono_value_box (this->vtable->domain, ac->element_class, ea);
163 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
171 MONO_CHECK_ARG_NULL (idxs);
173 io = (MonoArray *)idxs;
174 ic = (MonoClass *)io->obj.vtable->klass;
176 ao = (MonoArray *)this;
177 ac = (MonoClass *)ao->obj.vtable->klass;
179 g_assert (ic->rank == 1);
180 if (io->bounds != NULL || io->max_length != ac->rank)
181 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
183 ind = (gint32 *)io->vector;
185 if (ao->bounds == NULL) {
186 if (*ind < 0 || *ind >= ao->max_length)
187 mono_raise_exception (mono_get_exception_index_out_of_range ());
189 return ves_icall_System_Array_GetValueImpl (this, *ind);
192 for (i = 0; i < ac->rank; i++)
193 if ((ind [i] < ao->bounds [i].lower_bound) ||
194 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
195 mono_raise_exception (mono_get_exception_index_out_of_range ());
197 pos = ind [0] - ao->bounds [0].lower_bound;
198 for (i = 1; i < ac->rank; i++)
199 pos = pos*ao->bounds [i].length + ind [i] -
200 ao->bounds [i].lower_bound;
202 return ves_icall_System_Array_GetValueImpl (this, pos);
206 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
208 MonoClass *ac, *vc, *ec;
220 vc = value->vtable->klass;
224 ac = this->obj.vtable->klass;
225 ec = ac->element_class;
227 esize = mono_array_element_size (ac);
228 ea = (gpointer*)((char*)this->vector + (pos * esize));
229 va = (gpointer*)((char*)value + sizeof (MonoObject));
231 if (mono_class_is_nullable (ec)) {
232 mono_nullable_init ((guint8*)ea, value, ec);
237 memset (ea, 0, esize);
241 #define NO_WIDENING_CONVERSION G_STMT_START{\
242 mono_raise_exception (mono_get_exception_argument ( \
243 "value", "not a widening conversion")); \
246 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
247 if (esize < vsize + (extra)) \
248 mono_raise_exception (mono_get_exception_argument ( \
249 "value", "not a widening conversion")); \
252 #define INVALID_CAST G_STMT_START{ \
253 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
254 mono_raise_exception (mono_get_exception_invalid_cast ()); \
257 /* Check element (destination) type. */
258 switch (ec->byval_arg.type) {
259 case MONO_TYPE_STRING:
260 switch (vc->byval_arg.type) {
261 case MONO_TYPE_STRING:
267 case MONO_TYPE_BOOLEAN:
268 switch (vc->byval_arg.type) {
269 case MONO_TYPE_BOOLEAN:
282 NO_WIDENING_CONVERSION;
289 if (!ec->valuetype) {
290 if (!mono_object_isinst (value, ec))
292 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
296 if (mono_object_isinst (value, ec)) {
297 if (ec->has_references)
298 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
300 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
307 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
309 et = ec->byval_arg.type;
310 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
311 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
313 vt = vc->byval_arg.type;
314 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
315 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
317 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
323 case MONO_TYPE_CHAR: \
324 CHECK_WIDENING_CONVERSION(0); \
325 *(etype *) ea = (etype) u64; \
327 /* You can't assign a signed value to an unsigned array. */ \
332 /* You can't assign a floating point number to an integer array. */ \
335 NO_WIDENING_CONVERSION; \
339 #define ASSIGN_SIGNED(etype) G_STMT_START{\
345 CHECK_WIDENING_CONVERSION(0); \
346 *(etype *) ea = (etype) i64; \
348 /* You can assign an unsigned value to a signed array if the array's */ \
349 /* element size is larger than the value size. */ \
354 case MONO_TYPE_CHAR: \
355 CHECK_WIDENING_CONVERSION(1); \
356 *(etype *) ea = (etype) u64; \
358 /* You can't assign a floating point number to an integer array. */ \
361 NO_WIDENING_CONVERSION; \
365 #define ASSIGN_REAL(etype) G_STMT_START{\
369 CHECK_WIDENING_CONVERSION(0); \
370 *(etype *) ea = (etype) r64; \
372 /* All integer values fit into a floating point array, so we don't */ \
373 /* need to CHECK_WIDENING_CONVERSION here. */ \
378 *(etype *) ea = (etype) i64; \
384 case MONO_TYPE_CHAR: \
385 *(etype *) ea = (etype) u64; \
392 u64 = *(guint8 *) va;
395 u64 = *(guint16 *) va;
398 u64 = *(guint32 *) va;
401 u64 = *(guint64 *) va;
407 i64 = *(gint16 *) va;
410 i64 = *(gint32 *) va;
413 i64 = *(gint64 *) va;
416 r64 = *(gfloat *) va;
419 r64 = *(gdouble *) va;
422 u64 = *(guint16 *) va;
424 case MONO_TYPE_BOOLEAN:
425 /* Boolean is only compatible with itself. */
438 NO_WIDENING_CONVERSION;
445 /* If we can't do a direct copy, let's try a widening conversion. */
448 ASSIGN_UNSIGNED (guint16);
450 ASSIGN_UNSIGNED (guint8);
452 ASSIGN_UNSIGNED (guint16);
454 ASSIGN_UNSIGNED (guint32);
456 ASSIGN_UNSIGNED (guint64);
458 ASSIGN_SIGNED (gint8);
460 ASSIGN_SIGNED (gint16);
462 ASSIGN_SIGNED (gint32);
464 ASSIGN_SIGNED (gint64);
466 ASSIGN_REAL (gfloat);
468 ASSIGN_REAL (gdouble);
472 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
476 #undef NO_WIDENING_CONVERSION
477 #undef CHECK_WIDENING_CONVERSION
478 #undef ASSIGN_UNSIGNED
484 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
492 MONO_CHECK_ARG_NULL (idxs);
494 ic = idxs->obj.vtable->klass;
495 ac = this->obj.vtable->klass;
497 g_assert (ic->rank == 1);
498 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
499 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
501 ind = (gint32 *)idxs->vector;
503 if (this->bounds == NULL) {
504 if (*ind < 0 || *ind >= this->max_length)
505 mono_raise_exception (mono_get_exception_index_out_of_range ());
507 ves_icall_System_Array_SetValueImpl (this, value, *ind);
511 for (i = 0; i < ac->rank; i++)
512 if ((ind [i] < this->bounds [i].lower_bound) ||
513 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
514 mono_raise_exception (mono_get_exception_index_out_of_range ());
516 pos = ind [0] - this->bounds [0].lower_bound;
517 for (i = 1; i < ac->rank; i++)
518 pos = pos * this->bounds [i].length + ind [i] -
519 this->bounds [i].lower_bound;
521 ves_icall_System_Array_SetValueImpl (this, value, pos);
525 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
527 MonoClass *aklass, *klass;
530 gboolean bounded = FALSE;
534 MONO_CHECK_ARG_NULL (type);
535 MONO_CHECK_ARG_NULL (lengths);
537 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
539 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
541 for (i = 0; i < mono_array_length (lengths); i++)
542 if (mono_array_get (lengths, gint32, i) < 0)
543 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
545 klass = mono_class_from_mono_type (type->type);
546 mono_class_init_or_throw (klass);
548 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
549 /* vectors are not the same as one dimensional arrays with no-zero bounds */
554 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
556 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
557 for (i = 0; i < aklass->rank; ++i) {
558 sizes [i] = mono_array_get (lengths, guint32, i);
560 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
562 sizes [i + aklass->rank] = 0;
565 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
571 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
573 MonoClass *aklass, *klass;
576 gboolean bounded = FALSE;
580 MONO_CHECK_ARG_NULL (type);
581 MONO_CHECK_ARG_NULL (lengths);
583 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
585 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
587 for (i = 0; i < mono_array_length (lengths); i++)
588 if ((mono_array_get (lengths, gint64, i) < 0) ||
589 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
590 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
592 klass = mono_class_from_mono_type (type->type);
593 mono_class_init_or_throw (klass);
595 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
596 /* vectors are not the same as one dimensional arrays with no-zero bounds */
601 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
603 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
604 for (i = 0; i < aklass->rank; ++i) {
605 sizes [i] = mono_array_get (lengths, guint64, i);
607 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
609 sizes [i + aklass->rank] = 0;
612 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
618 ves_icall_System_Array_GetRank (MonoObject *this)
622 return this->vtable->klass->rank;
626 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
628 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
633 if ((dimension < 0) || (dimension >= rank))
634 mono_raise_exception (mono_get_exception_index_out_of_range ());
636 if (this->bounds == NULL)
637 length = this->max_length;
639 length = this->bounds [dimension].length;
641 #ifdef MONO_BIG_ARRAYS
642 if (length > G_MAXINT32)
643 mono_raise_exception (mono_get_exception_overflow ());
649 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
651 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
655 if ((dimension < 0) || (dimension >= rank))
656 mono_raise_exception (mono_get_exception_index_out_of_range ());
658 if (this->bounds == NULL)
659 return this->max_length;
661 return this->bounds [dimension].length;
665 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
667 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
671 if ((dimension < 0) || (dimension >= rank))
672 mono_raise_exception (mono_get_exception_index_out_of_range ());
674 if (this->bounds == NULL)
677 return this->bounds [dimension].lower_bound;
681 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
683 int sz = mono_array_element_size (mono_object_class (arr));
684 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
688 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
693 MonoClass *src_class;
694 MonoClass *dest_class;
698 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
701 if (source->bounds || dest->bounds)
704 /* there's no integer overflow since mono_array_length returns an unsigned integer */
705 if ((dest_idx + length > mono_array_length (dest)) ||
706 (source_idx + length > mono_array_length (source)))
709 src_class = source->obj.vtable->klass->element_class;
710 dest_class = dest->obj.vtable->klass->element_class;
713 * Handle common cases.
716 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
717 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
718 // FIXME: This is racy
722 int has_refs = dest_class->has_references;
723 for (i = source_idx; i < source_idx + length; ++i) {
724 MonoObject *elem = mono_array_get (source, MonoObject*, i);
725 if (elem && !mono_object_isinst (elem, dest_class))
729 element_size = mono_array_element_size (dest->obj.vtable->klass);
730 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
731 for (i = 0; i < length; ++i) {
732 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
733 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
737 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
739 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
745 /* Check if we're copying a char[] <==> (u)short[] */
746 if (src_class != dest_class) {
747 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
750 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
752 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
753 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
754 // FIXME: This is racy
758 for (i = source_idx; i < source_idx + length; ++i) {
759 MonoObject *elem = mono_array_get (source, MonoObject*, i);
760 if (elem && !mono_object_isinst (elem, dest_class))
768 if (dest_class->valuetype) {
769 element_size = mono_array_element_size (source->obj.vtable->klass);
770 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
771 if (dest_class->has_references) {
772 mono_value_copy_array (dest, dest_idx, source_addr, length);
774 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
775 memmove (dest_addr, source_addr, element_size * length);
778 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
785 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
794 ao = (MonoArray *)this;
795 ac = (MonoClass *)ao->obj.vtable->klass;
797 esize = mono_array_element_size (ac);
798 ea = (gpointer*)((char*)ao->vector + (pos * esize));
800 memcpy (value, ea, esize);
804 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
813 ao = (MonoArray *)this;
814 ac = (MonoClass *)ao->obj.vtable->klass;
815 ec = ac->element_class;
817 esize = mono_array_element_size (ac);
818 ea = (gpointer*)((char*)ao->vector + (pos * esize));
820 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
821 g_assert (esize == sizeof (gpointer));
822 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
824 g_assert (ec->inited);
825 g_assert (esize == mono_class_value_size (ec, NULL));
826 if (ec->has_references)
827 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
829 memcpy (ea, value, esize);
834 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
836 MonoClass *klass = array->obj.vtable->klass;
837 guint32 size = mono_array_element_size (klass);
838 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
840 const char *field_data;
842 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
843 MonoException *exc = mono_get_exception_argument("array",
844 "Cannot initialize array of non-primitive type.");
845 mono_raise_exception (exc);
848 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
849 MonoException *exc = mono_get_exception_argument("field_handle",
850 "Field doesn't have an RVA");
851 mono_raise_exception (exc);
854 size *= array->max_length;
855 field_data = mono_field_get_data (field_handle);
857 if (size > mono_type_size (field_handle->type, &align)) {
858 MonoException *exc = mono_get_exception_argument("field_handle",
859 "Field not large enough to fill array");
860 mono_raise_exception (exc);
863 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
865 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
866 guint ## n *src = (guint ## n *) field_data; \
867 guint ## n *end = (guint ## n *)((char*)src + size); \
869 for (; src < end; data++, src++) { \
870 *data = read ## n (src); \
874 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
876 switch (type->type) {
893 memcpy (mono_array_addr (array, char, 0), field_data, size);
897 memcpy (mono_array_addr (array, char, 0), field_data, size);
899 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
902 double *data = (double*)mono_array_addr (array, double, 0);
904 for (i = 0; i < size; i++, data++) {
914 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
918 return offsetof (MonoString, chars);
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
926 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
929 return mono_object_clone (obj);
933 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
938 MONO_CHECK_ARG_NULL (handle);
940 klass = mono_class_from_mono_type (handle);
941 MONO_CHECK_ARG (handle, klass);
943 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
945 /* This will call the type constructor */
946 mono_runtime_class_init (vtable);
950 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
954 mono_image_check_for_module_cctor (image);
955 if (image->has_module_cctor) {
956 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
957 /*It's fine to raise the exception here*/
958 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
963 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
968 /* later make this configurable and per-arch */
969 int min_size = 4096 * 4 * sizeof (void*);
970 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
971 /* if we have no info we are optimistic and assume there is enough room */
974 current = (guint8 *)&stack_addr;
975 if (current > stack_addr) {
976 if ((current - stack_addr) < min_size)
979 if (current - (stack_addr - stack_size) < min_size)
986 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
990 return mono_object_clone (this);
994 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
997 MonoObject **values = NULL;
1001 MonoClassField* field;
1004 MONO_ARCH_SAVE_REGS;
1006 klass = mono_object_class (this);
1008 if (mono_class_num_fields (klass) == 0)
1009 return mono_object_hash (this);
1012 * Compute the starting value of the hashcode for fields of primitive
1013 * types, and return the remaining fields in an array to the managed side.
1014 * This way, we can avoid costly reflection operations in managed code.
1017 while ((field = mono_class_get_fields (klass, &iter))) {
1018 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1020 if (mono_field_is_deleted (field))
1022 /* FIXME: Add more types */
1023 switch (field->type->type) {
1025 result ^= *(gint32*)((guint8*)this + field->offset);
1027 case MONO_TYPE_STRING: {
1029 s = *(MonoString**)((guint8*)this + field->offset);
1031 result ^= mono_string_hash (s);
1036 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1037 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1038 values [count++] = o;
1044 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1045 for (i = 0; i < count; ++i)
1046 mono_array_setref (*fields, i, values [i]);
1054 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1057 MonoObject **values = NULL;
1059 MonoClassField* field;
1063 MONO_ARCH_SAVE_REGS;
1065 MONO_CHECK_ARG_NULL (that);
1067 if (this->vtable != that->vtable)
1070 klass = mono_object_class (this);
1072 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1073 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1076 * Do the comparison for fields of primitive type and return a result if
1077 * possible. Otherwise, return the remaining fields in an array to the
1078 * managed side. This way, we can avoid costly reflection operations in
1083 while ((field = mono_class_get_fields (klass, &iter))) {
1084 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1086 if (mono_field_is_deleted (field))
1088 /* FIXME: Add more types */
1089 switch (field->type->type) {
1092 case MONO_TYPE_BOOLEAN:
1093 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1098 case MONO_TYPE_CHAR:
1099 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1104 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1109 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1113 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1117 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1122 case MONO_TYPE_STRING: {
1123 MonoString *s1, *s2;
1124 guint32 s1len, s2len;
1125 s1 = *(MonoString**)((guint8*)this + field->offset);
1126 s2 = *(MonoString**)((guint8*)that + field->offset);
1129 if ((s1 == NULL) || (s2 == NULL))
1131 s1len = mono_string_length (s1);
1132 s2len = mono_string_length (s2);
1136 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1142 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1143 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1144 values [count++] = o;
1145 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1146 values [count++] = o;
1149 if (klass->enumtype)
1150 /* enums only have one non-static field */
1156 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1157 for (i = 0; i < count; ++i)
1158 mono_array_setref (*fields, i, values [i]);
1165 static MonoReflectionType *
1166 ves_icall_System_Object_GetType (MonoObject *obj)
1168 MONO_ARCH_SAVE_REGS;
1170 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1171 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1173 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1177 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1179 MONO_ARCH_SAVE_REGS;
1181 mtype->type = &obj->vtable->klass->byval_arg;
1182 g_assert (mtype->type->type);
1186 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1188 MONO_ARCH_SAVE_REGS;
1190 MONO_CHECK_ARG_NULL (obj);
1192 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1196 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1197 MonoReflectionMethod *method,
1198 MonoArray *opt_param_types)
1200 MONO_ARCH_SAVE_REGS;
1202 MONO_CHECK_ARG_NULL (method);
1204 return mono_image_create_method_token (
1205 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1209 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1211 MONO_ARCH_SAVE_REGS;
1213 mono_image_create_pefile (mb, file);
1217 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1219 MONO_ARCH_SAVE_REGS;
1221 mono_image_build_metadata (mb);
1225 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1227 MONO_ARCH_SAVE_REGS;
1229 mono_image_register_token (mb->dynamic_image, token, obj);
1233 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1235 MonoMethod **dest = data;
1237 /* skip unmanaged frames */
1253 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1255 MonoMethod **dest = data;
1257 /* skip unmanaged frames */
1262 if (!strcmp (m->klass->name_space, "System.Reflection"))
1271 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1273 MonoMethod **dest = data;
1275 /* skip unmanaged frames */
1279 if (m->wrapper_type != MONO_WRAPPER_NONE)
1282 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1296 static MonoReflectionType *
1297 type_from_name (const char *str, MonoBoolean ignoreCase)
1299 MonoType *type = NULL;
1300 MonoAssembly *assembly = NULL;
1301 MonoTypeNameParse info;
1302 char *temp_str = g_strdup (str);
1303 gboolean type_resolve = FALSE;
1305 MONO_ARCH_SAVE_REGS;
1307 /* mono_reflection_parse_type() mangles the string */
1308 if (!mono_reflection_parse_type (temp_str, &info)) {
1309 mono_reflection_free_type_info (&info);
1314 if (info.assembly.name) {
1315 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1317 MonoMethod *m = mono_method_get_last_managed ();
1318 MonoMethod *dest = m;
1320 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1325 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1326 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1327 * to crash. This only seems to happen in some strange remoting
1328 * scenarios and I was unable to figure out what's happening there.
1329 * Dec 10, 2005 - Martin.
1333 assembly = dest->klass->image->assembly;
1334 type_resolve = TRUE;
1336 g_warning (G_STRLOC);
1341 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1342 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1345 if (!info.assembly.name && !type) /* try mscorlib */
1346 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1348 if (assembly && !type && type_resolve) {
1349 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1350 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1353 mono_reflection_free_type_info (&info);
1359 return mono_type_get_object (mono_domain_get (), type);
1363 MonoReflectionType *
1364 mono_type_get (const char *str)
1366 char *copy = g_strdup (str);
1367 MonoReflectionType *type = type_from_name (copy, FALSE);
1374 static MonoReflectionType*
1375 ves_icall_type_from_name (MonoString *name,
1376 MonoBoolean throwOnError,
1377 MonoBoolean ignoreCase)
1379 char *str = mono_string_to_utf8 (name);
1380 MonoReflectionType *type;
1382 type = type_from_name (str, ignoreCase);
1385 MonoException *e = NULL;
1388 e = mono_get_exception_type_load (name, NULL);
1390 mono_loader_clear_error ();
1392 mono_raise_exception (e);
1399 static MonoReflectionType*
1400 ves_icall_type_from_handle (MonoType *handle)
1402 MonoDomain *domain = mono_domain_get ();
1404 MONO_ARCH_SAVE_REGS;
1406 return mono_type_get_object (domain, handle);
1410 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1412 MONO_ARCH_SAVE_REGS;
1414 if (c && type->type && c->type)
1415 return mono_metadata_type_equal (type->type, c->type);
1417 return (type == c) ? TRUE : FALSE;
1420 /* System.TypeCode */
1439 TYPECODE_STRING = 18
1443 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1445 int t = type->type->type;
1447 MONO_ARCH_SAVE_REGS;
1449 if (type->type->byref)
1450 return TYPECODE_OBJECT;
1454 case MONO_TYPE_VOID:
1455 return TYPECODE_OBJECT;
1456 case MONO_TYPE_BOOLEAN:
1457 return TYPECODE_BOOLEAN;
1459 return TYPECODE_BYTE;
1461 return TYPECODE_SBYTE;
1463 return TYPECODE_UINT16;
1465 return TYPECODE_INT16;
1466 case MONO_TYPE_CHAR:
1467 return TYPECODE_CHAR;
1471 return TYPECODE_OBJECT;
1473 return TYPECODE_UINT32;
1475 return TYPECODE_INT32;
1477 return TYPECODE_UINT64;
1479 return TYPECODE_INT64;
1481 return TYPECODE_SINGLE;
1483 return TYPECODE_DOUBLE;
1484 case MONO_TYPE_VALUETYPE: {
1485 MonoClass *klass = type->type->data.klass;
1487 if (klass->enumtype) {
1488 t = mono_class_enum_basetype (klass)->type;
1490 } else if (mono_is_corlib_image (klass->image)) {
1491 if (strcmp (klass->name_space, "System") == 0) {
1492 if (strcmp (klass->name, "Decimal") == 0)
1493 return TYPECODE_DECIMAL;
1494 else if (strcmp (klass->name, "DateTime") == 0)
1495 return TYPECODE_DATETIME;
1498 return TYPECODE_OBJECT;
1500 case MONO_TYPE_STRING:
1501 return TYPECODE_STRING;
1502 case MONO_TYPE_SZARRAY:
1503 case MONO_TYPE_ARRAY:
1504 case MONO_TYPE_OBJECT:
1506 case MONO_TYPE_MVAR:
1507 case MONO_TYPE_TYPEDBYREF:
1508 return TYPECODE_OBJECT;
1509 case MONO_TYPE_CLASS:
1511 MonoClass *klass = type->type->data.klass;
1512 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1513 if (strcmp (klass->name, "DBNull") == 0)
1514 return TYPECODE_DBNULL;
1517 return TYPECODE_OBJECT;
1518 case MONO_TYPE_GENERICINST:
1519 return TYPECODE_OBJECT;
1521 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1527 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1533 MONO_ARCH_SAVE_REGS;
1535 g_assert (type != NULL);
1537 domain = ((MonoObject *)type)->vtable->domain;
1539 if (!c) /* FIXME: dont know what do do here */
1542 klass = mono_class_from_mono_type (type->type);
1543 klassc = mono_class_from_mono_type (c->type);
1545 /* Interface check requires a more complex setup so we
1546 * only do for them. Otherwise we simply avoid mono_class_init.
1548 if (check_interfaces) {
1549 mono_class_init_or_throw (klass);
1550 mono_class_init_or_throw (klassc);
1551 } else if (!klass->supertypes || !klassc->supertypes) {
1552 mono_loader_lock ();
1553 mono_class_setup_supertypes (klass);
1554 mono_class_setup_supertypes (klassc);
1555 mono_loader_unlock ();
1558 if (type->type->byref)
1559 return klassc == mono_defaults.object_class;
1561 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1565 mono_type_is_primitive (MonoType *type)
1567 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1568 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1572 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1574 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1575 return mono_class_enum_basetype (type->data.klass);
1576 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1577 return mono_class_enum_basetype (type->data.generic_class->container_class);
1582 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1588 MONO_ARCH_SAVE_REGS;
1590 g_assert (type != NULL);
1592 domain = ((MonoObject *)type)->vtable->domain;
1594 klass = mono_class_from_mono_type (type->type);
1595 klassc = mono_class_from_mono_type (c->type);
1597 mono_class_init_or_throw (klass);
1598 mono_class_init_or_throw (klassc);
1600 if (type->type->byref ^ c->type->byref)
1603 if (type->type->byref) {
1604 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1605 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1607 klass = mono_class_from_mono_type (t);
1608 klassc = mono_class_from_mono_type (ot);
1610 if (mono_type_is_primitive (t)) {
1611 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1612 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1613 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1614 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1615 return t->type == ot->type;
1617 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1620 if (klass->valuetype)
1621 return klass == klassc;
1622 return klass->valuetype == klassc->valuetype;
1625 return mono_class_is_assignable_from (klass, klassc);
1629 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1631 MonoClass *klass = mono_class_from_mono_type (type->type);
1632 mono_class_init_or_throw (klass);
1633 return mono_object_isinst (obj, klass) != NULL;
1637 ves_icall_get_attributes (MonoReflectionType *type)
1639 MonoClass *klass = mono_class_from_mono_type (type->type);
1640 return klass->flags;
1643 static MonoReflectionMarshal*
1644 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1646 MonoClass *klass = field->field->parent;
1647 MonoMarshalType *info;
1650 if (klass->generic_container ||
1651 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1654 info = mono_marshal_load_type_info (klass);
1656 for (i = 0; i < info->num_fields; ++i) {
1657 if (info->fields [i].field == field->field) {
1658 if (!info->fields [i].mspec)
1661 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1668 static MonoReflectionField*
1669 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1671 gboolean found = FALSE;
1678 klass = handle->parent;
1680 klass = mono_class_from_mono_type (type);
1682 /* Check that the field belongs to the class */
1683 for (k = klass; k; k = k->parent) {
1684 if (k == handle->parent) {
1691 /* The managed code will throw the exception */
1695 return mono_field_get_object (mono_domain_get (), klass, handle);
1699 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1702 MonoType *type = mono_field_get_type_checked (field->field, &error);
1703 if (!mono_error_ok (&error))
1704 mono_error_raise_exception (&error);
1706 return type_array_from_modifiers (field->field->parent->image, type, optional);
1710 vell_icall_get_method_attributes (MonoMethod *method)
1712 return method->flags;
1716 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1719 MonoDomain *domain = mono_domain_get ();
1720 MonoMethodSignature* sig;
1721 MONO_ARCH_SAVE_REGS;
1723 sig = mono_method_signature_checked (method, &error);
1724 if (!mono_error_ok (&error))
1725 mono_error_raise_exception (&error);
1728 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1729 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1730 info->attrs = method->flags;
1731 info->implattrs = method->iflags;
1732 if (sig->call_convention == MONO_CALL_DEFAULT)
1733 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1735 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1740 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1744 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1746 MonoDomain *domain = mono_domain_get ();
1748 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1751 static MonoReflectionMarshal*
1752 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1754 MonoDomain *domain = mono_domain_get ();
1755 MonoReflectionMarshal* res = NULL;
1756 MonoMarshalSpec **mspecs;
1759 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1760 mono_method_get_marshal_info (method, mspecs);
1763 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1765 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1767 mono_metadata_free_marshal_spec (mspecs [i]);
1774 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1776 MonoClass *parent = field->field->parent;
1777 if (!parent->size_inited)
1778 mono_class_init (parent);
1780 return field->field->offset - sizeof (MonoObject);
1783 static MonoReflectionType*
1784 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1787 MONO_ARCH_SAVE_REGS;
1789 parent = declaring? field->field->parent: field->klass;
1791 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1795 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1797 MonoClass *fklass = field->klass;
1798 MonoClassField *cf = field->field;
1799 MonoDomain *domain = mono_object_domain (field);
1801 if (fklass->image->assembly->ref_only)
1802 mono_raise_exception (mono_get_exception_invalid_operation (
1803 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1805 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1806 mono_security_core_clr_ensure_reflection_access_field (cf);
1808 return mono_field_get_value_object (domain, cf, obj);
1812 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1815 MonoClassField *cf = field->field;
1819 MONO_ARCH_SAVE_REGS;
1821 if (field->klass->image->assembly->ref_only)
1822 mono_raise_exception (mono_get_exception_invalid_operation (
1823 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1825 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1826 mono_security_core_clr_ensure_reflection_access_field (cf);
1828 type = mono_field_get_type_checked (cf, &error);
1829 if (!mono_error_ok (&error))
1830 mono_error_raise_exception (&error);
1832 v = (gchar *) value;
1834 switch (type->type) {
1837 case MONO_TYPE_BOOLEAN:
1840 case MONO_TYPE_CHAR:
1849 case MONO_TYPE_VALUETYPE:
1852 v += sizeof (MonoObject);
1854 case MONO_TYPE_STRING:
1855 case MONO_TYPE_OBJECT:
1856 case MONO_TYPE_CLASS:
1857 case MONO_TYPE_ARRAY:
1858 case MONO_TYPE_SZARRAY:
1861 case MONO_TYPE_GENERICINST: {
1862 MonoGenericClass *gclass = type->data.generic_class;
1863 g_assert (!gclass->context.class_inst->is_open);
1865 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1866 MonoClass *nklass = mono_class_from_mono_type (type);
1867 MonoObject *nullable;
1870 * Convert the boxed vtype into a Nullable structure.
1871 * This is complicated by the fact that Nullables have
1872 * a variable structure.
1874 nullable = mono_object_new (mono_domain_get (), nklass);
1876 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1878 v = mono_object_unbox (nullable);
1881 if (gclass->container_class->valuetype && (v != NULL))
1882 v += sizeof (MonoObject);
1886 g_error ("type 0x%x not handled in "
1887 "ves_icall_FieldInfo_SetValueInternal", type->type);
1892 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1893 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1894 if (!vtable->initialized)
1895 mono_runtime_class_init (vtable);
1896 mono_field_static_set_value (vtable, cf, v);
1898 mono_field_set_value (obj, cf, v);
1903 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1905 MonoObject *o = NULL;
1906 MonoClassField *field = this->field;
1908 MonoDomain *domain = mono_object_domain (this);
1910 MonoTypeEnum def_type;
1911 const char *def_value;
1913 MONO_ARCH_SAVE_REGS;
1915 mono_class_init (field->parent);
1917 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1918 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1920 if (field->parent->image->dynamic) {
1922 g_assert_not_reached ();
1925 def_value = mono_class_get_field_default_value (field, &def_type);
1927 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1931 case MONO_TYPE_BOOLEAN:
1934 case MONO_TYPE_CHAR:
1942 case MONO_TYPE_R8: {
1945 /* boxed value type */
1946 t = g_new0 (MonoType, 1);
1948 klass = mono_class_from_mono_type (t);
1950 o = mono_object_new (domain, klass);
1951 v = ((gchar *) o) + sizeof (MonoObject);
1952 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1955 case MONO_TYPE_STRING:
1956 case MONO_TYPE_CLASS:
1957 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1960 g_assert_not_reached ();
1966 static MonoReflectionType*
1967 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1970 MonoClassField *field = ref_field->field;
1971 MonoType *type = mono_field_get_type_checked (field, &error);
1972 if (!mono_error_ok (&error))
1973 mono_error_raise_exception (&error);
1974 return mono_type_get_object (mono_object_domain (ref_field), type);
1977 static MonoReflectionType*
1978 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1980 MonoMethod *method = rmethod->method.method;
1982 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1985 /* From MonoProperty.cs */
1987 PInfo_Attributes = 1,
1988 PInfo_GetMethod = 1 << 1,
1989 PInfo_SetMethod = 1 << 2,
1990 PInfo_ReflectedType = 1 << 3,
1991 PInfo_DeclaringType = 1 << 4,
1996 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1998 MonoDomain *domain = mono_object_domain (property);
2000 MONO_ARCH_SAVE_REGS;
2002 if ((req_info & PInfo_ReflectedType) != 0)
2003 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2004 if ((req_info & PInfo_DeclaringType) != 0)
2005 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2007 if ((req_info & PInfo_Name) != 0)
2008 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2010 if ((req_info & PInfo_Attributes) != 0)
2011 info->attrs = property->property->attrs;
2013 if ((req_info & PInfo_GetMethod) != 0)
2014 MONO_STRUCT_SETREF (info, get, property->property->get ?
2015 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2017 if ((req_info & PInfo_SetMethod) != 0)
2018 MONO_STRUCT_SETREF (info, set, property->property->set ?
2019 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2021 * There may be other methods defined for properties, though, it seems they are not exposed
2022 * in the reflection API
2027 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2029 MonoDomain *domain = mono_object_domain (event);
2031 MONO_ARCH_SAVE_REGS;
2033 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2034 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2036 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2037 info->attrs = event->event->attrs;
2038 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2039 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2040 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2042 #ifndef MONO_SMALL_CONFIG
2043 if (event->event->other) {
2045 while (event->event->other [n])
2047 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2049 for (i = 0; i < n; i++)
2050 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2056 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2061 mono_class_setup_interfaces (klass, error);
2062 if (!mono_error_ok (error))
2065 for (i = 0; i < klass->interface_count; i++) {
2066 ic = klass->interfaces [i];
2067 g_hash_table_insert (ifaces, ic, ic);
2069 collect_interfaces (ic, ifaces, error);
2070 if (!mono_error_ok (error))
2076 MonoArray *iface_array;
2077 MonoGenericContext *context;
2081 } FillIfaceArrayData;
2084 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2086 FillIfaceArrayData *data = user_data;
2087 MonoClass *ic = key;
2088 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2090 if (!mono_error_ok (data->error))
2093 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2094 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2095 if (!mono_error_ok (data->error))
2099 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2102 mono_metadata_free_type (inflated);
2106 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2109 MonoClass *class = mono_class_from_mono_type (type->type);
2111 FillIfaceArrayData data = { 0 };
2114 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2116 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2117 data.context = mono_class_get_context (class);
2118 class = class->generic_class->container_class;
2121 for (parent = class; parent; parent = parent->parent) {
2122 mono_class_setup_interfaces (parent, &error);
2123 if (!mono_error_ok (&error))
2125 collect_interfaces (parent, iface_hash, &error);
2126 if (!mono_error_ok (&error))
2130 data.error = &error;
2131 data.domain = mono_object_domain (type);
2133 len = g_hash_table_size (iface_hash);
2135 g_hash_table_destroy (iface_hash);
2136 if (!data.domain->empty_types)
2137 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2138 return data.domain->empty_types;
2141 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2142 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2143 if (!mono_error_ok (&error))
2146 g_hash_table_destroy (iface_hash);
2147 return data.iface_array;
2150 g_hash_table_destroy (iface_hash);
2151 mono_error_raise_exception (&error);
2156 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2158 gboolean variance_used;
2159 MonoClass *class = mono_class_from_mono_type (type->type);
2160 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2161 MonoReflectionMethod *member;
2164 int i = 0, len, ioffset;
2167 MONO_ARCH_SAVE_REGS;
2168 mono_class_init_or_throw (class);
2169 mono_class_init_or_throw (iclass);
2171 mono_class_setup_vtable (class);
2173 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2177 len = mono_class_num_methods (iclass);
2178 domain = mono_object_domain (type);
2179 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2180 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2182 while ((method = mono_class_get_methods (iclass, &iter))) {
2183 member = mono_method_get_object (domain, method, iclass);
2184 mono_array_setref (*methods, i, member);
2185 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2186 mono_array_setref (*targets, i, member);
2193 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2195 MonoClass *klass = mono_class_from_mono_type (type->type);
2196 mono_class_init_or_throw (klass);
2198 if (klass->image->dynamic) {
2199 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2200 *packing = tb->packing_size;
2201 *size = tb->class_size;
2203 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2207 static MonoReflectionType*
2208 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2212 MONO_ARCH_SAVE_REGS;
2214 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2215 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2217 class = mono_class_from_mono_type (type->type);
2218 mono_class_init_or_throw (class);
2220 // GetElementType should only return a type for:
2221 // Array Pointer PassedByRef
2222 if (type->type->byref)
2223 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2224 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2225 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2226 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2227 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2232 static MonoReflectionType*
2233 ves_icall_get_type_parent (MonoReflectionType *type)
2235 MonoClass *class = mono_class_from_mono_type (type->type);
2236 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2240 ves_icall_type_ispointer (MonoReflectionType *type)
2242 MONO_ARCH_SAVE_REGS;
2244 return type->type->type == MONO_TYPE_PTR;
2248 ves_icall_type_isprimitive (MonoReflectionType *type)
2250 MONO_ARCH_SAVE_REGS;
2252 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)));
2256 ves_icall_type_isbyref (MonoReflectionType *type)
2258 MONO_ARCH_SAVE_REGS;
2260 return type->type->byref;
2264 ves_icall_type_iscomobject (MonoReflectionType *type)
2266 MonoClass *klass = mono_class_from_mono_type (type->type);
2267 mono_class_init_or_throw (klass);
2269 return (klass && klass->is_com_object);
2272 static MonoReflectionModule*
2273 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2275 MonoClass *class = mono_class_from_mono_type (type->type);
2276 return mono_module_get_object (mono_object_domain (type), class->image);
2279 static MonoReflectionAssembly*
2280 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2282 MonoDomain *domain = mono_domain_get ();
2283 MonoClass *class = mono_class_from_mono_type (type->type);
2284 return mono_assembly_get_object (domain, class->image->assembly);
2287 static MonoReflectionType*
2288 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2290 MonoDomain *domain = mono_domain_get ();
2293 MONO_ARCH_SAVE_REGS;
2295 if (type->type->byref)
2297 if (type->type->type == MONO_TYPE_VAR)
2298 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2299 else if (type->type->type == MONO_TYPE_MVAR)
2300 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2302 class = mono_class_from_mono_type (type->type)->nested_in;
2304 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2308 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2310 MonoDomain *domain = mono_domain_get ();
2311 MonoClass *class = mono_class_from_mono_type (type->type);
2313 if (type->type->byref) {
2314 char *n = g_strdup_printf ("%s&", class->name);
2315 MonoString *res = mono_string_new (domain, n);
2321 return mono_string_new (domain, class->name);
2326 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2328 MonoDomain *domain = mono_domain_get ();
2329 MonoClass *class = mono_class_from_mono_type (type->type);
2331 while (class->nested_in)
2332 class = class->nested_in;
2334 if (class->name_space [0] == '\0')
2337 return mono_string_new (domain, class->name_space);
2341 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2345 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2346 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2348 class = mono_class_from_mono_type (type->type);
2354 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2357 MonoClass *klass, *pklass;
2358 MonoDomain *domain = mono_object_domain (type);
2359 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2361 MONO_ARCH_SAVE_REGS;
2363 klass = mono_class_from_mono_type (type->type);
2365 if (klass->generic_container) {
2366 MonoGenericContainer *container = klass->generic_container;
2367 res = mono_array_new_specific (array_vtable, container->type_argc);
2368 for (i = 0; i < container->type_argc; ++i) {
2369 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2370 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2372 } else if (klass->generic_class) {
2373 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2374 res = mono_array_new_specific (array_vtable, inst->type_argc);
2375 for (i = 0; i < inst->type_argc; ++i)
2376 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2378 res = mono_array_new_specific (array_vtable, 0);
2384 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2387 MONO_ARCH_SAVE_REGS;
2389 if (!IS_MONOTYPE (type))
2392 if (type->type->byref)
2395 klass = mono_class_from_mono_type (type->type);
2396 return klass->generic_container != NULL;
2399 static MonoReflectionType*
2400 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2403 MONO_ARCH_SAVE_REGS;
2405 if (type->type->byref)
2408 klass = mono_class_from_mono_type (type->type);
2410 if (klass->generic_container) {
2411 return type; /* check this one */
2413 if (klass->generic_class) {
2414 MonoClass *generic_class = klass->generic_class->container_class;
2417 tb = mono_class_get_ref_info (generic_class);
2419 if (generic_class->wastypebuilder && tb)
2422 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2427 static MonoReflectionType*
2428 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2431 MonoType *geninst, **types;
2434 g_assert (IS_MONOTYPE (type));
2435 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2437 count = mono_array_length (type_array);
2438 types = g_new0 (MonoType *, count);
2440 for (i = 0; i < count; i++) {
2441 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2442 types [i] = t->type;
2445 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2450 class = mono_class_from_mono_type (geninst);
2452 /*we might inflate to the GTD*/
2453 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2454 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2456 return mono_type_get_object (mono_object_domain (type), geninst);
2460 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2463 MONO_ARCH_SAVE_REGS;
2465 if (type->type->byref)
2468 klass = mono_class_from_mono_type (type->type);
2470 return klass->generic_class != NULL;
2474 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2477 MONO_ARCH_SAVE_REGS;
2479 if (!IS_MONOTYPE (type))
2482 if (type->type->byref)
2485 klass = mono_class_from_mono_type (type->type);
2486 return klass->generic_class != NULL || klass->generic_container != NULL;
2490 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2492 MONO_ARCH_SAVE_REGS;
2494 if (!IS_MONOTYPE (type))
2497 if (is_generic_parameter (type->type))
2498 return mono_type_get_generic_param_num (type->type);
2502 static GenericParameterAttributes
2503 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2505 MONO_ARCH_SAVE_REGS;
2507 g_assert (IS_MONOTYPE (type));
2508 g_assert (is_generic_parameter (type->type));
2509 return mono_generic_param_info (type->type->data.generic_param)->flags;
2513 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2515 MonoGenericParamInfo *param_info;
2521 MONO_ARCH_SAVE_REGS;
2523 g_assert (IS_MONOTYPE (type));
2525 domain = mono_object_domain (type);
2526 param_info = mono_generic_param_info (type->type->data.generic_param);
2527 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2530 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2531 for (i = 0; i < count; i++)
2532 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2539 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2541 MONO_ARCH_SAVE_REGS;
2542 return is_generic_parameter (type->type);
2546 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2548 MONO_ARCH_SAVE_REGS;
2549 return is_generic_parameter (tb->type.type);
2553 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2554 MonoReflectionType *t)
2556 enumtype->type = t->type;
2559 static MonoReflectionMethod*
2560 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2561 MonoReflectionMethod* generic)
2568 MONO_ARCH_SAVE_REGS;
2570 domain = ((MonoObject *)type)->vtable->domain;
2572 klass = mono_class_from_mono_type (type->type);
2573 mono_class_init_or_throw (klass);
2576 while ((method = mono_class_get_methods (klass, &iter))) {
2577 if (method->token == generic->method->token)
2578 return mono_method_get_object (domain, method, klass);
2586 static MonoReflectionMethod *
2587 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2590 MonoType *type = ref_type->type;
2592 MONO_ARCH_SAVE_REGS;
2594 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2595 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2596 if (type->type == MONO_TYPE_VAR)
2599 method = mono_type_get_generic_param_owner (type)->owner.method;
2601 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2604 static MonoReflectionDllImportAttribute*
2605 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2607 static MonoClass *DllImportAttributeClass = NULL;
2608 MonoDomain *domain = mono_domain_get ();
2609 MonoReflectionDllImportAttribute *attr;
2610 MonoImage *image = method->klass->image;
2611 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2612 MonoTableInfo *tables = image->tables;
2613 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2614 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2615 guint32 im_cols [MONO_IMPLMAP_SIZE];
2616 guint32 scope_token;
2617 const char *import = NULL;
2618 const char *scope = NULL;
2621 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2624 if (!DllImportAttributeClass) {
2625 DllImportAttributeClass =
2626 mono_class_from_name (mono_defaults.corlib,
2627 "System.Runtime.InteropServices", "DllImportAttribute");
2628 g_assert (DllImportAttributeClass);
2631 if (method->klass->image->dynamic) {
2632 MonoReflectionMethodAux *method_aux =
2633 g_hash_table_lookup (
2634 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2636 import = method_aux->dllentry;
2637 scope = method_aux->dll;
2640 if (!import || !scope) {
2641 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2646 if (piinfo->implmap_idx) {
2647 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2649 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2650 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2651 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2652 scope = mono_metadata_string_heap (image, scope_token);
2655 flags = piinfo->piflags;
2657 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2659 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2660 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2661 attr->call_conv = (flags & 0x700) >> 8;
2662 attr->charset = ((flags & 0x6) >> 1) + 1;
2663 if (attr->charset == 1)
2665 attr->exact_spelling = (flags & 0x1) != 0;
2666 attr->set_last_error = (flags & 0x40) != 0;
2667 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2668 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2669 attr->preserve_sig = FALSE;
2674 static MonoReflectionMethod *
2675 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2677 MonoMethodInflated *imethod;
2680 MONO_ARCH_SAVE_REGS;
2682 if (method->method->is_generic)
2685 if (!method->method->is_inflated)
2688 imethod = (MonoMethodInflated *) method->method;
2690 result = imethod->declaring;
2691 /* Not a generic method. */
2692 if (!result->is_generic)
2695 if (method->method->klass->image->dynamic) {
2696 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2697 MonoReflectionMethod *res;
2700 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2701 * the dynamic case as well ?
2703 mono_loader_lock ();
2704 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2705 mono_loader_unlock ();
2711 if (imethod->context.class_inst) {
2712 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2713 /*Generic methods gets the context of the GTD.*/
2714 if (mono_class_get_context (klass))
2715 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2718 return mono_method_get_object (mono_object_domain (method), result, NULL);
2722 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2724 MONO_ARCH_SAVE_REGS;
2726 return mono_method_signature (method->method)->generic_param_count != 0;
2730 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2732 MONO_ARCH_SAVE_REGS;
2734 return method->method->is_generic;
2738 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2743 MONO_ARCH_SAVE_REGS;
2745 domain = mono_object_domain (method);
2747 if (method->method->is_inflated) {
2748 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2751 count = inst->type_argc;
2752 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2754 for (i = 0; i < count; i++)
2755 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2761 count = mono_method_signature (method->method)->generic_param_count;
2762 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2764 for (i = 0; i < count; i++) {
2765 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2766 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2767 MonoClass *pklass = mono_class_from_generic_parameter (
2768 param, method->method->klass->image, TRUE);
2769 mono_array_setref (res, i,
2770 mono_type_get_object (domain, &pklass->byval_arg));
2777 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2780 * Invoke from reflection is supposed to always be a virtual call (the API
2781 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2782 * greater flexibility.
2784 MonoMethod *m = method->method;
2788 MONO_ARCH_SAVE_REGS;
2792 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2793 mono_security_core_clr_ensure_reflection_access_method (m);
2795 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2796 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2797 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2802 if (!mono_object_isinst (this, m->klass)) {
2803 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2806 m = mono_object_get_virtual_method (this, m);
2807 /* must pass the pointer to the value for valuetype methods */
2808 if (m->klass->valuetype)
2809 obj = mono_object_unbox (this);
2810 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2811 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2816 pcount = params? mono_array_length (params): 0;
2817 if (pcount != mono_method_signature (m)->param_count) {
2818 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2822 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2823 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."));
2827 if (m->klass->image->assembly->ref_only) {
2828 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."));
2832 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2835 intptr_t *lower_bounds;
2836 pcount = mono_array_length (params);
2837 lengths = alloca (sizeof (uintptr_t) * pcount);
2838 /* Note: the synthetized array .ctors have int32 as argument type */
2839 for (i = 0; i < pcount; ++i)
2840 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2842 if (m->klass->rank == pcount) {
2843 /* Only lengths provided. */
2844 lower_bounds = NULL;
2846 g_assert (pcount == (m->klass->rank * 2));
2847 /* lower bounds are first. */
2848 lower_bounds = (intptr_t*)lengths;
2849 lengths += m->klass->rank;
2852 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2854 return mono_runtime_invoke_array (m, obj, params, NULL);
2858 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2860 MonoDomain *domain = mono_object_domain (method);
2861 MonoMethod *m = method->method;
2862 MonoMethodSignature *sig = mono_method_signature (m);
2863 MonoArray *out_args;
2865 int i, j, outarg_count = 0;
2867 MONO_ARCH_SAVE_REGS;
2869 if (m->klass == mono_defaults.object_class) {
2871 if (!strcmp (m->name, "FieldGetter")) {
2872 MonoClass *k = this->vtable->klass;
2876 /* If this is a proxy, then it must be a CBO */
2877 if (k == mono_defaults.transparent_proxy_class) {
2878 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2879 this = tp->rp->unwrapped_server;
2881 k = this->vtable->klass;
2884 name = mono_array_get (params, MonoString *, 1);
2885 str = mono_string_to_utf8 (name);
2888 MonoClassField* field = mono_class_get_field_from_name (k, str);
2890 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2891 if (field_klass->valuetype)
2892 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2894 result = *((gpointer *)((char *)this + field->offset));
2896 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2897 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2898 mono_array_setref (out_args, 0, result);
2906 g_assert_not_reached ();
2908 } else if (!strcmp (m->name, "FieldSetter")) {
2909 MonoClass *k = this->vtable->klass;
2915 /* If this is a proxy, then it must be a CBO */
2916 if (k == mono_defaults.transparent_proxy_class) {
2917 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2918 this = tp->rp->unwrapped_server;
2920 k = this->vtable->klass;
2923 name = mono_array_get (params, MonoString *, 1);
2924 str = mono_string_to_utf8 (name);
2927 MonoClassField* field = mono_class_get_field_from_name (k, str);
2929 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2930 MonoObject *val = mono_array_get (params, gpointer, 2);
2932 if (field_klass->valuetype) {
2933 size = mono_type_size (field->type, &align);
2934 g_assert (size == mono_class_value_size (field_klass, NULL));
2935 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2937 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2940 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2941 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2951 g_assert_not_reached ();
2956 for (i = 0; i < mono_array_length (params); i++) {
2957 if (sig->params [i]->byref)
2961 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2963 /* handle constructors only for objects already allocated */
2964 if (!strcmp (method->method->name, ".ctor"))
2967 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2968 g_assert (!method->method->klass->valuetype);
2969 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2971 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2972 if (sig->params [i]->byref) {
2974 arg = mono_array_get (params, gpointer, i);
2975 mono_array_setref (out_args, j, arg);
2980 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2986 read_enum_value (char *mem, int type)
2990 return *(guint8*)mem;
2992 return *(gint8*)mem;
2994 return *(guint16*)mem;
2996 return *(gint16*)mem;
2998 return *(guint32*)mem;
3000 return *(gint32*)mem;
3002 return *(guint64*)mem;
3004 return *(gint64*)mem;
3006 g_assert_not_reached ();
3012 write_enum_value (char *mem, int type, guint64 value)
3016 case MONO_TYPE_I1: {
3017 guint8 *p = (guint8*)mem;
3022 case MONO_TYPE_I2: {
3023 guint16 *p = (void*)mem;
3028 case MONO_TYPE_I4: {
3029 guint32 *p = (void*)mem;
3034 case MONO_TYPE_I8: {
3035 guint64 *p = (void*)mem;
3040 g_assert_not_reached ();
3046 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3049 MonoClass *enumc, *objc;
3054 MONO_ARCH_SAVE_REGS;
3056 MONO_CHECK_ARG_NULL (enumType);
3057 MONO_CHECK_ARG_NULL (value);
3059 domain = mono_object_domain (enumType);
3060 enumc = mono_class_from_mono_type (enumType->type);
3062 mono_class_init_or_throw (enumc);
3064 objc = value->vtable->klass;
3066 if (!enumc->enumtype)
3067 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3068 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3069 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."));
3071 etype = mono_class_enum_basetype (enumc);
3073 /* MS throws this for typebuilders */
3074 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3076 res = mono_object_new (domain, enumc);
3077 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3078 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3084 ves_icall_System_Enum_get_value (MonoObject *this)
3092 MONO_ARCH_SAVE_REGS;
3097 g_assert (this->vtable->klass->enumtype);
3099 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3100 res = mono_object_new (mono_object_domain (this), enumc);
3101 dst = (char *)res + sizeof (MonoObject);
3102 src = (char *)this + sizeof (MonoObject);
3103 size = mono_class_value_size (enumc, NULL);
3105 memcpy (dst, src, size);
3110 static MonoReflectionType *
3111 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3116 MONO_ARCH_SAVE_REGS;
3118 klass = mono_class_from_mono_type (type->type);
3119 mono_class_init_or_throw (klass);
3121 etype = mono_class_enum_basetype (klass);
3123 /* MS throws this for typebuilders */
3124 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3126 return mono_type_get_object (mono_object_domain (type), etype);
3130 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3132 gpointer tdata = (char *)this + sizeof (MonoObject);
3133 gpointer odata = (char *)other + sizeof (MonoObject);
3134 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3135 g_assert (basetype);
3137 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3138 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3139 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3142 return me > other ? 1 : -1; \
3145 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3146 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3147 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3150 return me - other; \
3153 switch (basetype->type) {
3155 COMPARE_ENUM_VALUES (guint8);
3157 COMPARE_ENUM_VALUES (gint8);
3158 case MONO_TYPE_CHAR:
3160 COMPARE_ENUM_VALUES_RANGE (guint16);
3162 COMPARE_ENUM_VALUES (gint16);
3164 COMPARE_ENUM_VALUES (guint32);
3166 COMPARE_ENUM_VALUES (gint32);
3168 COMPARE_ENUM_VALUES (guint64);
3170 COMPARE_ENUM_VALUES (gint64);
3172 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3174 #undef COMPARE_ENUM_VALUES_RANGE
3175 #undef COMPARE_ENUM_VALUES
3180 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3182 gpointer data = (char *)this + sizeof (MonoObject);
3183 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3184 g_assert (basetype);
3186 switch (basetype->type) {
3188 return *((gint8*)data);
3190 return *((guint8*)data);
3191 case MONO_TYPE_CHAR:
3193 return *((guint16*)data);
3196 return *((gint16*)data);
3198 return *((guint32*)data);
3200 return *((gint32*)data);
3202 case MONO_TYPE_I8: {
3203 gint64 value = *((gint64*)data);
3204 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3207 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3213 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3215 MonoDomain *domain = mono_object_domain (type);
3216 MonoClass *enumc = mono_class_from_mono_type (type->type);
3217 guint j = 0, nvalues, crow;
3219 MonoClassField *field;
3221 MONO_ARCH_SAVE_REGS;
3223 mono_class_init_or_throw (enumc);
3225 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3226 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3227 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3228 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3232 while ((field = mono_class_get_fields (enumc, &iter))) {
3235 MonoTypeEnum def_type;
3237 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3239 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3241 if (mono_field_is_deleted (field))
3243 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3245 p = mono_class_get_field_default_value (field, &def_type);
3246 len = mono_metadata_decode_blob_size (p, &p);
3247 switch (mono_class_enum_basetype (enumc)->type) {
3250 mono_array_set (info->values, gchar, j, *p);
3252 case MONO_TYPE_CHAR:
3255 mono_array_set (info->values, gint16, j, read16 (p));
3259 mono_array_set (info->values, gint32, j, read32 (p));
3263 mono_array_set (info->values, gint64, j, read64 (p));
3266 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3273 BFLAGS_IgnoreCase = 1,
3274 BFLAGS_DeclaredOnly = 2,
3275 BFLAGS_Instance = 4,
3277 BFLAGS_Public = 0x10,
3278 BFLAGS_NonPublic = 0x20,
3279 BFLAGS_FlattenHierarchy = 0x40,
3280 BFLAGS_InvokeMethod = 0x100,
3281 BFLAGS_CreateInstance = 0x200,
3282 BFLAGS_GetField = 0x400,
3283 BFLAGS_SetField = 0x800,
3284 BFLAGS_GetProperty = 0x1000,
3285 BFLAGS_SetProperty = 0x2000,
3286 BFLAGS_ExactBinding = 0x10000,
3287 BFLAGS_SuppressChangeType = 0x20000,
3288 BFLAGS_OptionalParamBinding = 0x40000
3291 static MonoReflectionField *
3292 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3295 MonoClass *startklass, *klass;
3297 MonoClassField *field;
3300 int (*compare_func) (const char *s1, const char *s2) = NULL;
3301 domain = ((MonoObject *)type)->vtable->domain;
3302 klass = startklass = mono_class_from_mono_type (type->type);
3305 mono_raise_exception (mono_get_exception_argument_null ("name"));
3306 if (type->type->byref)
3309 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3312 if (klass->exception_type != MONO_EXCEPTION_NONE)
3313 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3316 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3317 guint32 flags = mono_field_get_flags (field);
3320 if (mono_field_is_deleted_with_flags (field, flags))
3322 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3323 if (bflags & BFLAGS_Public)
3325 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3326 if (bflags & BFLAGS_NonPublic) {
3333 if (flags & FIELD_ATTRIBUTE_STATIC) {
3334 if (bflags & BFLAGS_Static)
3335 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3338 if (bflags & BFLAGS_Instance)
3345 utf8_name = mono_string_to_utf8 (name);
3347 if (compare_func (mono_field_get_name (field), utf8_name)) {
3353 return mono_field_get_object (domain, klass, field);
3355 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3362 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3365 MonoClass *startklass, *klass, *refklass;
3370 MonoClassField *field;
3371 MonoPtrArray tmp_array;
3373 MONO_ARCH_SAVE_REGS;
3375 domain = ((MonoObject *)type)->vtable->domain;
3376 if (type->type->byref)
3377 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3378 klass = startklass = mono_class_from_mono_type (type->type);
3379 refklass = mono_class_from_mono_type (reftype->type);
3381 mono_ptr_array_init (tmp_array, 2);
3384 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3385 mono_ptr_array_destroy (tmp_array);
3386 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3390 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3391 guint32 flags = mono_field_get_flags (field);
3393 if (mono_field_is_deleted_with_flags (field, flags))
3395 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3396 if (bflags & BFLAGS_Public)
3398 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3399 if (bflags & BFLAGS_NonPublic) {
3406 if (flags & FIELD_ATTRIBUTE_STATIC) {
3407 if (bflags & BFLAGS_Static)
3408 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3411 if (bflags & BFLAGS_Instance)
3417 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3418 mono_ptr_array_append (tmp_array, member);
3420 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3423 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3425 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3426 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3428 mono_ptr_array_destroy (tmp_array);
3434 method_nonpublic (MonoMethod* method, gboolean start_klass)
3436 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3437 case METHOD_ATTRIBUTE_ASSEM:
3438 return (start_klass || mono_defaults.generic_ilist_class);
3439 case METHOD_ATTRIBUTE_PRIVATE:
3441 case METHOD_ATTRIBUTE_PUBLIC:
3449 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3451 static MonoClass *MethodInfo_array;
3453 MonoClass *startklass, *klass, *refklass;
3458 int i, len, match, nslots;
3459 /*FIXME, use MonoBitSet*/
3460 guint32 method_slots_default [8];
3461 guint32 *method_slots = NULL;
3462 gchar *mname = NULL;
3463 int (*compare_func) (const char *s1, const char *s2) = NULL;
3464 MonoVTable *array_vtable;
3466 MonoPtrArray tmp_array;
3468 mono_ptr_array_init (tmp_array, 4);
3470 if (!MethodInfo_array) {
3471 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3472 mono_memory_barrier ();
3473 MethodInfo_array = klass;
3476 domain = ((MonoObject *)type)->vtable->domain;
3477 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3478 if (type->type->byref)
3479 return mono_array_new_specific (array_vtable, 0);
3480 klass = startklass = mono_class_from_mono_type (type->type);
3481 refklass = mono_class_from_mono_type (reftype->type);
3485 mname = mono_string_to_utf8 (name);
3486 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3489 /* An optimization for calls made from Delegate:CreateDelegate () */
3490 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3491 method = mono_get_delegate_invoke (klass);
3492 if (mono_loader_get_last_error ())
3495 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3497 res = mono_array_new_specific (array_vtable, 1);
3498 mono_array_setref (res, 0, member);
3503 mono_class_setup_vtable (klass);
3504 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3507 if (is_generic_parameter (type->type))
3508 nslots = mono_class_get_vtable_size (klass->parent);
3510 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3511 if (nslots >= sizeof (method_slots_default) * 8) {
3512 method_slots = g_new0 (guint32, nslots / 32 + 1);
3514 method_slots = method_slots_default;
3515 memset (method_slots, 0, sizeof (method_slots_default));
3518 mono_class_setup_vtable (klass);
3519 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3523 while ((method = mono_class_get_methods (klass, &iter))) {
3525 if (method->slot != -1) {
3526 g_assert (method->slot < nslots);
3527 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3529 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3530 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3533 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3535 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3536 if (bflags & BFLAGS_Public)
3538 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3544 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3545 if (bflags & BFLAGS_Static)
3546 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3549 if (bflags & BFLAGS_Instance)
3557 if (compare_func (mname, method->name))
3563 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3565 mono_ptr_array_append (tmp_array, member);
3567 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3571 if (method_slots != method_slots_default)
3572 g_free (method_slots);
3574 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3576 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3577 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3579 mono_ptr_array_destroy (tmp_array);
3584 if (method_slots != method_slots_default)
3585 g_free (method_slots);
3586 mono_ptr_array_destroy (tmp_array);
3587 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3588 ex = mono_class_get_exception_for_failure (klass);
3590 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3591 mono_loader_clear_error ();
3593 mono_raise_exception (ex);
3598 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3601 static MonoClass *System_Reflection_ConstructorInfo;
3602 MonoClass *startklass, *klass, *refklass;
3607 gpointer iter = NULL;
3608 MonoPtrArray tmp_array;
3610 MONO_ARCH_SAVE_REGS;
3612 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3614 domain = ((MonoObject *)type)->vtable->domain;
3615 if (type->type->byref)
3616 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3617 klass = startklass = mono_class_from_mono_type (type->type);
3618 refklass = mono_class_from_mono_type (reftype->type);
3620 if (!System_Reflection_ConstructorInfo)
3621 System_Reflection_ConstructorInfo = mono_class_from_name (
3622 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3625 while ((method = mono_class_get_methods (klass, &iter))) {
3627 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3629 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3630 if (bflags & BFLAGS_Public)
3633 if (bflags & BFLAGS_NonPublic)
3639 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3640 if (bflags & BFLAGS_Static)
3641 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3644 if (bflags & BFLAGS_Instance)
3650 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3652 mono_ptr_array_append (tmp_array, member);
3655 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3657 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3658 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3660 mono_ptr_array_destroy (tmp_array);
3666 property_hash (gconstpointer data)
3668 MonoProperty *prop = (MonoProperty*)data;
3670 return g_str_hash (prop->name);
3674 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3676 // Properties are hide-by-name-and-signature
3677 if (!g_str_equal (prop1->name, prop2->name))
3680 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3682 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3688 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3693 return method_nonpublic (accessor, start_klass);
3697 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3701 static MonoClass *System_Reflection_PropertyInfo;
3702 MonoClass *startklass, *klass;
3708 gchar *propname = NULL;
3709 int (*compare_func) (const char *s1, const char *s2) = NULL;
3711 GHashTable *properties = NULL;
3712 MonoPtrArray tmp_array;
3714 MONO_ARCH_SAVE_REGS;
3716 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3718 if (!System_Reflection_PropertyInfo)
3719 System_Reflection_PropertyInfo = mono_class_from_name (
3720 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3722 domain = ((MonoObject *)type)->vtable->domain;
3723 if (type->type->byref)
3724 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3725 klass = startklass = mono_class_from_mono_type (type->type);
3728 propname = mono_string_to_utf8 (name);
3729 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3732 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3734 mono_class_setup_vtable (klass);
3735 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3739 while ((prop = mono_class_get_properties (klass, &iter))) {
3745 flags = method->flags;
3748 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3749 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3750 if (bflags & BFLAGS_Public)
3752 } else if (bflags & BFLAGS_NonPublic) {
3753 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3754 property_accessor_nonpublic(prop->set, startklass == klass)) {
3761 if (flags & METHOD_ATTRIBUTE_STATIC) {
3762 if (bflags & BFLAGS_Static)
3763 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3766 if (bflags & BFLAGS_Instance)
3775 if (compare_func (propname, prop->name))
3779 if (g_hash_table_lookup (properties, prop))
3782 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3784 g_hash_table_insert (properties, prop, prop);
3786 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3789 g_hash_table_destroy (properties);
3792 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3793 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3794 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3796 mono_ptr_array_destroy (tmp_array);
3802 g_hash_table_destroy (properties);
3805 mono_ptr_array_destroy (tmp_array);
3807 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3808 ex = mono_class_get_exception_for_failure (klass);
3810 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3811 mono_loader_clear_error ();
3813 mono_raise_exception (ex);
3817 static MonoReflectionEvent *
3818 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3821 MonoClass *klass, *startklass;
3826 int (*compare_func) (const char *s1, const char *s2);
3828 MONO_ARCH_SAVE_REGS;
3830 event_name = mono_string_to_utf8 (name);
3831 if (type->type->byref)
3833 klass = startklass = mono_class_from_mono_type (type->type);
3834 domain = mono_object_domain (type);
3836 mono_class_init_or_throw (klass);
3838 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3840 if (klass->exception_type != MONO_EXCEPTION_NONE)
3841 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3844 while ((event = mono_class_get_events (klass, &iter))) {
3845 if (compare_func (event->name, event_name))
3848 method = event->add;
3850 method = event->remove;
3852 method = event->raise;
3854 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3855 if (!(bflags & BFLAGS_Public))
3858 if (!(bflags & BFLAGS_NonPublic))
3860 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3864 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3865 if (!(bflags & BFLAGS_Static))
3867 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3870 if (!(bflags & BFLAGS_Instance))
3874 if (!(bflags & BFLAGS_NonPublic))
3877 g_free (event_name);
3878 return mono_event_get_object (domain, startklass, event);
3881 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3884 g_free (event_name);
3889 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3893 static MonoClass *System_Reflection_EventInfo;
3894 MonoClass *startklass, *klass;
3901 MonoPtrArray tmp_array;
3903 MONO_ARCH_SAVE_REGS;
3905 mono_ptr_array_init (tmp_array, 4);
3907 if (!System_Reflection_EventInfo)
3908 System_Reflection_EventInfo = mono_class_from_name (
3909 mono_defaults.corlib, "System.Reflection", "EventInfo");
3911 domain = mono_object_domain (type);
3912 if (type->type->byref)
3913 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3914 klass = startklass = mono_class_from_mono_type (type->type);
3917 mono_class_setup_vtable (klass);
3918 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3922 while ((event = mono_class_get_events (klass, &iter))) {
3924 method = event->add;
3926 method = event->remove;
3928 method = event->raise;
3930 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3931 if (bflags & BFLAGS_Public)
3933 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3934 if (bflags & BFLAGS_NonPublic)
3939 if (bflags & BFLAGS_NonPublic)
3945 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3946 if (bflags & BFLAGS_Static)
3947 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3950 if (bflags & BFLAGS_Instance)
3955 if (bflags & BFLAGS_Instance)
3959 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3961 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3964 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3966 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3967 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3969 mono_ptr_array_destroy (tmp_array);
3974 mono_ptr_array_destroy (tmp_array);
3975 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3976 ex = mono_class_get_exception_for_failure (klass);
3978 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3979 mono_loader_clear_error ();
3981 mono_raise_exception (ex);
3985 static MonoReflectionType *
3986 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3994 MONO_ARCH_SAVE_REGS;
3997 mono_raise_exception (mono_get_exception_argument_null ("name"));
3999 domain = ((MonoObject *)type)->vtable->domain;
4000 if (type->type->byref)
4002 klass = mono_class_from_mono_type (type->type);
4004 str = mono_string_to_utf8 (name);
4007 if (klass->exception_type != MONO_EXCEPTION_NONE)
4008 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4011 * If a nested type is generic, return its generic type definition.
4012 * Note that this means that the return value is essentially a
4013 * nested type of the generic type definition of @klass.
4015 * A note in MSDN claims that a generic type definition can have
4016 * nested types that aren't generic. In any case, the container of that
4017 * nested type would be the generic type definition.
4019 if (klass->generic_class)
4020 klass = klass->generic_class->container_class;
4023 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4025 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4026 if (bflags & BFLAGS_Public)
4029 if (bflags & BFLAGS_NonPublic)
4034 if (strcmp (nested->name, str) == 0){
4036 return mono_type_get_object (domain, &nested->byval_arg);
4039 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4046 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4055 MonoPtrArray tmp_array;
4057 MONO_ARCH_SAVE_REGS;
4059 domain = ((MonoObject *)type)->vtable->domain;
4060 if (type->type->byref)
4061 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4062 klass = mono_class_from_mono_type (type->type);
4065 * If a nested type is generic, return its generic type definition.
4066 * Note that this means that the return value is essentially the set
4067 * of nested types of the generic type definition of @klass.
4069 * A note in MSDN claims that a generic type definition can have
4070 * nested types that aren't generic. In any case, the container of that
4071 * nested type would be the generic type definition.
4073 if (klass->generic_class)
4074 klass = klass->generic_class->container_class;
4076 mono_ptr_array_init (tmp_array, 1);
4078 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4080 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4081 if (bflags & BFLAGS_Public)
4084 if (bflags & BFLAGS_NonPublic)
4089 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4090 mono_ptr_array_append (tmp_array, member);
4093 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4095 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4096 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4098 mono_ptr_array_destroy (tmp_array);
4103 static MonoReflectionType*
4104 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4107 MonoType *type = NULL;
4108 MonoTypeNameParse info;
4109 gboolean type_resolve;
4111 MONO_ARCH_SAVE_REGS;
4113 /* On MS.NET, this does not fire a TypeResolve event */
4114 type_resolve = TRUE;
4115 str = mono_string_to_utf8 (name);
4116 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4117 if (!mono_reflection_parse_type (str, &info)) {
4119 mono_reflection_free_type_info (&info);
4120 if (throwOnError) /* uhm: this is a parse error, though... */
4121 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4122 /*g_print ("failed parse\n");*/
4126 if (info.assembly.name) {
4128 mono_reflection_free_type_info (&info);
4130 /* 1.0 and 2.0 throw different exceptions */
4131 if (mono_defaults.generic_ilist_class)
4132 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4134 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4139 if (module != NULL) {
4141 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4146 if (assembly->assembly->dynamic) {
4147 /* Enumerate all modules */
4148 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4152 if (abuilder->modules) {
4153 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4154 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4155 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4161 if (!type && abuilder->loaded_modules) {
4162 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4163 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4164 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4171 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4173 mono_reflection_free_type_info (&info);
4175 MonoException *e = NULL;
4178 e = mono_get_exception_type_load (name, NULL);
4180 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4181 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4183 mono_loader_clear_error ();
4186 mono_raise_exception (e);
4189 } else if (mono_loader_get_last_error ()) {
4191 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4192 mono_loader_clear_error ();
4195 if (type->type == MONO_TYPE_CLASS) {
4196 MonoClass *klass = mono_type_get_class (type);
4198 if (mono_is_security_manager_active () && !klass->exception_type)
4199 /* Some security problems are detected during generic vtable construction */
4200 mono_class_setup_vtable (klass);
4201 /* need to report exceptions ? */
4202 if (throwOnError && klass->exception_type) {
4203 /* report SecurityException (or others) that occured when loading the assembly */
4204 MonoException *exc = mono_class_get_exception_for_failure (klass);
4205 mono_loader_clear_error ();
4206 mono_raise_exception (exc);
4207 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4212 /* g_print ("got it\n"); */
4213 return mono_type_get_object (mono_object_domain (assembly), type);
4217 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4220 gchar *shadow_ini_file;
4223 /* Check for shadow-copied assembly */
4224 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4225 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4227 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4228 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4234 g_free (shadow_ini_file);
4235 if (content != NULL) {
4238 *filename = content;
4246 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4248 MonoDomain *domain = mono_object_domain (assembly);
4249 MonoAssembly *mass = assembly->assembly;
4250 MonoString *res = NULL;
4255 MONO_ARCH_SAVE_REGS;
4257 if (g_path_is_absolute (mass->image->name)) {
4258 absolute = g_strdup (mass->image->name);
4259 dirname = g_path_get_dirname (absolute);
4261 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4262 dirname = g_strdup (mass->basedir);
4265 replace_shadow_path (domain, dirname, &absolute);
4270 for (i = strlen (absolute) - 1; i >= 0; i--)
4271 if (absolute [i] == '\\')
4276 uri = g_filename_to_uri (absolute, NULL, NULL);
4278 const char *prepend = "file://";
4280 if (*absolute == '/' && *(absolute + 1) == '/') {
4283 prepend = "file:///";
4286 uri = g_strconcat (prepend, absolute, NULL);
4290 res = mono_string_new (domain, uri);
4298 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4300 MonoAssembly *mass = assembly->assembly;
4302 MONO_ARCH_SAVE_REGS;
4304 return mass->in_gac;
4307 static MonoReflectionAssembly*
4308 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4312 MonoImageOpenStatus status;
4314 MONO_ARCH_SAVE_REGS;
4316 name = mono_string_to_utf8 (mname);
4317 res = mono_assembly_load_with_partial_name (name, &status);
4323 return mono_assembly_get_object (mono_domain_get (), res);
4327 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4329 MonoDomain *domain = mono_object_domain (assembly);
4332 MONO_ARCH_SAVE_REGS;
4334 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4340 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4342 MONO_ARCH_SAVE_REGS;
4344 return assembly->assembly->ref_only;
4348 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4350 MonoDomain *domain = mono_object_domain (assembly);
4352 MONO_ARCH_SAVE_REGS;
4354 return mono_string_new (domain, assembly->assembly->image->version);
4357 static MonoReflectionMethod*
4358 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4360 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4362 MONO_ARCH_SAVE_REGS;
4366 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4369 static MonoReflectionModule*
4370 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4372 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4376 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4378 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4379 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4383 MONO_ARCH_SAVE_REGS;
4385 for (i = 0; i < table->rows; ++i) {
4386 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4387 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4393 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4395 static MonoClass *System_Version = NULL;
4396 static MonoMethod *create_version = NULL;
4400 if (!System_Version) {
4401 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4402 g_assert (System_Version);
4405 if (!create_version) {
4406 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4407 create_version = mono_method_desc_search_in_class (desc, System_Version);
4408 g_assert (create_version);
4409 mono_method_desc_free (desc);
4415 args [3] = &revision;
4416 result = mono_object_new (domain, System_Version);
4417 mono_runtime_invoke (create_version, result, args, NULL);
4423 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4425 static MonoClass *System_Reflection_AssemblyName;
4427 MonoDomain *domain = mono_object_domain (assembly);
4429 static MonoMethod *create_culture = NULL;
4430 MonoImage *image = assembly->assembly->image;
4433 MONO_ARCH_SAVE_REGS;
4435 if (!System_Reflection_AssemblyName)
4436 System_Reflection_AssemblyName = mono_class_from_name (
4437 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4439 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4442 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4444 if (count > 0 && !create_culture) {
4445 MonoMethodDesc *desc = mono_method_desc_new (
4446 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4447 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4448 g_assert (create_culture);
4449 mono_method_desc_free (desc);
4452 for (i = 0; i < count; i++) {
4453 MonoReflectionAssemblyName *aname;
4454 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4456 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4458 aname = (MonoReflectionAssemblyName *) mono_object_new (
4459 domain, System_Reflection_AssemblyName);
4461 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4463 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4464 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4465 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4466 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4467 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4468 aname->versioncompat = 1; /* SameMachine (default) */
4469 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4470 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4472 if (create_culture) {
4474 MonoBoolean assembly_ref = 1;
4475 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4476 args [1] = &assembly_ref;
4477 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4480 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4481 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4482 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4484 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4485 /* public key token isn't copied - the class library will
4486 automatically generate it from the public key if required */
4487 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4488 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4490 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4491 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4494 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4497 /* note: this function doesn't return the codebase on purpose (i.e. it can
4498 be used under partial trust as path information isn't present). */
4500 mono_array_setref (result, i, aname);
4511 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4513 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4515 mono_array_setref (info->res, info->idx, name);
4520 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4522 MonoImage *img = assembly->assembly->image;
4527 MONO_ARCH_SAVE_REGS;
4529 mono_image_lock (img);
4530 mono_image_init_name_cache (img);
4533 len = g_hash_table_size (img->name_cache);
4534 mono_image_unlock (img);
4536 /*we can't create objects holding the image lock */
4537 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4539 mono_image_lock (img);
4540 /*len might have changed, create a new array*/
4541 if (len != g_hash_table_size (img->name_cache))
4546 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4547 mono_image_unlock (img);
4552 /* move this in some file in mono/util/ */
4554 g_concat_dir_and_file (const char *dir, const char *file)
4556 g_return_val_if_fail (dir != NULL, NULL);
4557 g_return_val_if_fail (file != NULL, NULL);
4560 * If the directory name doesn't have a / on the end, we need
4561 * to add one so we get a proper path to the file
4563 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4564 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4566 return g_strconcat (dir, file, NULL);
4570 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4572 char *n = mono_string_to_utf8 (name);
4573 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4575 guint32 cols [MONO_MANIFEST_SIZE];
4576 guint32 impl, file_idx;
4580 MONO_ARCH_SAVE_REGS;
4582 for (i = 0; i < table->rows; ++i) {
4583 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4584 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4585 if (strcmp (val, n) == 0)
4589 if (i == table->rows)
4592 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4595 * this code should only be called after obtaining the
4596 * ResourceInfo and handling the other cases.
4598 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4599 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4601 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4606 module = assembly->assembly->image;
4608 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4610 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4614 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4616 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4618 guint32 cols [MONO_MANIFEST_SIZE];
4619 guint32 file_cols [MONO_FILE_SIZE];
4623 MONO_ARCH_SAVE_REGS;
4625 n = mono_string_to_utf8 (name);
4626 for (i = 0; i < table->rows; ++i) {
4627 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4628 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4629 if (strcmp (val, n) == 0)
4633 if (i == table->rows)
4636 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4637 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4640 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4641 case MONO_IMPLEMENTATION_FILE:
4642 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4643 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4644 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4645 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4646 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4647 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4650 info->location = RESOURCE_LOCATION_EMBEDDED;
4653 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4654 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4655 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4656 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4657 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4658 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4660 mono_raise_exception (ex);
4662 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4664 /* Obtain info recursively */
4665 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4666 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4669 case MONO_IMPLEMENTATION_EXP_TYPE:
4670 g_assert_not_reached ();
4679 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4681 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4682 MonoArray *result = NULL;
4687 MONO_ARCH_SAVE_REGS;
4689 /* check hash if needed */
4691 n = mono_string_to_utf8 (name);
4692 for (i = 0; i < table->rows; ++i) {
4693 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4694 if (strcmp (val, n) == 0) {
4697 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4698 fn = mono_string_new (mono_object_domain (assembly), n);
4700 return (MonoObject*)fn;
4708 for (i = 0; i < table->rows; ++i) {
4709 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4713 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4716 for (i = 0; i < table->rows; ++i) {
4717 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4718 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4719 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4720 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4725 return (MonoObject*)result;
4729 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4731 MonoDomain *domain = mono_domain_get();
4734 int i, j, file_count = 0;
4735 MonoImage **modules;
4736 guint32 module_count, real_module_count;
4737 MonoTableInfo *table;
4738 guint32 cols [MONO_FILE_SIZE];
4739 MonoImage *image = assembly->assembly->image;
4741 g_assert (image != NULL);
4742 g_assert (!assembly->assembly->dynamic);
4744 table = &image->tables [MONO_TABLE_FILE];
4745 file_count = table->rows;
4747 modules = image->modules;
4748 module_count = image->module_count;
4750 real_module_count = 0;
4751 for (i = 0; i < module_count; ++i)
4753 real_module_count ++;
4755 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4756 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4758 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4760 for (i = 0; i < module_count; ++i)
4762 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4766 for (i = 0; i < file_count; ++i, ++j) {
4767 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4768 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4769 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4771 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4773 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4774 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4776 mono_array_setref (res, j, mono_module_get_object (domain, m));
4783 static MonoReflectionMethod*
4784 ves_icall_GetCurrentMethod (void)
4786 MonoMethod *m = mono_method_get_last_managed ();
4788 while (m->is_inflated)
4789 m = ((MonoMethodInflated*)m)->declaring;
4791 return mono_method_get_object (mono_domain_get (), m, NULL);
4796 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4799 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4800 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4801 //method is inflated, we should inflate it on the other class
4802 MonoGenericContext ctx;
4803 ctx.method_inst = inflated->context.method_inst;
4804 ctx.class_inst = inflated->context.class_inst;
4805 if (klass->generic_class)
4806 ctx.class_inst = klass->generic_class->context.class_inst;
4807 else if (klass->generic_container)
4808 ctx.class_inst = klass->generic_container->context.class_inst;
4809 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4812 mono_class_setup_methods (method->klass);
4813 if (method->klass->exception_type)
4815 for (i = 0; i < method->klass->method.count; ++i) {
4816 if (method->klass->methods [i] == method) {
4821 mono_class_setup_methods (klass);
4822 if (klass->exception_type)
4824 g_assert (offset >= 0 && offset < klass->method.count);
4825 return klass->methods [offset];
4828 static MonoReflectionMethod*
4829 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4833 klass = mono_class_from_mono_type (type);
4834 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4836 if (method->klass != klass) {
4837 method = mono_method_get_equivalent_method (method, klass);
4842 klass = method->klass;
4843 return mono_method_get_object (mono_domain_get (), method, klass);
4846 static MonoReflectionMethod*
4847 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4849 return mono_method_get_object (mono_domain_get (), method, NULL);
4852 static MonoReflectionMethodBody*
4853 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4855 return mono_method_body_get_object (mono_domain_get (), method);
4858 static MonoReflectionAssembly*
4859 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4861 MonoMethod *dest = NULL;
4863 MONO_ARCH_SAVE_REGS;
4865 mono_stack_walk_no_il (get_executing, &dest);
4866 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4870 static MonoReflectionAssembly*
4871 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4873 MonoDomain* domain = mono_domain_get ();
4875 MONO_ARCH_SAVE_REGS;
4877 if (!domain->entry_assembly)
4880 return mono_assembly_get_object (domain, domain->entry_assembly);
4883 static MonoReflectionAssembly*
4884 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4889 MONO_ARCH_SAVE_REGS;
4892 mono_stack_walk_no_il (get_executing, &dest);
4894 mono_stack_walk_no_il (get_caller, &dest);
4897 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4901 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4902 gboolean assembly_qualified)
4904 MonoDomain *domain = mono_object_domain (object);
4905 MonoTypeNameFormat format;
4910 format = assembly_qualified ?
4911 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4912 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4914 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4916 name = mono_type_get_name_full (object->type, format);
4920 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4925 res = mono_string_new (domain, name);
4932 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4934 MonoClass *klass = mono_class_from_mono_type (this->type);
4935 mono_class_init_or_throw (klass);
4936 return mono_security_core_clr_class_level (klass);
4940 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4942 static MonoMethod *create_culture = NULL;
4945 const char *pkey_ptr;
4947 MonoBoolean assembly_ref = 0;
4949 MONO_ARCH_SAVE_REGS;
4951 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4952 aname->major = name->major;
4953 aname->minor = name->minor;
4954 aname->build = name->build;
4955 aname->flags = name->flags;
4956 aname->revision = name->revision;
4957 aname->hashalg = name->hash_alg;
4958 aname->versioncompat = 1; /* SameMachine (default) */
4959 aname->processor_architecture = name->arch;
4961 if (by_default_version)
4962 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4965 if (absolute != NULL && *absolute != '\0') {
4966 const gchar *prepend = "file://";
4969 codebase = g_strdup (absolute);
4974 for (i = strlen (codebase) - 1; i >= 0; i--)
4975 if (codebase [i] == '\\')
4978 if (*codebase == '/' && *(codebase + 1) == '/') {
4981 prepend = "file:///";
4985 result = g_strconcat (prepend, codebase, NULL);
4991 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4995 if (!create_culture) {
4996 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4997 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4998 g_assert (create_culture);
4999 mono_method_desc_free (desc);
5002 if (name->culture) {
5003 args [0] = mono_string_new (domain, name->culture);
5004 args [1] = &assembly_ref;
5005 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5008 if (name->public_key) {
5009 pkey_ptr = (char*)name->public_key;
5010 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5012 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5013 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5014 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5015 } else if (default_publickey) {
5016 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5017 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5020 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5021 if (name->public_key_token [0]) {
5025 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5026 p = mono_array_addr (aname->keyToken, char, 0);
5028 for (i = 0, j = 0; i < 8; i++) {
5029 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5030 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5033 } else if (default_token) {
5034 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5039 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5041 MonoDomain *domain = mono_object_domain (assembly);
5042 MonoAssembly *mass = assembly->assembly;
5046 name = mono_stringify_assembly_name (&mass->aname);
5047 res = mono_string_new (domain, name);
5054 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5057 MonoAssembly *mass = assembly->assembly;
5059 MONO_ARCH_SAVE_REGS;
5061 if (g_path_is_absolute (mass->image->name)) {
5062 fill_reflection_assembly_name (mono_object_domain (assembly),
5063 aname, &mass->aname, mass->image->name, TRUE,
5067 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5069 fill_reflection_assembly_name (mono_object_domain (assembly),
5070 aname, &mass->aname, absolute, TRUE, TRUE,
5077 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5080 MonoImageOpenStatus status = MONO_IMAGE_OK;
5083 MonoAssemblyName name;
5086 MONO_ARCH_SAVE_REGS;
5088 filename = mono_string_to_utf8 (fname);
5090 dirname = g_path_get_dirname (filename);
5091 replace_shadow_path (mono_domain_get (), dirname, &filename);
5094 image = mono_image_open (filename, &status);
5100 if (status == MONO_IMAGE_IMAGE_INVALID)
5101 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5103 exc = mono_get_exception_file_not_found2 (NULL, fname);
5104 mono_raise_exception (exc);
5107 res = mono_assembly_fill_assembly_name (image, &name);
5109 mono_image_close (image);
5111 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5114 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5118 mono_image_close (image);
5122 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5123 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5125 MonoBoolean result = FALSE;
5126 MonoDeclSecurityEntry entry;
5128 /* SecurityAction.RequestMinimum */
5129 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5130 *minimum = entry.blob;
5131 *minLength = entry.size;
5134 /* SecurityAction.RequestOptional */
5135 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5136 *optional = entry.blob;
5137 *optLength = entry.size;
5140 /* SecurityAction.RequestRefuse */
5141 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5142 *refused = entry.blob;
5143 *refLength = entry.size;
5151 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5155 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5157 guint32 attrs, visibility;
5159 /* we start the count from 1 because we skip the special type <Module> */
5162 for (i = 1; i < tdef->rows; ++i) {
5163 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5164 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5165 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5169 count = tdef->rows - 1;
5171 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5172 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5174 for (i = 1; i < tdef->rows; ++i) {
5175 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5176 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5177 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5178 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5180 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5182 MonoLoaderError *error;
5185 error = mono_loader_get_last_error ();
5186 g_assert (error != NULL);
5188 ex = mono_loader_error_prepare_exception (error);
5189 mono_array_setref (*exceptions, count, ex);
5191 if (mono_loader_get_last_error ())
5192 mono_loader_clear_error ();
5201 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5203 MonoArray *res = NULL;
5204 MonoArray *exceptions = NULL;
5205 MonoImage *image = NULL;
5206 MonoTableInfo *table = NULL;
5209 int i, len, ex_count;
5211 MONO_ARCH_SAVE_REGS;
5213 domain = mono_object_domain (assembly);
5215 g_assert (!assembly->assembly->dynamic);
5216 image = assembly->assembly->image;
5217 table = &image->tables [MONO_TABLE_FILE];
5218 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5220 /* Append data from all modules in the assembly */
5221 for (i = 0; i < table->rows; ++i) {
5222 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5223 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5226 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5227 /* Append the new types to the end of the array */
5228 if (mono_array_length (res2) > 0) {
5230 MonoArray *res3, *ex3;
5232 len1 = mono_array_length (res);
5233 len2 = mono_array_length (res2);
5235 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5236 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5237 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5240 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5241 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5242 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5249 /* the ReflectionTypeLoadException must have all the types (Types property),
5250 * NULL replacing types which throws an exception. The LoaderException must
5251 * contain all exceptions for NULL items.
5254 len = mono_array_length (res);
5257 for (i = 0; i < len; i++) {
5258 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5262 klass = mono_type_get_class (t->type);
5263 if ((klass != NULL) && klass->exception_type) {
5264 /* keep the class in the list */
5265 list = g_list_append (list, klass);
5266 /* and replace Type with NULL */
5267 mono_array_setref (res, i, NULL);
5274 if (list || ex_count) {
5276 MonoException *exc = NULL;
5277 MonoArray *exl = NULL;
5278 int j, length = g_list_length (list) + ex_count;
5280 mono_loader_clear_error ();
5282 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5283 /* Types for which mono_class_get () succeeded */
5284 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5285 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5286 mono_array_setref (exl, i, exc);
5288 /* Types for which it don't */
5289 for (j = 0; j < mono_array_length (exceptions); ++j) {
5290 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5292 g_assert (i < length);
5293 mono_array_setref (exl, i, exc);
5300 exc = mono_get_exception_reflection_type_load (res, exl);
5301 mono_loader_clear_error ();
5302 mono_raise_exception (exc);
5309 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5311 MonoAssemblyName aname;
5312 MonoDomain *domain = mono_object_domain (name);
5314 gboolean is_version_defined;
5315 gboolean is_token_defined;
5317 aname.public_key = NULL;
5318 val = mono_string_to_utf8 (assname);
5319 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5320 g_free ((guint8*) aname.public_key);
5325 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5326 FALSE, is_token_defined);
5328 mono_assembly_name_free (&aname);
5329 g_free ((guint8*) aname.public_key);
5335 static MonoReflectionType*
5336 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5338 MonoDomain *domain = mono_object_domain (module);
5341 MONO_ARCH_SAVE_REGS;
5343 g_assert (module->image);
5345 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5346 /* These images do not have a global type */
5349 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5350 return mono_type_get_object (domain, &klass->byval_arg);
5354 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5356 /*if (module->image)
5357 mono_image_close (module->image);*/
5361 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5363 MonoDomain *domain = mono_object_domain (module);
5365 MONO_ARCH_SAVE_REGS;
5367 g_assert (module->image);
5368 return mono_string_new (domain, module->image->guid);
5372 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5375 if (module->image && module->image->is_module_handle)
5376 return module->image->raw_data;
5379 return (gpointer) (-1);
5383 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5385 if (image->dynamic) {
5386 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5387 *pe_kind = dyn->pe_kind;
5388 *machine = dyn->machine;
5391 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5392 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5397 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5399 return (image->md_version_major << 16) | (image->md_version_minor);
5403 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5405 MonoArray *exceptions;
5408 MONO_ARCH_SAVE_REGS;
5411 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5413 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5414 for (i = 0; i < mono_array_length (exceptions); ++i) {
5415 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5417 mono_raise_exception (ex);
5424 mono_memberref_is_method (MonoImage *image, guint32 token)
5426 if (!image->dynamic) {
5427 guint32 cols [MONO_MEMBERREF_SIZE];
5429 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5430 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5431 mono_metadata_decode_blob_size (sig, &sig);
5432 return (*sig != 0x6);
5434 MonoClass *handle_class;
5436 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5439 return mono_defaults.methodhandle_class == handle_class;
5444 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5447 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5448 mono_array_addr (type_args, MonoType*, 0));
5450 context->class_inst = NULL;
5452 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5453 mono_array_addr (method_args, MonoType*, 0));
5455 context->method_inst = NULL;
5459 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5462 int table = mono_metadata_token_table (token);
5463 int index = mono_metadata_token_index (token);
5464 MonoGenericContext context;
5466 *error = ResolveTokenError_Other;
5468 /* Validate token */
5469 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5470 (table != MONO_TABLE_TYPESPEC)) {
5471 *error = ResolveTokenError_BadTable;
5475 if (image->dynamic) {
5476 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5477 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5478 return klass ? &klass->byval_arg : NULL;
5481 init_generic_context_from_args (&context, type_args, method_args);
5482 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5483 return klass ? &klass->byval_arg : NULL;
5486 if ((index <= 0) || (index > image->tables [table].rows)) {
5487 *error = ResolveTokenError_OutOfRange;
5491 init_generic_context_from_args (&context, type_args, method_args);
5492 klass = mono_class_get_full (image, token, &context);
5494 if (mono_loader_get_last_error ())
5495 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5498 return &klass->byval_arg;
5504 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5506 int table = mono_metadata_token_table (token);
5507 int index = mono_metadata_token_index (token);
5508 MonoGenericContext context;
5511 *error = ResolveTokenError_Other;
5513 /* Validate token */
5514 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5515 (table != MONO_TABLE_MEMBERREF)) {
5516 *error = ResolveTokenError_BadTable;
5520 if (image->dynamic) {
5521 if (table == MONO_TABLE_METHOD)
5522 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5524 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5525 *error = ResolveTokenError_BadTable;
5529 init_generic_context_from_args (&context, type_args, method_args);
5530 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5533 if ((index <= 0) || (index > image->tables [table].rows)) {
5534 *error = ResolveTokenError_OutOfRange;
5537 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5538 *error = ResolveTokenError_BadTable;
5542 init_generic_context_from_args (&context, type_args, method_args);
5543 method = mono_get_method_full (image, token, NULL, &context);
5545 if (mono_loader_get_last_error ())
5546 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5552 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5554 int index = mono_metadata_token_index (token);
5556 *error = ResolveTokenError_Other;
5558 /* Validate token */
5559 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5560 *error = ResolveTokenError_BadTable;
5565 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5567 if ((index <= 0) || (index >= image->heap_us.size)) {
5568 *error = ResolveTokenError_OutOfRange;
5572 /* FIXME: What to do if the index points into the middle of a string ? */
5574 return mono_ldstr (mono_domain_get (), image, index);
5577 static MonoClassField*
5578 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5581 int table = mono_metadata_token_table (token);
5582 int index = mono_metadata_token_index (token);
5583 MonoGenericContext context;
5584 MonoClassField *field;
5586 *error = ResolveTokenError_Other;
5588 /* Validate token */
5589 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5590 *error = ResolveTokenError_BadTable;
5594 if (image->dynamic) {
5595 if (table == MONO_TABLE_FIELD)
5596 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5598 if (mono_memberref_is_method (image, token)) {
5599 *error = ResolveTokenError_BadTable;
5603 init_generic_context_from_args (&context, type_args, method_args);
5604 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5607 if ((index <= 0) || (index > image->tables [table].rows)) {
5608 *error = ResolveTokenError_OutOfRange;
5611 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5612 *error = ResolveTokenError_BadTable;
5616 init_generic_context_from_args (&context, type_args, method_args);
5617 field = mono_field_from_token (image, token, &klass, &context);
5619 if (mono_loader_get_last_error ())
5620 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5627 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5629 int table = mono_metadata_token_table (token);
5631 *error = ResolveTokenError_Other;
5634 case MONO_TABLE_TYPEDEF:
5635 case MONO_TABLE_TYPEREF:
5636 case MONO_TABLE_TYPESPEC: {
5637 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5639 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5643 case MONO_TABLE_METHOD:
5644 case MONO_TABLE_METHODSPEC: {
5645 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5647 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5651 case MONO_TABLE_FIELD: {
5652 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5654 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5658 case MONO_TABLE_MEMBERREF:
5659 if (mono_memberref_is_method (image, token)) {
5660 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5662 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5667 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5669 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5676 *error = ResolveTokenError_BadTable;
5683 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5685 int table = mono_metadata_token_table (token);
5686 int idx = mono_metadata_token_index (token);
5687 MonoTableInfo *tables = image->tables;
5692 *error = ResolveTokenError_OutOfRange;
5694 /* FIXME: Support other tables ? */
5695 if (table != MONO_TABLE_STANDALONESIG)
5701 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5704 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5706 ptr = mono_metadata_blob_heap (image, sig);
5707 len = mono_metadata_decode_blob_size (ptr, &ptr);
5709 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5710 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5714 static MonoReflectionType*
5715 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5718 int isbyref = 0, rank;
5719 char *str = mono_string_to_utf8 (smodifiers);
5722 MONO_ARCH_SAVE_REGS;
5724 klass = mono_class_from_mono_type (tb->type.type);
5726 /* logic taken from mono_reflection_parse_type(): keep in sync */
5730 if (isbyref) { /* only one level allowed by the spec */
5737 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5740 klass = mono_ptr_class_get (&klass->byval_arg);
5741 mono_class_init (klass);
5752 else if (*p != '*') { /* '*' means unknown lower bound */
5763 klass = mono_array_class_get (klass, rank);
5764 mono_class_init (klass);
5771 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5775 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5780 MONO_ARCH_SAVE_REGS;
5783 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5789 check_for_invalid_type (MonoClass *klass)
5793 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5796 name = mono_type_get_full_name (klass);
5797 str = mono_string_new (mono_domain_get (), name);
5799 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5802 static MonoReflectionType *
5803 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5805 MonoClass *klass, *aklass;
5807 MONO_ARCH_SAVE_REGS;
5809 klass = mono_class_from_mono_type (type->type);
5810 check_for_invalid_type (klass);
5812 if (rank == 0) //single dimentional array
5813 aklass = mono_array_class_get (klass, 1);
5815 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5817 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5820 static MonoReflectionType *
5821 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5825 MONO_ARCH_SAVE_REGS;
5827 klass = mono_class_from_mono_type (type->type);
5828 mono_class_init_or_throw (klass);
5829 check_for_invalid_type (klass);
5831 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5834 static MonoReflectionType *
5835 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5837 MonoClass *klass, *pklass;
5839 klass = mono_class_from_mono_type (type->type);
5840 mono_class_init_or_throw (klass);
5841 check_for_invalid_type (klass);
5843 pklass = mono_ptr_class_get (type->type);
5845 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5849 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5850 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5852 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5853 MonoObject *delegate;
5855 MonoMethod *method = info->method;
5857 MONO_ARCH_SAVE_REGS;
5859 mono_class_init_or_throw (delegate_class);
5861 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5863 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5864 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5868 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5870 if (method->dynamic) {
5871 /* Creating a trampoline would leak memory */
5872 func = mono_compile_method (method);
5874 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5875 method = mono_object_get_virtual_method (target, method);
5876 func = mono_create_ftnptr (mono_domain_get (),
5877 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5880 mono_delegate_ctor_with_method (delegate, target, func, method);
5886 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5888 /* Reset the invoke impl to the default one */
5889 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5893 * Magic number to convert a time which is relative to
5894 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5896 #define EPOCH_ADJUST ((guint64)62135596800LL)
5899 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5901 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5904 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5906 convert_to_absolute_date(SYSTEMTIME *date)
5908 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5909 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5910 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5911 /* from the calendar FAQ */
5912 int a = (14 - date->wMonth) / 12;
5913 int y = date->wYear - a;
5914 int m = date->wMonth + 12 * a - 2;
5915 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5917 /* d is now the day of the week for the first of the month (0 == Sunday) */
5919 int day_of_week = date->wDayOfWeek;
5921 /* set day_in_month to the first day in the month which falls on day_of_week */
5922 int day_in_month = 1 + (day_of_week - d);
5923 if (day_in_month <= 0)
5926 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5927 date->wDay = day_in_month + (date->wDay - 1) * 7;
5928 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5935 * Return's the offset from GMT of a local time.
5937 * tm is a local time
5938 * t is the same local time as seconds.
5941 gmt_offset(struct tm *tm, time_t t)
5943 #if defined (HAVE_TM_GMTOFF)
5944 return tm->tm_gmtoff;
5949 g.tm_isdst = tm->tm_isdst;
5951 return (int)difftime(t, t2);
5956 * This is heavily based on zdump.c from glibc 2.2.
5958 * * data[0]: start of daylight saving time (in DateTime ticks).
5959 * * data[1]: end of daylight saving time (in DateTime ticks).
5960 * * data[2]: utcoffset (in TimeSpan ticks).
5961 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5962 * * name[0]: name of this timezone when not daylight saving.
5963 * * name[1]: name of this timezone when daylight saving.
5965 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5966 * the class library allows years between 1 and 9999.
5968 * Returns true on success and zero on failure.
5971 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5974 MonoDomain *domain = mono_domain_get ();
5975 struct tm start, tt;
5979 int is_daylight = 0, day;
5982 MONO_ARCH_SAVE_REGS;
5984 MONO_CHECK_ARG_NULL (data);
5985 MONO_CHECK_ARG_NULL (names);
5987 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5988 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5991 * no info is better than crashing: we'll need our own tz data
5992 * to make this work properly, anyway. The range is probably
5993 * reduced to 1970 .. 2037 because that is what mktime is
5994 * guaranteed to support (we get into an infinite loop
5998 memset (&start, 0, sizeof (start));
6001 start.tm_year = year-1900;
6003 t = mktime (&start);
6005 if ((year < 1970) || (year > 2037) || (t == -1)) {
6007 tt = *localtime (&t);
6008 strftime (tzone, sizeof (tzone), "%Z", &tt);
6009 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6010 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6014 gmtoff = gmt_offset (&start, t);
6016 /* For each day of the year, calculate the tm_gmtoff. */
6017 for (day = 0; day < 365; day++) {
6020 tt = *localtime (&t);
6022 /* Daylight saving starts or ends here. */
6023 if (gmt_offset (&tt, t) != gmtoff) {
6027 /* Try to find the exact hour when daylight saving starts/ends. */
6031 tt1 = *localtime (&t1);
6032 } while (gmt_offset (&tt1, t1) != gmtoff);
6034 /* Try to find the exact minute when daylight saving starts/ends. */
6037 tt1 = *localtime (&t1);
6038 } while (gmt_offset (&tt1, t1) == gmtoff);
6040 strftime (tzone, sizeof (tzone), "%Z", &tt);
6042 /* Write data, if we're already in daylight saving, we're done. */
6044 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6045 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6048 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6049 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6053 /* This is only set once when we enter daylight saving. */
6054 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6055 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6057 gmtoff = gmt_offset (&tt, t);
6062 strftime (tzone, sizeof (tzone), "%Z", &tt);
6063 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6064 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6065 mono_array_set ((*data), gint64, 0, 0);
6066 mono_array_set ((*data), gint64, 1, 0);
6067 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6068 mono_array_set ((*data), gint64, 3, 0);
6073 MonoDomain *domain = mono_domain_get ();
6074 TIME_ZONE_INFORMATION tz_info;
6079 tz_id = GetTimeZoneInformation (&tz_info);
6080 if (tz_id == TIME_ZONE_ID_INVALID)
6083 MONO_CHECK_ARG_NULL (data);
6084 MONO_CHECK_ARG_NULL (names);
6086 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6087 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6089 for (i = 0; i < 32; ++i)
6090 if (!tz_info.DaylightName [i])
6092 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6093 for (i = 0; i < 32; ++i)
6094 if (!tz_info.StandardName [i])
6096 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6098 if ((year <= 1601) || (year > 30827)) {
6100 * According to MSDN, the MS time functions can't handle dates outside
6106 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6107 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6108 tz_info.StandardDate.wYear = year;
6109 convert_to_absolute_date(&tz_info.StandardDate);
6110 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6115 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6116 tz_info.DaylightDate.wYear = year;
6117 convert_to_absolute_date(&tz_info.DaylightDate);
6118 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6123 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6125 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6126 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6133 ves_icall_System_Object_obj_address (MonoObject *this)
6135 MONO_ARCH_SAVE_REGS;
6142 static inline gint32
6143 mono_array_get_byte_length (MonoArray *array)
6149 klass = array->obj.vtable->klass;
6151 if (array->bounds == NULL)
6152 length = array->max_length;
6155 for (i = 0; i < klass->rank; ++ i)
6156 length *= array->bounds [i].length;
6159 switch (klass->element_class->byval_arg.type) {
6162 case MONO_TYPE_BOOLEAN:
6166 case MONO_TYPE_CHAR:
6174 return length * sizeof (gpointer);
6185 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6187 MONO_ARCH_SAVE_REGS;
6189 return mono_array_get_byte_length (array);
6193 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6195 MONO_ARCH_SAVE_REGS;
6197 return mono_array_get (array, gint8, idx);
6201 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6203 MONO_ARCH_SAVE_REGS;
6205 mono_array_set (array, gint8, idx, value);
6209 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6211 guint8 *src_buf, *dest_buf;
6213 MONO_ARCH_SAVE_REGS;
6215 /* watch out for integer overflow */
6216 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6219 src_buf = (guint8 *)src->vector + src_offset;
6220 dest_buf = (guint8 *)dest->vector + dest_offset;
6223 memcpy (dest_buf, src_buf, count);
6225 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6231 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6233 MonoDomain *domain = mono_object_domain (this);
6235 MonoRealProxy *rp = ((MonoRealProxy *)this);
6236 MonoTransparentProxy *tp;
6240 MONO_ARCH_SAVE_REGS;
6242 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6243 tp = (MonoTransparentProxy*) res;
6245 MONO_OBJECT_SETREF (tp, rp, rp);
6246 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6247 klass = mono_class_from_mono_type (type);
6249 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6250 tp->remote_class = mono_remote_class (domain, class_name, klass);
6252 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6256 static MonoReflectionType *
6257 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6259 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6262 /* System.Environment */
6265 ves_icall_System_Environment_get_UserName (void)
6267 MONO_ARCH_SAVE_REGS;
6269 /* using glib is more portable */
6270 return mono_string_new (mono_domain_get (), g_get_user_name ());
6275 ves_icall_System_Environment_get_MachineName (void)
6277 #if defined (HOST_WIN32)
6282 len = MAX_COMPUTERNAME_LENGTH + 1;
6283 buf = g_new (gunichar2, len);
6286 if (GetComputerName (buf, (PDWORD) &len))
6287 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6291 #elif !defined(DISABLE_SOCKETS)
6295 if (gethostname (buf, sizeof (buf)) == 0)
6296 result = mono_string_new (mono_domain_get (), buf);
6302 return mono_string_new (mono_domain_get (), "mono");
6307 ves_icall_System_Environment_get_Platform (void)
6309 #if defined (TARGET_WIN32)
6312 #elif defined(__MACH__)
6315 // Notice that the value is hidden from user code, and only exposed
6316 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6317 // define and making assumptions based on Unix/128/4 values before there
6318 // was a MacOS define. Lots of code would assume that not-Unix meant
6319 // Windows, but in this case, it would be OSX.
6329 ves_icall_System_Environment_get_NewLine (void)
6331 MONO_ARCH_SAVE_REGS;
6333 #if defined (HOST_WIN32)
6334 return mono_string_new (mono_domain_get (), "\r\n");
6336 return mono_string_new (mono_domain_get (), "\n");
6341 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6346 MONO_ARCH_SAVE_REGS;
6351 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6352 value = g_getenv (utf8_name);
6359 return mono_string_new (mono_domain_get (), value);
6363 * There is no standard way to get at environ.
6366 #ifndef __MINGW32_VERSION
6367 #if defined(__APPLE__) && !defined (__arm__)
6368 /* Apple defines this in crt_externs.h but doesn't provide that header for
6369 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6370 * in fact exist on all implementations (so far)
6372 gchar ***_NSGetEnviron(void);
6373 #define environ (*_NSGetEnviron())
6382 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6393 env_strings = GetEnvironmentStrings();
6396 env_string = env_strings;
6397 while (*env_string != '\0') {
6398 /* weird case that MS seems to skip */
6399 if (*env_string != '=')
6401 while (*env_string != '\0')
6407 domain = mono_domain_get ();
6408 names = mono_array_new (domain, mono_defaults.string_class, n);
6412 env_string = env_strings;
6413 while (*env_string != '\0') {
6414 /* weird case that MS seems to skip */
6415 if (*env_string != '=') {
6416 equal_str = wcschr(env_string, '=');
6417 g_assert(equal_str);
6418 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6419 mono_array_setref (names, n, str);
6422 while (*env_string != '\0')
6427 FreeEnvironmentStrings (env_strings);
6439 MONO_ARCH_SAVE_REGS;
6442 for (e = environ; *e != 0; ++ e)
6445 domain = mono_domain_get ();
6446 names = mono_array_new (domain, mono_defaults.string_class, n);
6449 for (e = environ; *e != 0; ++ e) {
6450 parts = g_strsplit (*e, "=", 2);
6452 str = mono_string_new (domain, *parts);
6453 mono_array_setref (names, n, str);
6466 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6468 #if !GLIB_CHECK_VERSION(2,4,0)
6469 #define g_setenv(a,b,c) setenv(a,b,c)
6470 #define g_unsetenv(a) unsetenv(a)
6474 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6479 gunichar2 *utf16_name, *utf16_value;
6481 gchar *utf8_name, *utf8_value;
6484 MONO_ARCH_SAVE_REGS;
6487 utf16_name = mono_string_to_utf16 (name);
6488 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6489 SetEnvironmentVariable (utf16_name, NULL);
6490 g_free (utf16_name);
6494 utf16_value = mono_string_to_utf16 (value);
6496 SetEnvironmentVariable (utf16_name, utf16_value);
6498 g_free (utf16_name);
6499 g_free (utf16_value);
6501 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6503 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6504 g_unsetenv (utf8_name);
6509 utf8_value = mono_string_to_utf8_checked (value, &error);
6510 if (!mono_error_ok (&error)) {
6512 mono_error_raise_exception (&error);
6514 g_setenv (utf8_name, utf8_value, TRUE);
6517 g_free (utf8_value);
6522 ves_icall_System_Environment_Exit (int result)
6524 MONO_ARCH_SAVE_REGS;
6526 mono_threads_set_shutting_down ();
6528 mono_runtime_set_shutting_down ();
6530 /* This will kill the tp threads which cannot be suspended */
6531 mono_thread_pool_cleanup ();
6533 /* Suspend all managed threads since the runtime is going away */
6534 mono_thread_suspend_all_other_threads ();
6536 mono_runtime_quit ();
6538 /* we may need to do some cleanup here... */
6543 ves_icall_System_Environment_GetGacPath (void)
6545 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6549 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6551 #if defined (HOST_WIN32)
6552 #ifndef CSIDL_FLAG_CREATE
6553 #define CSIDL_FLAG_CREATE 0x8000
6556 WCHAR path [MAX_PATH];
6557 /* Create directory if no existing */
6558 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6562 return mono_string_new_utf16 (mono_domain_get (), path, len);
6565 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6567 return mono_string_new (mono_domain_get (), "");
6571 ves_icall_System_Environment_GetLogicalDrives (void)
6573 gunichar2 buf [256], *ptr, *dname;
6575 guint initial_size = 127, size = 128;
6578 MonoString *drivestr;
6579 MonoDomain *domain = mono_domain_get ();
6582 MONO_ARCH_SAVE_REGS;
6587 while (size > initial_size) {
6588 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6589 if (size > initial_size) {
6592 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6593 initial_size = size;
6607 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6612 while (*u16) { u16++; len ++; }
6613 drivestr = mono_string_new_utf16 (domain, dname, len);
6614 mono_array_setref (result, ndrives++, drivestr);
6625 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6627 gunichar2 volume_name [MAX_PATH + 1];
6629 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6631 return mono_string_from_utf16 (volume_name);
6635 ves_icall_System_Environment_InternalGetHome (void)
6637 MONO_ARCH_SAVE_REGS;
6639 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6642 static const char *encodings [] = {
6644 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6645 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6646 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6648 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6649 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6650 "x_unicode_2_0_utf_7",
6652 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6653 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6655 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6658 "unicodefffe", "utf_16be",
6665 * Returns the internal codepage, if the value of "int_code_page" is
6666 * 1 at entry, and we can not compute a suitable code page number,
6667 * returns the code page as a string
6670 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6675 char *codepage = NULL;
6677 int want_name = *int_code_page;
6680 *int_code_page = -1;
6681 MONO_ARCH_SAVE_REGS;
6683 g_get_charset (&cset);
6684 c = codepage = strdup (cset);
6685 for (c = codepage; *c; c++){
6686 if (isascii (*c) && isalpha (*c))
6691 /* g_print ("charset: %s\n", cset); */
6693 /* handle some common aliases */
6696 for (i = 0; p != 0; ){
6697 if ((gssize) p < 7){
6699 p = encodings [++i];
6702 if (strcmp (p, codepage) == 0){
6703 *int_code_page = code;
6706 p = encodings [++i];
6709 if (strstr (codepage, "utf_8") != NULL)
6710 *int_code_page |= 0x10000000;
6713 if (want_name && *int_code_page == -1)
6714 return mono_string_new (mono_domain_get (), cset);
6720 ves_icall_System_Environment_get_HasShutdownStarted (void)
6722 if (mono_runtime_is_shutting_down ())
6725 if (mono_domain_is_unloading (mono_domain_get ()))
6732 ves_icall_System_Environment_BroadcastSettingChange (void)
6735 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6740 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6741 MonoReflectionMethod *method,
6742 MonoArray *out_args)
6744 MONO_ARCH_SAVE_REGS;
6746 mono_message_init (mono_object_domain (this), this, method, out_args);
6750 ves_icall_IsTransparentProxy (MonoObject *proxy)
6752 MONO_ARCH_SAVE_REGS;
6757 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6763 static MonoReflectionMethod *
6764 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6765 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6769 MonoMethod **vtable;
6770 MonoMethod *res = NULL;
6772 MONO_CHECK_ARG_NULL (rtype);
6773 MONO_CHECK_ARG_NULL (rmethod);
6775 method = rmethod->method;
6776 klass = mono_class_from_mono_type (rtype->type);
6777 mono_class_init_or_throw (klass);
6779 if (MONO_CLASS_IS_INTERFACE (klass))
6782 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6785 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6786 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6792 mono_class_setup_vtable (klass);
6793 vtable = klass->vtable;
6795 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6796 gboolean variance_used = FALSE;
6797 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6798 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6800 res = vtable [offs + method->slot];
6802 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6805 if (method->slot != -1)
6806 res = vtable [method->slot];
6812 return mono_method_get_object (mono_domain_get (), res, NULL);
6816 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6821 MONO_ARCH_SAVE_REGS;
6823 klass = mono_class_from_mono_type (type->type);
6824 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6826 if (enable) vtable->remote = 1;
6827 else vtable->remote = 0;
6831 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6836 MONO_ARCH_SAVE_REGS;
6838 domain = mono_object_domain (type);
6839 klass = mono_class_from_mono_type (type->type);
6840 mono_class_init_or_throw (klass);
6842 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6843 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6845 if (klass->rank >= 1) {
6846 g_assert (klass->rank == 1);
6847 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6849 /* Bypass remoting object creation check */
6850 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6855 ves_icall_System_IO_get_temp_path (void)
6857 MONO_ARCH_SAVE_REGS;
6859 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6862 #ifndef PLATFORM_NO_DRIVEINFO
6864 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6865 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6869 ULARGE_INTEGER wapi_free_bytes_avail;
6870 ULARGE_INTEGER wapi_total_number_of_bytes;
6871 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6873 MONO_ARCH_SAVE_REGS;
6875 *error = ERROR_SUCCESS;
6876 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6877 &wapi_total_number_of_free_bytes);
6880 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6881 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6882 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6884 *free_bytes_avail = 0;
6885 *total_number_of_bytes = 0;
6886 *total_number_of_free_bytes = 0;
6887 *error = GetLastError ();
6894 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6896 MONO_ARCH_SAVE_REGS;
6898 return GetDriveType (mono_string_chars (root_path_name));
6903 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6905 MONO_ARCH_SAVE_REGS;
6907 return mono_compile_method (method);
6911 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6916 MONO_ARCH_SAVE_REGS;
6918 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6920 #if defined (HOST_WIN32)
6921 /* Avoid mixing '/' and '\\' */
6924 for (i = strlen (path) - 1; i >= 0; i--)
6925 if (path [i] == '/')
6929 mcpath = mono_string_new (mono_domain_get (), path);
6936 get_bundled_app_config (void)
6938 const gchar *app_config;
6941 gchar *config_file_name, *config_file_path;
6945 MONO_ARCH_SAVE_REGS;
6947 domain = mono_domain_get ();
6948 file = domain->setup->configuration_file;
6952 // Retrieve config file and remove the extension
6953 config_file_name = mono_string_to_utf8 (file);
6954 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6955 if (!config_file_path)
6956 config_file_path = config_file_name;
6957 len = strlen (config_file_path) - strlen (".config");
6958 module = g_malloc0 (len + 1);
6959 memcpy (module, config_file_path, len);
6960 // Get the config file from the module name
6961 app_config = mono_config_string_for_assembly_file (module);
6964 if (config_file_name != config_file_path)
6965 g_free (config_file_name);
6966 g_free (config_file_path);
6971 return mono_string_new (mono_domain_get (), app_config);
6975 get_bundled_machine_config (void)
6977 const gchar *machine_config;
6979 MONO_ARCH_SAVE_REGS;
6981 machine_config = mono_get_machine_config ();
6983 if (!machine_config)
6986 return mono_string_new (mono_domain_get (), machine_config);
6990 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6995 MONO_ARCH_SAVE_REGS;
6997 path = g_path_get_dirname (mono_get_config_dir ());
6999 #if defined (HOST_WIN32)
7000 /* Avoid mixing '/' and '\\' */
7003 for (i = strlen (path) - 1; i >= 0; i--)
7004 if (path [i] == '/')
7008 ipath = mono_string_new (mono_domain_get (), path);
7015 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7017 MonoPEResourceDataEntry *entry;
7020 MONO_ARCH_SAVE_REGS;
7022 if (!assembly || !result || !size)
7027 image = assembly->assembly->image;
7028 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7032 *result = mono_image_rva_map (image, entry->rde_data_offset);
7037 *size = entry->rde_size;
7043 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7045 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7049 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7051 #if defined (HOST_WIN32)
7052 OutputDebugString (mono_string_chars (message));
7054 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7058 /* Only used for value types */
7060 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7065 MONO_ARCH_SAVE_REGS;
7067 domain = mono_object_domain (type);
7068 klass = mono_class_from_mono_type (type->type);
7069 mono_class_init_or_throw (klass);
7071 if (mono_class_is_nullable (klass))
7072 /* No arguments -> null */
7075 return mono_object_new (domain, klass);
7078 static MonoReflectionMethod *
7079 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7081 MonoClass *klass, *parent;
7082 MonoMethod *method = m->method;
7083 MonoMethod *result = NULL;
7086 MONO_ARCH_SAVE_REGS;
7088 if (method->klass == NULL)
7091 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7092 MONO_CLASS_IS_INTERFACE (method->klass) ||
7093 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7096 slot = mono_method_get_vtable_slot (method);
7100 klass = method->klass;
7101 if (klass->generic_class)
7102 klass = klass->generic_class->container_class;
7105 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7106 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7107 mono_class_setup_vtable (parent);
7108 if (parent->vtable_size <= slot)
7113 klass = klass->parent;
7118 if (klass == method->klass)
7121 /*This is possible if definition == FALSE.
7122 * Do it here to be really sure we don't read invalid memory.
7124 if (slot >= klass->vtable_size)
7127 mono_class_setup_vtable (klass);
7129 result = klass->vtable [slot];
7130 if (result == NULL) {
7131 /* It is an abstract method */
7132 gpointer iter = NULL;
7133 while ((result = mono_class_get_methods (klass, &iter)))
7134 if (result->slot == slot)
7141 return mono_method_get_object (mono_domain_get (), result, NULL);
7145 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7147 MonoMethod *method = m->method;
7149 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7154 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7156 MONO_ARCH_SAVE_REGS;
7158 iter->sig = *(MonoMethodSignature**)argsp;
7160 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7161 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7164 /* FIXME: it's not documented what start is exactly... */
7168 iter->args = argsp + sizeof (gpointer);
7170 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7172 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7176 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7178 guint32 i, arg_size;
7181 MONO_ARCH_SAVE_REGS;
7183 i = iter->sig->sentinelpos + iter->next_arg;
7185 g_assert (i < iter->sig->param_count);
7187 res.type = iter->sig->params [i];
7188 res.klass = mono_class_from_mono_type (res.type);
7189 arg_size = mono_type_stack_size (res.type, &align);
7190 #if defined(__arm__)
7191 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7193 res.value = iter->args;
7194 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7195 if (arg_size <= sizeof (gpointer)) {
7197 int padding = arg_size - mono_type_size (res.type, &dummy);
7198 res.value = (guint8*)res.value + padding;
7201 iter->args = (char*)iter->args + arg_size;
7204 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7210 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7212 guint32 i, arg_size;
7215 MONO_ARCH_SAVE_REGS;
7217 i = iter->sig->sentinelpos + iter->next_arg;
7219 g_assert (i < iter->sig->param_count);
7221 while (i < iter->sig->param_count) {
7222 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7224 res.type = iter->sig->params [i];
7225 res.klass = mono_class_from_mono_type (res.type);
7226 /* FIXME: endianess issue... */
7227 arg_size = mono_type_stack_size (res.type, &align);
7228 #if defined(__arm__)
7229 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7231 res.value = iter->args;
7232 iter->args = (char*)iter->args + arg_size;
7234 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7237 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7246 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7249 MONO_ARCH_SAVE_REGS;
7251 i = iter->sig->sentinelpos + iter->next_arg;
7253 g_assert (i < iter->sig->param_count);
7255 return iter->sig->params [i];
7259 mono_TypedReference_ToObject (MonoTypedRef tref)
7261 MONO_ARCH_SAVE_REGS;
7263 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7264 MonoObject** objp = tref.value;
7268 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7272 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7274 MONO_ARCH_SAVE_REGS;
7276 if (MONO_TYPE_IS_REFERENCE (type)) {
7277 MonoObject** objp = value;
7281 return mono_value_box (mono_domain_get (), klass, value);
7285 prelink_method (MonoMethod *method)
7287 const char *exc_class, *exc_arg;
7288 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7290 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7292 mono_raise_exception(
7293 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7295 /* create the wrapper, too? */
7299 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7301 MONO_ARCH_SAVE_REGS;
7302 prelink_method (method->method);
7306 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7308 MonoClass *klass = mono_class_from_mono_type (type->type);
7310 gpointer iter = NULL;
7311 MONO_ARCH_SAVE_REGS;
7313 mono_class_init_or_throw (klass);
7315 while ((m = mono_class_get_methods (klass, &iter)))
7319 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7321 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7322 gint32 const **exponents,
7323 gunichar2 const **digitLowerTable,
7324 gunichar2 const **digitUpperTable,
7325 gint64 const **tenPowersList,
7326 gint32 const **decHexDigits)
7328 *mantissas = Formatter_MantissaBitsTable;
7329 *exponents = Formatter_TensExponentTable;
7330 *digitLowerTable = Formatter_DigitLowerTable;
7331 *digitUpperTable = Formatter_DigitUpperTable;
7332 *tenPowersList = Formatter_TenPowersList;
7333 *decHexDigits = Formatter_DecHexDigits;
7336 /* These parameters are "readonly" in corlib/System/Char.cs */
7338 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7339 guint8 const **numeric_data,
7340 gdouble const **numeric_data_values,
7341 guint16 const **to_lower_data_low,
7342 guint16 const **to_lower_data_high,
7343 guint16 const **to_upper_data_low,
7344 guint16 const **to_upper_data_high)
7346 *category_data = CategoryData;
7347 *numeric_data = NumericData;
7348 *numeric_data_values = NumericDataValues;
7349 *to_lower_data_low = ToLowerDataLow;
7350 *to_lower_data_high = ToLowerDataHigh;
7351 *to_upper_data_low = ToUpperDataLow;
7352 *to_upper_data_high = ToUpperDataHigh;
7356 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7358 return method->method->token;
7362 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7363 * and avoid useless allocations.
7366 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7370 for (i = 0; i < type->num_mods; ++i) {
7371 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7376 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7378 for (i = 0; i < type->num_mods; ++i) {
7379 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7380 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7381 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7389 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7391 MonoType *type = param->ClassImpl->type;
7392 MonoClass *member_class = mono_object_class (param->MemberImpl);
7393 MonoMethod *method = NULL;
7396 MonoMethodSignature *sig;
7398 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7399 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7400 method = rmethod->method;
7401 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7402 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7403 if (!(method = prop->property->get))
7404 method = prop->property->set;
7407 char *type_name = mono_type_get_full_name (member_class);
7408 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7409 MonoException *ex = mono_get_exception_not_supported (msg);
7412 mono_raise_exception (ex);
7415 image = method->klass->image;
7416 pos = param->PositionImpl;
7417 sig = mono_method_signature (method);
7421 type = sig->params [pos];
7423 return type_array_from_modifiers (image, type, optional);
7427 get_property_type (MonoProperty *prop)
7429 MonoMethodSignature *sig;
7431 sig = mono_method_signature (prop->get);
7433 } else if (prop->set) {
7434 sig = mono_method_signature (prop->set);
7435 return sig->params [sig->param_count - 1];
7441 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7443 MonoType *type = get_property_type (property->property);
7444 MonoImage *image = property->klass->image;
7448 return type_array_from_modifiers (image, type, optional);
7452 *Construct a MonoType suited to be used to decode a constant blob object.
7454 * @type is the target type which will be constructed
7455 * @blob_type is the blob type, for example, that comes from the constant table
7456 * @real_type is the expected constructed type.
7459 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7461 type->type = blob_type;
7462 type->data.klass = NULL;
7463 if (blob_type == MONO_TYPE_CLASS)
7464 type->data.klass = mono_defaults.object_class;
7465 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7466 /* For enums, we need to use the base type */
7467 type->type = MONO_TYPE_VALUETYPE;
7468 type->data.klass = mono_class_from_mono_type (real_type);
7470 type->data.klass = mono_class_from_mono_type (real_type);
7474 property_info_get_default_value (MonoReflectionProperty *property)
7477 MonoProperty *prop = property->property;
7478 MonoType *type = get_property_type (prop);
7479 MonoDomain *domain = mono_object_domain (property);
7480 MonoTypeEnum def_type;
7481 const char *def_value;
7484 mono_class_init (prop->parent);
7486 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7487 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7489 def_value = mono_class_get_property_default_value (prop, &def_type);
7491 mono_type_from_blob_type (&blob_type, def_type, type);
7492 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7498 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7500 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7501 MonoCustomAttrInfo *cinfo;
7504 mono_class_init_or_throw (attr_class);
7506 cinfo = mono_reflection_get_custom_attrs_info (obj);
7509 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7511 mono_custom_attrs_free (cinfo);
7516 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7518 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7523 mono_class_init_or_throw (attr_class);
7525 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7526 if (!mono_error_ok (&error))
7527 mono_error_raise_exception (&error);
7528 if (mono_loader_get_last_error ()) {
7529 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7530 g_assert_not_reached ();
7539 ves_icall_Mono_Runtime_GetDisplayName (void)
7542 MonoString *display_name;
7544 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7545 display_name = mono_string_new (mono_domain_get (), info);
7547 return display_name;
7551 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7553 MonoString *message;
7557 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7558 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7561 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7563 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7571 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7572 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7573 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7574 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7575 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7576 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7577 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7578 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7582 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7587 gunichar2 last, prev_last, prev2_last;
7595 last = prev_last = 0, prev2_last = 0;
7596 for (i = 0; i < ilength; i++) {
7598 if (c >= sizeof (dbase64)) {
7599 exc = mono_exception_from_name_msg (mono_get_corlib (),
7600 "System", "FormatException",
7601 "Invalid character found.");
7602 mono_raise_exception (exc);
7603 } else if (isspace (c)) {
7606 prev2_last = prev_last;
7612 olength = ilength - ignored;
7614 if (allowWhitespaceOnly && olength == 0) {
7615 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7618 if ((olength & 3) != 0 || olength <= 0) {
7619 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7620 "FormatException", "Invalid length.");
7621 mono_raise_exception (exc);
7624 if (prev2_last == '=') {
7625 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7626 mono_raise_exception (exc);
7629 olength = (olength * 3) / 4;
7633 if (prev_last == '=')
7636 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7637 res_ptr = mono_array_addr (result, guchar, 0);
7638 for (i = 0; i < ilength; ) {
7641 for (k = 0; k < 4 && i < ilength;) {
7647 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7648 exc = mono_exception_from_name_msg (mono_get_corlib (),
7649 "System", "FormatException",
7650 "Invalid character found.");
7651 mono_raise_exception (exc);
7656 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7658 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7660 *res_ptr++ = (b [2] << 6) | b [3];
7662 while (i < ilength && isspace (start [i]))
7670 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7672 MONO_ARCH_SAVE_REGS;
7674 return base64_to_byte_array (mono_string_chars (str),
7675 mono_string_length (str), allowWhitespaceOnly);
7679 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7681 MONO_ARCH_SAVE_REGS;
7683 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7687 #define ICALL_TYPE(id,name,first)
7688 #define ICALL(id,name,func) Icall_ ## id,
7691 #include "metadata/icall-def.h"
7697 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7698 #define ICALL(id,name,func)
7700 #include "metadata/icall-def.h"
7706 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7707 #define ICALL(id,name,func)
7709 guint16 first_icall;
7712 static const IcallTypeDesc
7713 icall_type_descs [] = {
7714 #include "metadata/icall-def.h"
7718 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7721 #define ICALL_TYPE(id,name,first)
7724 #ifdef HAVE_ARRAY_ELEM_INIT
7725 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7726 #define MSGSTRFIELD1(line) str##line
7728 static const struct msgstrtn_t {
7729 #define ICALL(id,name,func)
7731 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7732 #include "metadata/icall-def.h"
7734 } icall_type_names_str = {
7735 #define ICALL_TYPE(id,name,first) (name),
7736 #include "metadata/icall-def.h"
7739 static const guint16 icall_type_names_idx [] = {
7740 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7741 #include "metadata/icall-def.h"
7744 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7746 static const struct msgstr_t {
7748 #define ICALL_TYPE(id,name,first)
7749 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7750 #include "metadata/icall-def.h"
7752 } icall_names_str = {
7753 #define ICALL(id,name,func) (name),
7754 #include "metadata/icall-def.h"
7757 static const guint16 icall_names_idx [] = {
7758 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7759 #include "metadata/icall-def.h"
7762 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7768 #define ICALL_TYPE(id,name,first) name,
7769 #define ICALL(id,name,func)
7770 static const char* const
7771 icall_type_names [] = {
7772 #include "metadata/icall-def.h"
7776 #define icall_type_name_get(id) (icall_type_names [(id)])
7780 #define ICALL_TYPE(id,name,first)
7781 #define ICALL(id,name,func) name,
7782 static const char* const
7784 #include "metadata/icall-def.h"
7787 #define icall_name_get(id) icall_names [(id)]
7789 #endif /* !HAVE_ARRAY_ELEM_INIT */
7793 #define ICALL_TYPE(id,name,first)
7794 #define ICALL(id,name,func) func,
7795 static const gconstpointer
7796 icall_functions [] = {
7797 #include "metadata/icall-def.h"
7801 static GHashTable *icall_hash = NULL;
7802 static GHashTable *jit_icall_hash_name = NULL;
7803 static GHashTable *jit_icall_hash_addr = NULL;
7806 mono_icall_init (void)
7810 /* check that tables are sorted: disable in release */
7813 const char *prev_class = NULL;
7814 const char *prev_method;
7816 for (i = 0; i < Icall_type_num; ++i) {
7817 const IcallTypeDesc *desc;
7820 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7821 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7822 prev_class = icall_type_name_get (i);
7823 desc = &icall_type_descs [i];
7824 num_icalls = icall_desc_num_icalls (desc);
7825 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7826 for (j = 0; j < num_icalls; ++j) {
7827 const char *methodn = icall_name_get (desc->first_icall + j);
7828 if (prev_method && strcmp (prev_method, methodn) >= 0)
7829 g_print ("method %s should come before method %s\n", methodn, prev_method);
7830 prev_method = methodn;
7835 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7839 mono_icall_cleanup (void)
7841 g_hash_table_destroy (icall_hash);
7842 g_hash_table_destroy (jit_icall_hash_name);
7843 g_hash_table_destroy (jit_icall_hash_addr);
7847 mono_add_internal_call (const char *name, gconstpointer method)
7849 mono_loader_lock ();
7851 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7853 mono_loader_unlock ();
7856 #ifdef HAVE_ARRAY_ELEM_INIT
7858 compare_method_imap (const void *key, const void *elem)
7860 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7861 return strcmp (key, method_name);
7865 find_method_icall (const IcallTypeDesc *imap, const char *name)
7867 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7870 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7874 compare_class_imap (const void *key, const void *elem)
7876 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7877 return strcmp (key, class_name);
7880 static const IcallTypeDesc*
7881 find_class_icalls (const char *name)
7883 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7886 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7891 compare_method_imap (const void *key, const void *elem)
7893 const char** method_name = (const char**)elem;
7894 return strcmp (key, *method_name);
7898 find_method_icall (const IcallTypeDesc *imap, const char *name)
7900 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7903 return (gpointer)icall_functions [(nameslot - icall_names)];
7907 compare_class_imap (const void *key, const void *elem)
7909 const char** class_name = (const char**)elem;
7910 return strcmp (key, *class_name);
7913 static const IcallTypeDesc*
7914 find_class_icalls (const char *name)
7916 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7919 return &icall_type_descs [nameslot - icall_type_names];
7925 * we should probably export this as an helper (handle nested types).
7926 * Returns the number of chars written in buf.
7929 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7931 int nspacelen, cnamelen;
7932 nspacelen = strlen (klass->name_space);
7933 cnamelen = strlen (klass->name);
7934 if (nspacelen + cnamelen + 2 > bufsize)
7937 memcpy (buf, klass->name_space, nspacelen);
7938 buf [nspacelen ++] = '.';
7940 memcpy (buf + nspacelen, klass->name, cnamelen);
7941 buf [nspacelen + cnamelen] = 0;
7942 return nspacelen + cnamelen;
7946 mono_lookup_internal_call (MonoMethod *method)
7951 int typelen = 0, mlen, siglen;
7953 const IcallTypeDesc *imap;
7955 g_assert (method != NULL);
7957 if (method->is_inflated)
7958 method = ((MonoMethodInflated *) method)->declaring;
7960 if (method->klass->nested_in) {
7961 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7965 mname [pos++] = '/';
7968 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7974 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7979 imap = find_class_icalls (mname);
7981 mname [typelen] = ':';
7982 mname [typelen + 1] = ':';
7984 mlen = strlen (method->name);
7985 memcpy (mname + typelen + 2, method->name, mlen);
7986 sigstart = mname + typelen + 2 + mlen;
7989 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7990 siglen = strlen (tmpsig);
7991 if (typelen + mlen + siglen + 6 > sizeof (mname))
7994 memcpy (sigstart + 1, tmpsig, siglen);
7995 sigstart [siglen + 1] = ')';
7996 sigstart [siglen + 2] = 0;
7999 mono_loader_lock ();
8001 res = g_hash_table_lookup (icall_hash, mname);
8003 mono_loader_unlock ();
8006 /* try without signature */
8008 res = g_hash_table_lookup (icall_hash, mname);
8010 mono_loader_unlock ();
8014 /* it wasn't found in the static call tables */
8016 mono_loader_unlock ();
8019 res = find_method_icall (imap, sigstart - mlen);
8021 mono_loader_unlock ();
8024 /* try _with_ signature */
8026 res = find_method_icall (imap, sigstart - mlen);
8028 mono_loader_unlock ();
8032 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8033 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8034 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8035 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8036 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");
8037 g_print ("If you see other errors or faults after this message they are probably related\n");
8038 g_print ("and you need to fix your mono install first.\n");
8040 mono_loader_unlock ();
8046 type_from_typename (char *typename)
8048 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8050 if (!strcmp (typename, "int"))
8051 klass = mono_defaults.int_class;
8052 else if (!strcmp (typename, "ptr"))
8053 klass = mono_defaults.int_class;
8054 else if (!strcmp (typename, "void"))
8055 klass = mono_defaults.void_class;
8056 else if (!strcmp (typename, "int32"))
8057 klass = mono_defaults.int32_class;
8058 else if (!strcmp (typename, "uint32"))
8059 klass = mono_defaults.uint32_class;
8060 else if (!strcmp (typename, "int8"))
8061 klass = mono_defaults.sbyte_class;
8062 else if (!strcmp (typename, "uint8"))
8063 klass = mono_defaults.byte_class;
8064 else if (!strcmp (typename, "int16"))
8065 klass = mono_defaults.int16_class;
8066 else if (!strcmp (typename, "uint16"))
8067 klass = mono_defaults.uint16_class;
8068 else if (!strcmp (typename, "long"))
8069 klass = mono_defaults.int64_class;
8070 else if (!strcmp (typename, "ulong"))
8071 klass = mono_defaults.uint64_class;
8072 else if (!strcmp (typename, "float"))
8073 klass = mono_defaults.single_class;
8074 else if (!strcmp (typename, "double"))
8075 klass = mono_defaults.double_class;
8076 else if (!strcmp (typename, "object"))
8077 klass = mono_defaults.object_class;
8078 else if (!strcmp (typename, "obj"))
8079 klass = mono_defaults.object_class;
8080 else if (!strcmp (typename, "string"))
8081 klass = mono_defaults.string_class;
8082 else if (!strcmp (typename, "bool"))
8083 klass = mono_defaults.boolean_class;
8084 else if (!strcmp (typename, "boolean"))
8085 klass = mono_defaults.boolean_class;
8087 g_error ("%s", typename);
8088 g_assert_not_reached ();
8090 return &klass->byval_arg;
8093 MonoMethodSignature*
8094 mono_create_icall_signature (const char *sigstr)
8099 MonoMethodSignature *res;
8101 mono_loader_lock ();
8102 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8104 mono_loader_unlock ();
8108 parts = g_strsplit (sigstr, " ", 256);
8117 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8122 * Under windows, the default pinvoke calling convention is STDCALL but
8125 res->call_convention = MONO_CALL_C;
8128 res->ret = type_from_typename (parts [0]);
8129 for (i = 1; i < len; ++i) {
8130 res->params [i - 1] = type_from_typename (parts [i]);
8135 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8137 mono_loader_unlock ();
8143 mono_find_jit_icall_by_name (const char *name)
8145 MonoJitICallInfo *info;
8146 g_assert (jit_icall_hash_name);
8148 mono_loader_lock ();
8149 info = g_hash_table_lookup (jit_icall_hash_name, name);
8150 mono_loader_unlock ();
8155 mono_find_jit_icall_by_addr (gconstpointer addr)
8157 MonoJitICallInfo *info;
8158 g_assert (jit_icall_hash_addr);
8160 mono_loader_lock ();
8161 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8162 mono_loader_unlock ();
8168 * mono_get_jit_icall_info:
8170 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8171 * caller should access it while holding the loader lock.
8174 mono_get_jit_icall_info (void)
8176 return jit_icall_hash_name;
8180 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8182 mono_loader_lock ();
8183 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8184 mono_loader_unlock ();
8188 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8190 MonoJitICallInfo *info;
8195 mono_loader_lock ();
8197 if (!jit_icall_hash_name) {
8198 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8199 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8202 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8203 g_warning ("jit icall already defined \"%s\"\n", name);
8204 g_assert_not_reached ();
8207 info = g_new0 (MonoJitICallInfo, 1);
8214 info->wrapper = func;
8216 info->wrapper = NULL;
8219 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8220 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8222 mono_loader_unlock ();