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 mono_gc_bzero (ea, 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 mono_gc_memmove (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 mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), 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 mono_gc_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 mono_gc_memmove (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 mono_gc_memmove (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;
1915 MONO_ARCH_SAVE_REGS;
1917 mono_class_init (field->parent);
1919 t = mono_field_get_type_checked (field, &error);
1920 if (!mono_error_ok (&error))
1921 mono_error_raise_exception (&error);
1923 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1924 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1926 if (field->parent->image->dynamic) {
1928 g_assert_not_reached ();
1931 def_value = mono_class_get_field_default_value (field, &def_type);
1932 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1933 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1935 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1939 case MONO_TYPE_BOOLEAN:
1942 case MONO_TYPE_CHAR:
1950 case MONO_TYPE_R8: {
1953 /* boxed value type */
1954 t = g_new0 (MonoType, 1);
1956 klass = mono_class_from_mono_type (t);
1958 o = mono_object_new (domain, klass);
1959 v = ((gchar *) o) + sizeof (MonoObject);
1960 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1963 case MONO_TYPE_STRING:
1964 case MONO_TYPE_CLASS:
1965 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1968 g_assert_not_reached ();
1974 static MonoReflectionType*
1975 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1978 MonoClassField *field = ref_field->field;
1979 MonoType *type = mono_field_get_type_checked (field, &error);
1980 if (!mono_error_ok (&error))
1981 mono_error_raise_exception (&error);
1982 return mono_type_get_object (mono_object_domain (ref_field), type);
1985 static MonoReflectionType*
1986 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1988 MonoMethod *method = rmethod->method.method;
1990 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1993 /* From MonoProperty.cs */
1995 PInfo_Attributes = 1,
1996 PInfo_GetMethod = 1 << 1,
1997 PInfo_SetMethod = 1 << 2,
1998 PInfo_ReflectedType = 1 << 3,
1999 PInfo_DeclaringType = 1 << 4,
2004 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2006 MonoDomain *domain = mono_object_domain (property);
2008 MONO_ARCH_SAVE_REGS;
2010 if ((req_info & PInfo_ReflectedType) != 0)
2011 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2012 if ((req_info & PInfo_DeclaringType) != 0)
2013 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2015 if ((req_info & PInfo_Name) != 0)
2016 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2018 if ((req_info & PInfo_Attributes) != 0)
2019 info->attrs = property->property->attrs;
2021 if ((req_info & PInfo_GetMethod) != 0)
2022 MONO_STRUCT_SETREF (info, get, property->property->get ?
2023 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2025 if ((req_info & PInfo_SetMethod) != 0)
2026 MONO_STRUCT_SETREF (info, set, property->property->set ?
2027 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2029 * There may be other methods defined for properties, though, it seems they are not exposed
2030 * in the reflection API
2035 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2037 MonoDomain *domain = mono_object_domain (event);
2039 MONO_ARCH_SAVE_REGS;
2041 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2042 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2044 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2045 info->attrs = event->event->attrs;
2046 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2047 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2048 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2050 #ifndef MONO_SMALL_CONFIG
2051 if (event->event->other) {
2053 while (event->event->other [n])
2055 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2057 for (i = 0; i < n; i++)
2058 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2064 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2069 mono_class_setup_interfaces (klass, error);
2070 if (!mono_error_ok (error))
2073 for (i = 0; i < klass->interface_count; i++) {
2074 ic = klass->interfaces [i];
2075 g_hash_table_insert (ifaces, ic, ic);
2077 collect_interfaces (ic, ifaces, error);
2078 if (!mono_error_ok (error))
2084 MonoArray *iface_array;
2085 MonoGenericContext *context;
2089 } FillIfaceArrayData;
2092 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2094 FillIfaceArrayData *data = user_data;
2095 MonoClass *ic = key;
2096 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2098 if (!mono_error_ok (data->error))
2101 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2102 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2103 if (!mono_error_ok (data->error))
2107 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2110 mono_metadata_free_type (inflated);
2114 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2117 MonoClass *class = mono_class_from_mono_type (type->type);
2119 FillIfaceArrayData data = { 0 };
2122 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2124 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2125 data.context = mono_class_get_context (class);
2126 class = class->generic_class->container_class;
2129 for (parent = class; parent; parent = parent->parent) {
2130 mono_class_setup_interfaces (parent, &error);
2131 if (!mono_error_ok (&error))
2133 collect_interfaces (parent, iface_hash, &error);
2134 if (!mono_error_ok (&error))
2138 data.error = &error;
2139 data.domain = mono_object_domain (type);
2141 len = g_hash_table_size (iface_hash);
2143 g_hash_table_destroy (iface_hash);
2144 if (!data.domain->empty_types)
2145 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2146 return data.domain->empty_types;
2149 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2150 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2151 if (!mono_error_ok (&error))
2154 g_hash_table_destroy (iface_hash);
2155 return data.iface_array;
2158 g_hash_table_destroy (iface_hash);
2159 mono_error_raise_exception (&error);
2164 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2166 gboolean variance_used;
2167 MonoClass *class = mono_class_from_mono_type (type->type);
2168 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2169 MonoReflectionMethod *member;
2172 int i = 0, len, ioffset;
2175 MONO_ARCH_SAVE_REGS;
2176 mono_class_init_or_throw (class);
2177 mono_class_init_or_throw (iclass);
2179 mono_class_setup_vtable (class);
2181 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2185 len = mono_class_num_methods (iclass);
2186 domain = mono_object_domain (type);
2187 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2188 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2190 while ((method = mono_class_get_methods (iclass, &iter))) {
2191 member = mono_method_get_object (domain, method, iclass);
2192 mono_array_setref (*methods, i, member);
2193 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2194 mono_array_setref (*targets, i, member);
2201 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2203 MonoClass *klass = mono_class_from_mono_type (type->type);
2204 mono_class_init_or_throw (klass);
2206 if (klass->image->dynamic) {
2207 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2208 *packing = tb->packing_size;
2209 *size = tb->class_size;
2211 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2215 static MonoReflectionType*
2216 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2220 MONO_ARCH_SAVE_REGS;
2222 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2223 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2225 class = mono_class_from_mono_type (type->type);
2226 mono_class_init_or_throw (class);
2228 // GetElementType should only return a type for:
2229 // Array Pointer PassedByRef
2230 if (type->type->byref)
2231 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2232 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2233 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2234 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2235 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2240 static MonoReflectionType*
2241 ves_icall_get_type_parent (MonoReflectionType *type)
2243 MonoClass *class = mono_class_from_mono_type (type->type);
2244 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2248 ves_icall_type_ispointer (MonoReflectionType *type)
2250 MONO_ARCH_SAVE_REGS;
2252 return type->type->type == MONO_TYPE_PTR;
2256 ves_icall_type_isprimitive (MonoReflectionType *type)
2258 MONO_ARCH_SAVE_REGS;
2260 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)));
2264 ves_icall_type_isbyref (MonoReflectionType *type)
2266 MONO_ARCH_SAVE_REGS;
2268 return type->type->byref;
2272 ves_icall_type_iscomobject (MonoReflectionType *type)
2274 MonoClass *klass = mono_class_from_mono_type (type->type);
2275 mono_class_init_or_throw (klass);
2277 return (klass && klass->is_com_object);
2280 static MonoReflectionModule*
2281 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2283 MonoClass *class = mono_class_from_mono_type (type->type);
2284 return mono_module_get_object (mono_object_domain (type), class->image);
2287 static MonoReflectionAssembly*
2288 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2290 MonoDomain *domain = mono_domain_get ();
2291 MonoClass *class = mono_class_from_mono_type (type->type);
2292 return mono_assembly_get_object (domain, class->image->assembly);
2295 static MonoReflectionType*
2296 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2298 MonoDomain *domain = mono_domain_get ();
2301 MONO_ARCH_SAVE_REGS;
2303 if (type->type->byref)
2305 if (type->type->type == MONO_TYPE_VAR)
2306 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2307 else if (type->type->type == MONO_TYPE_MVAR)
2308 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2310 class = mono_class_from_mono_type (type->type)->nested_in;
2312 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2316 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2318 MonoDomain *domain = mono_domain_get ();
2319 MonoClass *class = mono_class_from_mono_type (type->type);
2321 if (type->type->byref) {
2322 char *n = g_strdup_printf ("%s&", class->name);
2323 MonoString *res = mono_string_new (domain, n);
2329 return mono_string_new (domain, class->name);
2334 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2336 MonoDomain *domain = mono_domain_get ();
2337 MonoClass *class = mono_class_from_mono_type (type->type);
2339 while (class->nested_in)
2340 class = class->nested_in;
2342 if (class->name_space [0] == '\0')
2345 return mono_string_new (domain, class->name_space);
2349 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2353 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2354 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2356 class = mono_class_from_mono_type (type->type);
2362 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2365 MonoClass *klass, *pklass;
2366 MonoDomain *domain = mono_object_domain (type);
2367 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2369 MONO_ARCH_SAVE_REGS;
2371 klass = mono_class_from_mono_type (type->type);
2373 if (klass->generic_container) {
2374 MonoGenericContainer *container = klass->generic_container;
2375 res = mono_array_new_specific (array_vtable, container->type_argc);
2376 for (i = 0; i < container->type_argc; ++i) {
2377 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2378 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2380 } else if (klass->generic_class) {
2381 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2382 res = mono_array_new_specific (array_vtable, inst->type_argc);
2383 for (i = 0; i < inst->type_argc; ++i)
2384 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2386 res = mono_array_new_specific (array_vtable, 0);
2392 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2395 MONO_ARCH_SAVE_REGS;
2397 if (!IS_MONOTYPE (type))
2400 if (type->type->byref)
2403 klass = mono_class_from_mono_type (type->type);
2404 return klass->generic_container != NULL;
2407 static MonoReflectionType*
2408 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2411 MONO_ARCH_SAVE_REGS;
2413 if (type->type->byref)
2416 klass = mono_class_from_mono_type (type->type);
2418 if (klass->generic_container) {
2419 return type; /* check this one */
2421 if (klass->generic_class) {
2422 MonoClass *generic_class = klass->generic_class->container_class;
2425 tb = mono_class_get_ref_info (generic_class);
2427 if (generic_class->wastypebuilder && tb)
2430 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2435 static MonoReflectionType*
2436 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2439 MonoType *geninst, **types;
2442 g_assert (IS_MONOTYPE (type));
2443 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2445 count = mono_array_length (type_array);
2446 types = g_new0 (MonoType *, count);
2448 for (i = 0; i < count; i++) {
2449 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2450 types [i] = t->type;
2453 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2458 class = mono_class_from_mono_type (geninst);
2460 /*we might inflate to the GTD*/
2461 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2462 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2464 return mono_type_get_object (mono_object_domain (type), geninst);
2468 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2471 MONO_ARCH_SAVE_REGS;
2473 if (type->type->byref)
2476 klass = mono_class_from_mono_type (type->type);
2478 return klass->generic_class != NULL;
2482 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2485 MONO_ARCH_SAVE_REGS;
2487 if (!IS_MONOTYPE (type))
2490 if (type->type->byref)
2493 klass = mono_class_from_mono_type (type->type);
2494 return klass->generic_class != NULL || klass->generic_container != NULL;
2498 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2500 MONO_ARCH_SAVE_REGS;
2502 if (!IS_MONOTYPE (type))
2505 if (is_generic_parameter (type->type))
2506 return mono_type_get_generic_param_num (type->type);
2510 static GenericParameterAttributes
2511 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2513 MONO_ARCH_SAVE_REGS;
2515 g_assert (IS_MONOTYPE (type));
2516 g_assert (is_generic_parameter (type->type));
2517 return mono_generic_param_info (type->type->data.generic_param)->flags;
2521 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2523 MonoGenericParamInfo *param_info;
2529 MONO_ARCH_SAVE_REGS;
2531 g_assert (IS_MONOTYPE (type));
2533 domain = mono_object_domain (type);
2534 param_info = mono_generic_param_info (type->type->data.generic_param);
2535 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2538 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2539 for (i = 0; i < count; i++)
2540 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2547 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2549 MONO_ARCH_SAVE_REGS;
2550 return is_generic_parameter (type->type);
2554 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2556 MONO_ARCH_SAVE_REGS;
2557 return is_generic_parameter (tb->type.type);
2561 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2562 MonoReflectionType *t)
2564 enumtype->type = t->type;
2567 static MonoReflectionMethod*
2568 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2569 MonoReflectionMethod* generic)
2576 MONO_ARCH_SAVE_REGS;
2578 domain = ((MonoObject *)type)->vtable->domain;
2580 klass = mono_class_from_mono_type (type->type);
2581 mono_class_init_or_throw (klass);
2584 while ((method = mono_class_get_methods (klass, &iter))) {
2585 if (method->token == generic->method->token)
2586 return mono_method_get_object (domain, method, klass);
2594 static MonoReflectionMethod *
2595 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2598 MonoType *type = ref_type->type;
2600 MONO_ARCH_SAVE_REGS;
2602 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2603 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2604 if (type->type == MONO_TYPE_VAR)
2607 method = mono_type_get_generic_param_owner (type)->owner.method;
2609 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2612 static MonoReflectionDllImportAttribute*
2613 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2615 static MonoClass *DllImportAttributeClass = NULL;
2616 MonoDomain *domain = mono_domain_get ();
2617 MonoReflectionDllImportAttribute *attr;
2618 MonoImage *image = method->klass->image;
2619 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2620 MonoTableInfo *tables = image->tables;
2621 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2622 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2623 guint32 im_cols [MONO_IMPLMAP_SIZE];
2624 guint32 scope_token;
2625 const char *import = NULL;
2626 const char *scope = NULL;
2629 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2632 if (!DllImportAttributeClass) {
2633 DllImportAttributeClass =
2634 mono_class_from_name (mono_defaults.corlib,
2635 "System.Runtime.InteropServices", "DllImportAttribute");
2636 g_assert (DllImportAttributeClass);
2639 if (method->klass->image->dynamic) {
2640 MonoReflectionMethodAux *method_aux =
2641 g_hash_table_lookup (
2642 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2644 import = method_aux->dllentry;
2645 scope = method_aux->dll;
2648 if (!import || !scope) {
2649 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2654 if (piinfo->implmap_idx) {
2655 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2657 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2658 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2659 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2660 scope = mono_metadata_string_heap (image, scope_token);
2663 flags = piinfo->piflags;
2665 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2667 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2668 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2669 attr->call_conv = (flags & 0x700) >> 8;
2670 attr->charset = ((flags & 0x6) >> 1) + 1;
2671 if (attr->charset == 1)
2673 attr->exact_spelling = (flags & 0x1) != 0;
2674 attr->set_last_error = (flags & 0x40) != 0;
2675 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2676 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2677 attr->preserve_sig = FALSE;
2682 static MonoReflectionMethod *
2683 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2685 MonoMethodInflated *imethod;
2688 MONO_ARCH_SAVE_REGS;
2690 if (method->method->is_generic)
2693 if (!method->method->is_inflated)
2696 imethod = (MonoMethodInflated *) method->method;
2698 result = imethod->declaring;
2699 /* Not a generic method. */
2700 if (!result->is_generic)
2703 if (method->method->klass->image->dynamic) {
2704 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2705 MonoReflectionMethod *res;
2708 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2709 * the dynamic case as well ?
2711 mono_loader_lock ();
2712 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2713 mono_loader_unlock ();
2719 if (imethod->context.class_inst) {
2720 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2721 /*Generic methods gets the context of the GTD.*/
2722 if (mono_class_get_context (klass))
2723 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2726 return mono_method_get_object (mono_object_domain (method), result, NULL);
2730 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2732 MONO_ARCH_SAVE_REGS;
2734 return mono_method_signature (method->method)->generic_param_count != 0;
2738 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2740 MONO_ARCH_SAVE_REGS;
2742 return method->method->is_generic;
2746 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2751 MONO_ARCH_SAVE_REGS;
2753 domain = mono_object_domain (method);
2755 if (method->method->is_inflated) {
2756 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2759 count = inst->type_argc;
2760 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2762 for (i = 0; i < count; i++)
2763 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2769 count = mono_method_signature (method->method)->generic_param_count;
2770 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2772 for (i = 0; i < count; i++) {
2773 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2774 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2775 MonoClass *pklass = mono_class_from_generic_parameter (
2776 param, method->method->klass->image, TRUE);
2777 mono_array_setref (res, i,
2778 mono_type_get_object (domain, &pklass->byval_arg));
2785 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2788 * Invoke from reflection is supposed to always be a virtual call (the API
2789 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2790 * greater flexibility.
2792 MonoMethod *m = method->method;
2796 MONO_ARCH_SAVE_REGS;
2800 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2801 mono_security_core_clr_ensure_reflection_access_method (m);
2803 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2804 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2805 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2810 if (!mono_object_isinst (this, m->klass)) {
2811 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2814 m = mono_object_get_virtual_method (this, m);
2815 /* must pass the pointer to the value for valuetype methods */
2816 if (m->klass->valuetype)
2817 obj = mono_object_unbox (this);
2818 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2819 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2824 pcount = params? mono_array_length (params): 0;
2825 if (pcount != mono_method_signature (m)->param_count) {
2826 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2830 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2831 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."));
2835 if (m->klass->image->assembly->ref_only) {
2836 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."));
2840 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2843 intptr_t *lower_bounds;
2844 pcount = mono_array_length (params);
2845 lengths = alloca (sizeof (uintptr_t) * pcount);
2846 /* Note: the synthetized array .ctors have int32 as argument type */
2847 for (i = 0; i < pcount; ++i)
2848 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2850 if (m->klass->rank == pcount) {
2851 /* Only lengths provided. */
2852 lower_bounds = NULL;
2854 g_assert (pcount == (m->klass->rank * 2));
2855 /* lower bounds are first. */
2856 lower_bounds = (intptr_t*)lengths;
2857 lengths += m->klass->rank;
2860 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2862 return mono_runtime_invoke_array (m, obj, params, NULL);
2866 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2868 MonoDomain *domain = mono_object_domain (method);
2869 MonoMethod *m = method->method;
2870 MonoMethodSignature *sig = mono_method_signature (m);
2871 MonoArray *out_args;
2873 int i, j, outarg_count = 0;
2875 MONO_ARCH_SAVE_REGS;
2877 if (m->klass == mono_defaults.object_class) {
2879 if (!strcmp (m->name, "FieldGetter")) {
2880 MonoClass *k = this->vtable->klass;
2884 /* If this is a proxy, then it must be a CBO */
2885 if (k == mono_defaults.transparent_proxy_class) {
2886 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2887 this = tp->rp->unwrapped_server;
2889 k = this->vtable->klass;
2892 name = mono_array_get (params, MonoString *, 1);
2893 str = mono_string_to_utf8 (name);
2896 MonoClassField* field = mono_class_get_field_from_name (k, str);
2898 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2899 if (field_klass->valuetype)
2900 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2902 result = *((gpointer *)((char *)this + field->offset));
2904 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2905 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2906 mono_array_setref (out_args, 0, result);
2914 g_assert_not_reached ();
2916 } else if (!strcmp (m->name, "FieldSetter")) {
2917 MonoClass *k = this->vtable->klass;
2923 /* If this is a proxy, then it must be a CBO */
2924 if (k == mono_defaults.transparent_proxy_class) {
2925 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2926 this = tp->rp->unwrapped_server;
2928 k = this->vtable->klass;
2931 name = mono_array_get (params, MonoString *, 1);
2932 str = mono_string_to_utf8 (name);
2935 MonoClassField* field = mono_class_get_field_from_name (k, str);
2937 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2938 MonoObject *val = mono_array_get (params, gpointer, 2);
2940 if (field_klass->valuetype) {
2941 size = mono_type_size (field->type, &align);
2942 g_assert (size == mono_class_value_size (field_klass, NULL));
2943 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2945 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2948 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2949 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2959 g_assert_not_reached ();
2964 for (i = 0; i < mono_array_length (params); i++) {
2965 if (sig->params [i]->byref)
2969 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2971 /* handle constructors only for objects already allocated */
2972 if (!strcmp (method->method->name, ".ctor"))
2975 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2976 g_assert (!method->method->klass->valuetype);
2977 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2979 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2980 if (sig->params [i]->byref) {
2982 arg = mono_array_get (params, gpointer, i);
2983 mono_array_setref (out_args, j, arg);
2988 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2994 read_enum_value (char *mem, int type)
2998 return *(guint8*)mem;
3000 return *(gint8*)mem;
3002 return *(guint16*)mem;
3004 return *(gint16*)mem;
3006 return *(guint32*)mem;
3008 return *(gint32*)mem;
3010 return *(guint64*)mem;
3012 return *(gint64*)mem;
3014 g_assert_not_reached ();
3020 write_enum_value (char *mem, int type, guint64 value)
3024 case MONO_TYPE_I1: {
3025 guint8 *p = (guint8*)mem;
3030 case MONO_TYPE_I2: {
3031 guint16 *p = (void*)mem;
3036 case MONO_TYPE_I4: {
3037 guint32 *p = (void*)mem;
3042 case MONO_TYPE_I8: {
3043 guint64 *p = (void*)mem;
3048 g_assert_not_reached ();
3054 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3057 MonoClass *enumc, *objc;
3062 MONO_ARCH_SAVE_REGS;
3064 MONO_CHECK_ARG_NULL (enumType);
3065 MONO_CHECK_ARG_NULL (value);
3067 domain = mono_object_domain (enumType);
3068 enumc = mono_class_from_mono_type (enumType->type);
3070 mono_class_init_or_throw (enumc);
3072 objc = value->vtable->klass;
3074 if (!enumc->enumtype)
3075 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3076 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3077 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."));
3079 etype = mono_class_enum_basetype (enumc);
3081 /* MS throws this for typebuilders */
3082 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3084 res = mono_object_new (domain, enumc);
3085 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3086 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3092 ves_icall_System_Enum_get_value (MonoObject *this)
3100 MONO_ARCH_SAVE_REGS;
3105 g_assert (this->vtable->klass->enumtype);
3107 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3108 res = mono_object_new (mono_object_domain (this), enumc);
3109 dst = (char *)res + sizeof (MonoObject);
3110 src = (char *)this + sizeof (MonoObject);
3111 size = mono_class_value_size (enumc, NULL);
3113 memcpy (dst, src, size);
3118 static MonoReflectionType *
3119 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3124 MONO_ARCH_SAVE_REGS;
3126 klass = mono_class_from_mono_type (type->type);
3127 mono_class_init_or_throw (klass);
3129 etype = mono_class_enum_basetype (klass);
3131 /* MS throws this for typebuilders */
3132 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3134 return mono_type_get_object (mono_object_domain (type), etype);
3138 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3140 gpointer tdata = (char *)this + sizeof (MonoObject);
3141 gpointer odata = (char *)other + sizeof (MonoObject);
3142 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3143 g_assert (basetype);
3145 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3146 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3147 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3150 return me > other ? 1 : -1; \
3153 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3154 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3155 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3158 return me - other; \
3161 switch (basetype->type) {
3163 COMPARE_ENUM_VALUES (guint8);
3165 COMPARE_ENUM_VALUES (gint8);
3166 case MONO_TYPE_CHAR:
3168 COMPARE_ENUM_VALUES_RANGE (guint16);
3170 COMPARE_ENUM_VALUES (gint16);
3172 COMPARE_ENUM_VALUES (guint32);
3174 COMPARE_ENUM_VALUES (gint32);
3176 COMPARE_ENUM_VALUES (guint64);
3178 COMPARE_ENUM_VALUES (gint64);
3180 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3182 #undef COMPARE_ENUM_VALUES_RANGE
3183 #undef COMPARE_ENUM_VALUES
3188 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3190 gpointer data = (char *)this + sizeof (MonoObject);
3191 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3192 g_assert (basetype);
3194 switch (basetype->type) {
3196 return *((gint8*)data);
3198 return *((guint8*)data);
3199 case MONO_TYPE_CHAR:
3201 return *((guint16*)data);
3204 return *((gint16*)data);
3206 return *((guint32*)data);
3208 return *((gint32*)data);
3210 case MONO_TYPE_I8: {
3211 gint64 value = *((gint64*)data);
3212 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3215 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3221 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3223 MonoDomain *domain = mono_object_domain (type);
3224 MonoClass *enumc = mono_class_from_mono_type (type->type);
3225 guint j = 0, nvalues, crow;
3227 MonoClassField *field;
3229 MONO_ARCH_SAVE_REGS;
3231 mono_class_init_or_throw (enumc);
3233 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3234 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3235 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3236 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3240 while ((field = mono_class_get_fields (enumc, &iter))) {
3243 MonoTypeEnum def_type;
3245 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3247 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3249 if (mono_field_is_deleted (field))
3251 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3253 p = mono_class_get_field_default_value (field, &def_type);
3254 len = mono_metadata_decode_blob_size (p, &p);
3255 switch (mono_class_enum_basetype (enumc)->type) {
3258 mono_array_set (info->values, gchar, j, *p);
3260 case MONO_TYPE_CHAR:
3263 mono_array_set (info->values, gint16, j, read16 (p));
3267 mono_array_set (info->values, gint32, j, read32 (p));
3271 mono_array_set (info->values, gint64, j, read64 (p));
3274 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3281 BFLAGS_IgnoreCase = 1,
3282 BFLAGS_DeclaredOnly = 2,
3283 BFLAGS_Instance = 4,
3285 BFLAGS_Public = 0x10,
3286 BFLAGS_NonPublic = 0x20,
3287 BFLAGS_FlattenHierarchy = 0x40,
3288 BFLAGS_InvokeMethod = 0x100,
3289 BFLAGS_CreateInstance = 0x200,
3290 BFLAGS_GetField = 0x400,
3291 BFLAGS_SetField = 0x800,
3292 BFLAGS_GetProperty = 0x1000,
3293 BFLAGS_SetProperty = 0x2000,
3294 BFLAGS_ExactBinding = 0x10000,
3295 BFLAGS_SuppressChangeType = 0x20000,
3296 BFLAGS_OptionalParamBinding = 0x40000
3299 static MonoReflectionField *
3300 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3303 MonoClass *startklass, *klass;
3305 MonoClassField *field;
3308 int (*compare_func) (const char *s1, const char *s2) = NULL;
3309 domain = ((MonoObject *)type)->vtable->domain;
3310 klass = startklass = mono_class_from_mono_type (type->type);
3313 mono_raise_exception (mono_get_exception_argument_null ("name"));
3314 if (type->type->byref)
3317 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3320 if (klass->exception_type != MONO_EXCEPTION_NONE)
3321 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3324 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3325 guint32 flags = mono_field_get_flags (field);
3328 if (mono_field_is_deleted_with_flags (field, flags))
3330 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3331 if (bflags & BFLAGS_Public)
3333 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3334 if (bflags & BFLAGS_NonPublic) {
3341 if (flags & FIELD_ATTRIBUTE_STATIC) {
3342 if (bflags & BFLAGS_Static)
3343 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3346 if (bflags & BFLAGS_Instance)
3353 utf8_name = mono_string_to_utf8 (name);
3355 if (compare_func (mono_field_get_name (field), utf8_name)) {
3361 return mono_field_get_object (domain, klass, field);
3363 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3370 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3373 MonoClass *startklass, *klass, *refklass;
3378 MonoClassField *field;
3379 MonoPtrArray tmp_array;
3381 MONO_ARCH_SAVE_REGS;
3383 domain = ((MonoObject *)type)->vtable->domain;
3384 if (type->type->byref)
3385 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3386 klass = startklass = mono_class_from_mono_type (type->type);
3387 refklass = mono_class_from_mono_type (reftype->type);
3389 mono_ptr_array_init (tmp_array, 2);
3392 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3393 mono_ptr_array_destroy (tmp_array);
3394 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3398 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3399 guint32 flags = mono_field_get_flags (field);
3401 if (mono_field_is_deleted_with_flags (field, flags))
3403 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3404 if (bflags & BFLAGS_Public)
3406 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3407 if (bflags & BFLAGS_NonPublic) {
3414 if (flags & FIELD_ATTRIBUTE_STATIC) {
3415 if (bflags & BFLAGS_Static)
3416 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3419 if (bflags & BFLAGS_Instance)
3425 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3426 mono_ptr_array_append (tmp_array, member);
3428 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3431 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3433 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3434 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3436 mono_ptr_array_destroy (tmp_array);
3442 method_nonpublic (MonoMethod* method, gboolean start_klass)
3444 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3445 case METHOD_ATTRIBUTE_ASSEM:
3446 return (start_klass || mono_defaults.generic_ilist_class);
3447 case METHOD_ATTRIBUTE_PRIVATE:
3449 case METHOD_ATTRIBUTE_PUBLIC:
3457 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3459 static MonoClass *MethodInfo_array;
3461 MonoClass *startklass, *klass, *refklass;
3466 int i, len, match, nslots;
3467 /*FIXME, use MonoBitSet*/
3468 guint32 method_slots_default [8];
3469 guint32 *method_slots = NULL;
3470 gchar *mname = NULL;
3471 int (*compare_func) (const char *s1, const char *s2) = NULL;
3472 MonoVTable *array_vtable;
3474 MonoPtrArray tmp_array;
3476 mono_ptr_array_init (tmp_array, 4);
3478 if (!MethodInfo_array) {
3479 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3480 mono_memory_barrier ();
3481 MethodInfo_array = klass;
3484 domain = ((MonoObject *)type)->vtable->domain;
3485 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3486 if (type->type->byref)
3487 return mono_array_new_specific (array_vtable, 0);
3488 klass = startklass = mono_class_from_mono_type (type->type);
3489 refklass = mono_class_from_mono_type (reftype->type);
3493 mname = mono_string_to_utf8 (name);
3494 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3497 /* An optimization for calls made from Delegate:CreateDelegate () */
3498 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3499 method = mono_get_delegate_invoke (klass);
3500 if (mono_loader_get_last_error ())
3503 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3505 res = mono_array_new_specific (array_vtable, 1);
3506 mono_array_setref (res, 0, member);
3511 mono_class_setup_vtable (klass);
3512 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3515 if (is_generic_parameter (type->type))
3516 nslots = mono_class_get_vtable_size (klass->parent);
3518 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3519 if (nslots >= sizeof (method_slots_default) * 8) {
3520 method_slots = g_new0 (guint32, nslots / 32 + 1);
3522 method_slots = method_slots_default;
3523 memset (method_slots, 0, sizeof (method_slots_default));
3526 mono_class_setup_vtable (klass);
3527 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3531 while ((method = mono_class_get_methods (klass, &iter))) {
3533 if (method->slot != -1) {
3534 g_assert (method->slot < nslots);
3535 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3537 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3538 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3541 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3543 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3544 if (bflags & BFLAGS_Public)
3546 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3552 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3553 if (bflags & BFLAGS_Static)
3554 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3557 if (bflags & BFLAGS_Instance)
3565 if (compare_func (mname, method->name))
3571 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3573 mono_ptr_array_append (tmp_array, member);
3575 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3579 if (method_slots != method_slots_default)
3580 g_free (method_slots);
3582 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3584 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3585 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3587 mono_ptr_array_destroy (tmp_array);
3592 if (method_slots != method_slots_default)
3593 g_free (method_slots);
3594 mono_ptr_array_destroy (tmp_array);
3595 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3596 ex = mono_class_get_exception_for_failure (klass);
3598 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3599 mono_loader_clear_error ();
3601 mono_raise_exception (ex);
3606 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3609 static MonoClass *System_Reflection_ConstructorInfo;
3610 MonoClass *startklass, *klass, *refklass;
3615 gpointer iter = NULL;
3616 MonoPtrArray tmp_array;
3618 MONO_ARCH_SAVE_REGS;
3620 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3622 domain = ((MonoObject *)type)->vtable->domain;
3623 if (type->type->byref)
3624 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3625 klass = startklass = mono_class_from_mono_type (type->type);
3626 refklass = mono_class_from_mono_type (reftype->type);
3628 if (!System_Reflection_ConstructorInfo)
3629 System_Reflection_ConstructorInfo = mono_class_from_name (
3630 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3633 while ((method = mono_class_get_methods (klass, &iter))) {
3635 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3637 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3638 if (bflags & BFLAGS_Public)
3641 if (bflags & BFLAGS_NonPublic)
3647 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3648 if (bflags & BFLAGS_Static)
3649 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3652 if (bflags & BFLAGS_Instance)
3658 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3660 mono_ptr_array_append (tmp_array, member);
3663 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3665 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3666 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3668 mono_ptr_array_destroy (tmp_array);
3674 property_hash (gconstpointer data)
3676 MonoProperty *prop = (MonoProperty*)data;
3678 return g_str_hash (prop->name);
3682 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3684 // Properties are hide-by-name-and-signature
3685 if (!g_str_equal (prop1->name, prop2->name))
3688 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3690 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3696 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3701 return method_nonpublic (accessor, start_klass);
3705 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3709 static MonoClass *System_Reflection_PropertyInfo;
3710 MonoClass *startklass, *klass;
3716 gchar *propname = NULL;
3717 int (*compare_func) (const char *s1, const char *s2) = NULL;
3719 GHashTable *properties = NULL;
3720 MonoPtrArray tmp_array;
3722 MONO_ARCH_SAVE_REGS;
3724 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3726 if (!System_Reflection_PropertyInfo)
3727 System_Reflection_PropertyInfo = mono_class_from_name (
3728 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3730 domain = ((MonoObject *)type)->vtable->domain;
3731 if (type->type->byref)
3732 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3733 klass = startklass = mono_class_from_mono_type (type->type);
3736 propname = mono_string_to_utf8 (name);
3737 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3740 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3742 mono_class_setup_vtable (klass);
3743 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3747 while ((prop = mono_class_get_properties (klass, &iter))) {
3753 flags = method->flags;
3756 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3757 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3758 if (bflags & BFLAGS_Public)
3760 } else if (bflags & BFLAGS_NonPublic) {
3761 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3762 property_accessor_nonpublic(prop->set, startklass == klass)) {
3769 if (flags & METHOD_ATTRIBUTE_STATIC) {
3770 if (bflags & BFLAGS_Static)
3771 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3774 if (bflags & BFLAGS_Instance)
3783 if (compare_func (propname, prop->name))
3787 if (g_hash_table_lookup (properties, prop))
3790 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3792 g_hash_table_insert (properties, prop, prop);
3794 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3797 g_hash_table_destroy (properties);
3800 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3801 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3802 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3804 mono_ptr_array_destroy (tmp_array);
3810 g_hash_table_destroy (properties);
3813 mono_ptr_array_destroy (tmp_array);
3815 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3816 ex = mono_class_get_exception_for_failure (klass);
3818 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3819 mono_loader_clear_error ();
3821 mono_raise_exception (ex);
3825 static MonoReflectionEvent *
3826 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3829 MonoClass *klass, *startklass;
3834 int (*compare_func) (const char *s1, const char *s2);
3836 MONO_ARCH_SAVE_REGS;
3838 event_name = mono_string_to_utf8 (name);
3839 if (type->type->byref)
3841 klass = startklass = mono_class_from_mono_type (type->type);
3842 domain = mono_object_domain (type);
3844 mono_class_init_or_throw (klass);
3846 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3848 if (klass->exception_type != MONO_EXCEPTION_NONE)
3849 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3852 while ((event = mono_class_get_events (klass, &iter))) {
3853 if (compare_func (event->name, event_name))
3856 method = event->add;
3858 method = event->remove;
3860 method = event->raise;
3862 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3863 if (!(bflags & BFLAGS_Public))
3866 if (!(bflags & BFLAGS_NonPublic))
3868 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3872 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3873 if (!(bflags & BFLAGS_Static))
3875 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3878 if (!(bflags & BFLAGS_Instance))
3882 if (!(bflags & BFLAGS_NonPublic))
3885 g_free (event_name);
3886 return mono_event_get_object (domain, startklass, event);
3889 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3892 g_free (event_name);
3897 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3901 static MonoClass *System_Reflection_EventInfo;
3902 MonoClass *startklass, *klass;
3909 MonoPtrArray tmp_array;
3911 MONO_ARCH_SAVE_REGS;
3913 mono_ptr_array_init (tmp_array, 4);
3915 if (!System_Reflection_EventInfo)
3916 System_Reflection_EventInfo = mono_class_from_name (
3917 mono_defaults.corlib, "System.Reflection", "EventInfo");
3919 domain = mono_object_domain (type);
3920 if (type->type->byref)
3921 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3922 klass = startklass = mono_class_from_mono_type (type->type);
3925 mono_class_setup_vtable (klass);
3926 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3930 while ((event = mono_class_get_events (klass, &iter))) {
3932 method = event->add;
3934 method = event->remove;
3936 method = event->raise;
3938 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3939 if (bflags & BFLAGS_Public)
3941 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3942 if (bflags & BFLAGS_NonPublic)
3947 if (bflags & BFLAGS_NonPublic)
3953 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3954 if (bflags & BFLAGS_Static)
3955 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3958 if (bflags & BFLAGS_Instance)
3963 if (bflags & BFLAGS_Instance)
3967 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3969 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3972 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3974 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3975 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3977 mono_ptr_array_destroy (tmp_array);
3982 mono_ptr_array_destroy (tmp_array);
3983 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3984 ex = mono_class_get_exception_for_failure (klass);
3986 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3987 mono_loader_clear_error ();
3989 mono_raise_exception (ex);
3993 static MonoReflectionType *
3994 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4002 MONO_ARCH_SAVE_REGS;
4005 mono_raise_exception (mono_get_exception_argument_null ("name"));
4007 domain = ((MonoObject *)type)->vtable->domain;
4008 if (type->type->byref)
4010 klass = mono_class_from_mono_type (type->type);
4012 str = mono_string_to_utf8 (name);
4015 if (klass->exception_type != MONO_EXCEPTION_NONE)
4016 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4019 * If a nested type is generic, return its generic type definition.
4020 * Note that this means that the return value is essentially a
4021 * nested type of the generic type definition of @klass.
4023 * A note in MSDN claims that a generic type definition can have
4024 * nested types that aren't generic. In any case, the container of that
4025 * nested type would be the generic type definition.
4027 if (klass->generic_class)
4028 klass = klass->generic_class->container_class;
4031 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4033 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4034 if (bflags & BFLAGS_Public)
4037 if (bflags & BFLAGS_NonPublic)
4042 if (strcmp (nested->name, str) == 0){
4044 return mono_type_get_object (domain, &nested->byval_arg);
4047 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4054 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4063 MonoPtrArray tmp_array;
4065 MONO_ARCH_SAVE_REGS;
4067 domain = ((MonoObject *)type)->vtable->domain;
4068 if (type->type->byref)
4069 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4070 klass = mono_class_from_mono_type (type->type);
4073 * If a nested type is generic, return its generic type definition.
4074 * Note that this means that the return value is essentially the set
4075 * of nested types of the generic type definition of @klass.
4077 * A note in MSDN claims that a generic type definition can have
4078 * nested types that aren't generic. In any case, the container of that
4079 * nested type would be the generic type definition.
4081 if (klass->generic_class)
4082 klass = klass->generic_class->container_class;
4084 mono_ptr_array_init (tmp_array, 1);
4086 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4088 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4089 if (bflags & BFLAGS_Public)
4092 if (bflags & BFLAGS_NonPublic)
4097 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4098 mono_ptr_array_append (tmp_array, member);
4101 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4103 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4104 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4106 mono_ptr_array_destroy (tmp_array);
4111 static MonoReflectionType*
4112 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4115 MonoType *type = NULL;
4116 MonoTypeNameParse info;
4117 gboolean type_resolve;
4119 MONO_ARCH_SAVE_REGS;
4121 /* On MS.NET, this does not fire a TypeResolve event */
4122 type_resolve = TRUE;
4123 str = mono_string_to_utf8 (name);
4124 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4125 if (!mono_reflection_parse_type (str, &info)) {
4127 mono_reflection_free_type_info (&info);
4128 if (throwOnError) /* uhm: this is a parse error, though... */
4129 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4130 /*g_print ("failed parse\n");*/
4134 if (info.assembly.name) {
4136 mono_reflection_free_type_info (&info);
4138 /* 1.0 and 2.0 throw different exceptions */
4139 if (mono_defaults.generic_ilist_class)
4140 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4142 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4147 if (module != NULL) {
4149 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4154 if (assembly->assembly->dynamic) {
4155 /* Enumerate all modules */
4156 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4160 if (abuilder->modules) {
4161 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4162 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4163 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4169 if (!type && abuilder->loaded_modules) {
4170 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4171 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4172 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4179 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4181 mono_reflection_free_type_info (&info);
4183 MonoException *e = NULL;
4186 e = mono_get_exception_type_load (name, NULL);
4188 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4189 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4191 mono_loader_clear_error ();
4194 mono_raise_exception (e);
4197 } else if (mono_loader_get_last_error ()) {
4199 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4200 mono_loader_clear_error ();
4203 if (type->type == MONO_TYPE_CLASS) {
4204 MonoClass *klass = mono_type_get_class (type);
4206 if (mono_is_security_manager_active () && !klass->exception_type)
4207 /* Some security problems are detected during generic vtable construction */
4208 mono_class_setup_vtable (klass);
4209 /* need to report exceptions ? */
4210 if (throwOnError && klass->exception_type) {
4211 /* report SecurityException (or others) that occured when loading the assembly */
4212 MonoException *exc = mono_class_get_exception_for_failure (klass);
4213 mono_loader_clear_error ();
4214 mono_raise_exception (exc);
4215 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4220 /* g_print ("got it\n"); */
4221 return mono_type_get_object (mono_object_domain (assembly), type);
4225 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4228 gchar *shadow_ini_file;
4231 /* Check for shadow-copied assembly */
4232 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4233 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4235 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4236 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4242 g_free (shadow_ini_file);
4243 if (content != NULL) {
4246 *filename = content;
4254 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4256 MonoDomain *domain = mono_object_domain (assembly);
4257 MonoAssembly *mass = assembly->assembly;
4258 MonoString *res = NULL;
4263 MONO_ARCH_SAVE_REGS;
4265 if (g_path_is_absolute (mass->image->name)) {
4266 absolute = g_strdup (mass->image->name);
4267 dirname = g_path_get_dirname (absolute);
4269 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4270 dirname = g_strdup (mass->basedir);
4273 replace_shadow_path (domain, dirname, &absolute);
4278 for (i = strlen (absolute) - 1; i >= 0; i--)
4279 if (absolute [i] == '\\')
4284 uri = g_filename_to_uri (absolute, NULL, NULL);
4286 const char *prepend = "file://";
4288 if (*absolute == '/' && *(absolute + 1) == '/') {
4291 prepend = "file:///";
4294 uri = g_strconcat (prepend, absolute, NULL);
4298 res = mono_string_new (domain, uri);
4306 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4308 MonoAssembly *mass = assembly->assembly;
4310 MONO_ARCH_SAVE_REGS;
4312 return mass->in_gac;
4315 static MonoReflectionAssembly*
4316 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4320 MonoImageOpenStatus status;
4322 MONO_ARCH_SAVE_REGS;
4324 name = mono_string_to_utf8 (mname);
4325 res = mono_assembly_load_with_partial_name (name, &status);
4331 return mono_assembly_get_object (mono_domain_get (), res);
4335 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4337 MonoDomain *domain = mono_object_domain (assembly);
4340 MONO_ARCH_SAVE_REGS;
4342 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4348 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4350 MONO_ARCH_SAVE_REGS;
4352 return assembly->assembly->ref_only;
4356 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4358 MonoDomain *domain = mono_object_domain (assembly);
4360 MONO_ARCH_SAVE_REGS;
4362 return mono_string_new (domain, assembly->assembly->image->version);
4365 static MonoReflectionMethod*
4366 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4368 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4370 MONO_ARCH_SAVE_REGS;
4374 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4377 static MonoReflectionModule*
4378 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4380 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4384 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4386 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4387 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4391 MONO_ARCH_SAVE_REGS;
4393 for (i = 0; i < table->rows; ++i) {
4394 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4395 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4401 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4403 static MonoClass *System_Version = NULL;
4404 static MonoMethod *create_version = NULL;
4408 if (!System_Version) {
4409 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4410 g_assert (System_Version);
4413 if (!create_version) {
4414 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4415 create_version = mono_method_desc_search_in_class (desc, System_Version);
4416 g_assert (create_version);
4417 mono_method_desc_free (desc);
4423 args [3] = &revision;
4424 result = mono_object_new (domain, System_Version);
4425 mono_runtime_invoke (create_version, result, args, NULL);
4431 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4433 static MonoClass *System_Reflection_AssemblyName;
4435 MonoDomain *domain = mono_object_domain (assembly);
4437 static MonoMethod *create_culture = NULL;
4438 MonoImage *image = assembly->assembly->image;
4441 MONO_ARCH_SAVE_REGS;
4443 if (!System_Reflection_AssemblyName)
4444 System_Reflection_AssemblyName = mono_class_from_name (
4445 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4447 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4450 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4452 if (count > 0 && !create_culture) {
4453 MonoMethodDesc *desc = mono_method_desc_new (
4454 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4455 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4456 g_assert (create_culture);
4457 mono_method_desc_free (desc);
4460 for (i = 0; i < count; i++) {
4461 MonoReflectionAssemblyName *aname;
4462 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4464 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4466 aname = (MonoReflectionAssemblyName *) mono_object_new (
4467 domain, System_Reflection_AssemblyName);
4469 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4471 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4472 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4473 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4474 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4475 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4476 aname->versioncompat = 1; /* SameMachine (default) */
4477 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4478 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4480 if (create_culture) {
4482 MonoBoolean assembly_ref = 1;
4483 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4484 args [1] = &assembly_ref;
4485 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4488 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4489 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4490 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4492 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4493 /* public key token isn't copied - the class library will
4494 automatically generate it from the public key if required */
4495 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4496 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4498 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4499 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4502 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4505 /* note: this function doesn't return the codebase on purpose (i.e. it can
4506 be used under partial trust as path information isn't present). */
4508 mono_array_setref (result, i, aname);
4519 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4521 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4523 mono_array_setref (info->res, info->idx, name);
4528 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4530 MonoImage *img = assembly->assembly->image;
4535 MONO_ARCH_SAVE_REGS;
4537 mono_image_lock (img);
4538 mono_image_init_name_cache (img);
4541 len = g_hash_table_size (img->name_cache);
4542 mono_image_unlock (img);
4544 /*we can't create objects holding the image lock */
4545 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4547 mono_image_lock (img);
4548 /*len might have changed, create a new array*/
4549 if (len != g_hash_table_size (img->name_cache))
4554 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4555 mono_image_unlock (img);
4560 /* move this in some file in mono/util/ */
4562 g_concat_dir_and_file (const char *dir, const char *file)
4564 g_return_val_if_fail (dir != NULL, NULL);
4565 g_return_val_if_fail (file != NULL, NULL);
4568 * If the directory name doesn't have a / on the end, we need
4569 * to add one so we get a proper path to the file
4571 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4572 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4574 return g_strconcat (dir, file, NULL);
4578 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4580 char *n = mono_string_to_utf8 (name);
4581 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4583 guint32 cols [MONO_MANIFEST_SIZE];
4584 guint32 impl, file_idx;
4588 MONO_ARCH_SAVE_REGS;
4590 for (i = 0; i < table->rows; ++i) {
4591 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4592 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4593 if (strcmp (val, n) == 0)
4597 if (i == table->rows)
4600 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4603 * this code should only be called after obtaining the
4604 * ResourceInfo and handling the other cases.
4606 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4607 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4609 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4614 module = assembly->assembly->image;
4616 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4618 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4622 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4624 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4626 guint32 cols [MONO_MANIFEST_SIZE];
4627 guint32 file_cols [MONO_FILE_SIZE];
4631 MONO_ARCH_SAVE_REGS;
4633 n = mono_string_to_utf8 (name);
4634 for (i = 0; i < table->rows; ++i) {
4635 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4636 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4637 if (strcmp (val, n) == 0)
4641 if (i == table->rows)
4644 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4645 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4648 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4649 case MONO_IMPLEMENTATION_FILE:
4650 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4651 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4652 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4653 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4654 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4655 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4658 info->location = RESOURCE_LOCATION_EMBEDDED;
4661 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4662 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4663 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4664 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4665 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4666 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4668 mono_raise_exception (ex);
4670 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4672 /* Obtain info recursively */
4673 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4674 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4677 case MONO_IMPLEMENTATION_EXP_TYPE:
4678 g_assert_not_reached ();
4687 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4689 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4690 MonoArray *result = NULL;
4695 MONO_ARCH_SAVE_REGS;
4697 /* check hash if needed */
4699 n = mono_string_to_utf8 (name);
4700 for (i = 0; i < table->rows; ++i) {
4701 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4702 if (strcmp (val, n) == 0) {
4705 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4706 fn = mono_string_new (mono_object_domain (assembly), n);
4708 return (MonoObject*)fn;
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))
4721 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4724 for (i = 0; i < table->rows; ++i) {
4725 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4726 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4727 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4728 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4733 return (MonoObject*)result;
4737 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4739 MonoDomain *domain = mono_domain_get();
4742 int i, j, file_count = 0;
4743 MonoImage **modules;
4744 guint32 module_count, real_module_count;
4745 MonoTableInfo *table;
4746 guint32 cols [MONO_FILE_SIZE];
4747 MonoImage *image = assembly->assembly->image;
4749 g_assert (image != NULL);
4750 g_assert (!assembly->assembly->dynamic);
4752 table = &image->tables [MONO_TABLE_FILE];
4753 file_count = table->rows;
4755 modules = image->modules;
4756 module_count = image->module_count;
4758 real_module_count = 0;
4759 for (i = 0; i < module_count; ++i)
4761 real_module_count ++;
4763 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4764 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4766 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4768 for (i = 0; i < module_count; ++i)
4770 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4774 for (i = 0; i < file_count; ++i, ++j) {
4775 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4776 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4777 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4779 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4781 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4782 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4784 mono_array_setref (res, j, mono_module_get_object (domain, m));
4791 static MonoReflectionMethod*
4792 ves_icall_GetCurrentMethod (void)
4794 MonoMethod *m = mono_method_get_last_managed ();
4796 while (m->is_inflated)
4797 m = ((MonoMethodInflated*)m)->declaring;
4799 return mono_method_get_object (mono_domain_get (), m, NULL);
4804 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4807 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4808 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4809 //method is inflated, we should inflate it on the other class
4810 MonoGenericContext ctx;
4811 ctx.method_inst = inflated->context.method_inst;
4812 ctx.class_inst = inflated->context.class_inst;
4813 if (klass->generic_class)
4814 ctx.class_inst = klass->generic_class->context.class_inst;
4815 else if (klass->generic_container)
4816 ctx.class_inst = klass->generic_container->context.class_inst;
4817 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4820 mono_class_setup_methods (method->klass);
4821 if (method->klass->exception_type)
4823 for (i = 0; i < method->klass->method.count; ++i) {
4824 if (method->klass->methods [i] == method) {
4829 mono_class_setup_methods (klass);
4830 if (klass->exception_type)
4832 g_assert (offset >= 0 && offset < klass->method.count);
4833 return klass->methods [offset];
4836 static MonoReflectionMethod*
4837 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4841 klass = mono_class_from_mono_type (type);
4842 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4844 if (method->klass != klass) {
4845 method = mono_method_get_equivalent_method (method, klass);
4850 klass = method->klass;
4851 return mono_method_get_object (mono_domain_get (), method, klass);
4854 static MonoReflectionMethod*
4855 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4857 return mono_method_get_object (mono_domain_get (), method, NULL);
4860 static MonoReflectionMethodBody*
4861 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4863 return mono_method_body_get_object (mono_domain_get (), method);
4866 static MonoReflectionAssembly*
4867 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4869 MonoMethod *dest = NULL;
4871 MONO_ARCH_SAVE_REGS;
4873 mono_stack_walk_no_il (get_executing, &dest);
4874 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4878 static MonoReflectionAssembly*
4879 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4881 MonoDomain* domain = mono_domain_get ();
4883 MONO_ARCH_SAVE_REGS;
4885 if (!domain->entry_assembly)
4888 return mono_assembly_get_object (domain, domain->entry_assembly);
4891 static MonoReflectionAssembly*
4892 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4897 MONO_ARCH_SAVE_REGS;
4900 mono_stack_walk_no_il (get_executing, &dest);
4902 mono_stack_walk_no_il (get_caller, &dest);
4905 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4909 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4910 gboolean assembly_qualified)
4912 MonoDomain *domain = mono_object_domain (object);
4913 MonoTypeNameFormat format;
4918 format = assembly_qualified ?
4919 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4920 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4922 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4924 name = mono_type_get_name_full (object->type, format);
4928 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4933 res = mono_string_new (domain, name);
4940 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4942 MonoClass *klass = mono_class_from_mono_type (this->type);
4943 mono_class_init_or_throw (klass);
4944 return mono_security_core_clr_class_level (klass);
4948 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4950 static MonoMethod *create_culture = NULL;
4953 const char *pkey_ptr;
4955 MonoBoolean assembly_ref = 0;
4957 MONO_ARCH_SAVE_REGS;
4959 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4960 aname->major = name->major;
4961 aname->minor = name->minor;
4962 aname->build = name->build;
4963 aname->flags = name->flags;
4964 aname->revision = name->revision;
4965 aname->hashalg = name->hash_alg;
4966 aname->versioncompat = 1; /* SameMachine (default) */
4967 aname->processor_architecture = name->arch;
4969 if (by_default_version)
4970 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4973 if (absolute != NULL && *absolute != '\0') {
4974 const gchar *prepend = "file://";
4977 codebase = g_strdup (absolute);
4982 for (i = strlen (codebase) - 1; i >= 0; i--)
4983 if (codebase [i] == '\\')
4986 if (*codebase == '/' && *(codebase + 1) == '/') {
4989 prepend = "file:///";
4993 result = g_strconcat (prepend, codebase, NULL);
4999 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5003 if (!create_culture) {
5004 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5005 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5006 g_assert (create_culture);
5007 mono_method_desc_free (desc);
5010 if (name->culture) {
5011 args [0] = mono_string_new (domain, name->culture);
5012 args [1] = &assembly_ref;
5013 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5016 if (name->public_key) {
5017 pkey_ptr = (char*)name->public_key;
5018 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5020 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5021 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5022 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5023 } else if (default_publickey) {
5024 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5025 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5028 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5029 if (name->public_key_token [0]) {
5033 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5034 p = mono_array_addr (aname->keyToken, char, 0);
5036 for (i = 0, j = 0; i < 8; i++) {
5037 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5038 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5041 } else if (default_token) {
5042 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5047 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5049 MonoDomain *domain = mono_object_domain (assembly);
5050 MonoAssembly *mass = assembly->assembly;
5054 name = mono_stringify_assembly_name (&mass->aname);
5055 res = mono_string_new (domain, name);
5062 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5065 MonoAssembly *mass = assembly->assembly;
5067 MONO_ARCH_SAVE_REGS;
5069 if (g_path_is_absolute (mass->image->name)) {
5070 fill_reflection_assembly_name (mono_object_domain (assembly),
5071 aname, &mass->aname, mass->image->name, TRUE,
5075 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5077 fill_reflection_assembly_name (mono_object_domain (assembly),
5078 aname, &mass->aname, absolute, TRUE, TRUE,
5085 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5088 MonoImageOpenStatus status = MONO_IMAGE_OK;
5091 MonoAssemblyName name;
5094 MONO_ARCH_SAVE_REGS;
5096 filename = mono_string_to_utf8 (fname);
5098 dirname = g_path_get_dirname (filename);
5099 replace_shadow_path (mono_domain_get (), dirname, &filename);
5102 image = mono_image_open (filename, &status);
5108 if (status == MONO_IMAGE_IMAGE_INVALID)
5109 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5111 exc = mono_get_exception_file_not_found2 (NULL, fname);
5112 mono_raise_exception (exc);
5115 res = mono_assembly_fill_assembly_name (image, &name);
5117 mono_image_close (image);
5119 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5122 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5126 mono_image_close (image);
5130 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5131 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5133 MonoBoolean result = FALSE;
5134 MonoDeclSecurityEntry entry;
5136 /* SecurityAction.RequestMinimum */
5137 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5138 *minimum = entry.blob;
5139 *minLength = entry.size;
5142 /* SecurityAction.RequestOptional */
5143 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5144 *optional = entry.blob;
5145 *optLength = entry.size;
5148 /* SecurityAction.RequestRefuse */
5149 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5150 *refused = entry.blob;
5151 *refLength = entry.size;
5159 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5163 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5165 guint32 attrs, visibility;
5167 /* we start the count from 1 because we skip the special type <Module> */
5170 for (i = 1; i < tdef->rows; ++i) {
5171 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5172 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5173 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5177 count = tdef->rows - 1;
5179 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5180 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5182 for (i = 1; i < tdef->rows; ++i) {
5183 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5184 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5185 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5186 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5188 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5190 MonoLoaderError *error;
5193 error = mono_loader_get_last_error ();
5194 g_assert (error != NULL);
5196 ex = mono_loader_error_prepare_exception (error);
5197 mono_array_setref (*exceptions, count, ex);
5199 if (mono_loader_get_last_error ())
5200 mono_loader_clear_error ();
5209 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5211 MonoArray *res = NULL;
5212 MonoArray *exceptions = NULL;
5213 MonoImage *image = NULL;
5214 MonoTableInfo *table = NULL;
5217 int i, len, ex_count;
5219 MONO_ARCH_SAVE_REGS;
5221 domain = mono_object_domain (assembly);
5223 g_assert (!assembly->assembly->dynamic);
5224 image = assembly->assembly->image;
5225 table = &image->tables [MONO_TABLE_FILE];
5226 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5228 /* Append data from all modules in the assembly */
5229 for (i = 0; i < table->rows; ++i) {
5230 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5231 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5234 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5235 /* Append the new types to the end of the array */
5236 if (mono_array_length (res2) > 0) {
5238 MonoArray *res3, *ex3;
5240 len1 = mono_array_length (res);
5241 len2 = mono_array_length (res2);
5243 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5244 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5245 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5248 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5249 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5250 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5257 /* the ReflectionTypeLoadException must have all the types (Types property),
5258 * NULL replacing types which throws an exception. The LoaderException must
5259 * contain all exceptions for NULL items.
5262 len = mono_array_length (res);
5265 for (i = 0; i < len; i++) {
5266 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5270 klass = mono_type_get_class (t->type);
5271 if ((klass != NULL) && klass->exception_type) {
5272 /* keep the class in the list */
5273 list = g_list_append (list, klass);
5274 /* and replace Type with NULL */
5275 mono_array_setref (res, i, NULL);
5282 if (list || ex_count) {
5284 MonoException *exc = NULL;
5285 MonoArray *exl = NULL;
5286 int j, length = g_list_length (list) + ex_count;
5288 mono_loader_clear_error ();
5290 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5291 /* Types for which mono_class_get () succeeded */
5292 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5293 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5294 mono_array_setref (exl, i, exc);
5296 /* Types for which it don't */
5297 for (j = 0; j < mono_array_length (exceptions); ++j) {
5298 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5300 g_assert (i < length);
5301 mono_array_setref (exl, i, exc);
5308 exc = mono_get_exception_reflection_type_load (res, exl);
5309 mono_loader_clear_error ();
5310 mono_raise_exception (exc);
5317 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5319 MonoAssemblyName aname;
5320 MonoDomain *domain = mono_object_domain (name);
5322 gboolean is_version_defined;
5323 gboolean is_token_defined;
5325 aname.public_key = NULL;
5326 val = mono_string_to_utf8 (assname);
5327 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5328 g_free ((guint8*) aname.public_key);
5333 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5334 FALSE, is_token_defined);
5336 mono_assembly_name_free (&aname);
5337 g_free ((guint8*) aname.public_key);
5343 static MonoReflectionType*
5344 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5346 MonoDomain *domain = mono_object_domain (module);
5349 MONO_ARCH_SAVE_REGS;
5351 g_assert (module->image);
5353 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5354 /* These images do not have a global type */
5357 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5358 return mono_type_get_object (domain, &klass->byval_arg);
5362 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5364 /*if (module->image)
5365 mono_image_close (module->image);*/
5369 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5371 MonoDomain *domain = mono_object_domain (module);
5373 MONO_ARCH_SAVE_REGS;
5375 g_assert (module->image);
5376 return mono_string_new (domain, module->image->guid);
5380 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5383 if (module->image && module->image->is_module_handle)
5384 return module->image->raw_data;
5387 return (gpointer) (-1);
5391 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5393 if (image->dynamic) {
5394 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5395 *pe_kind = dyn->pe_kind;
5396 *machine = dyn->machine;
5399 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5400 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5405 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5407 return (image->md_version_major << 16) | (image->md_version_minor);
5411 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5413 MonoArray *exceptions;
5416 MONO_ARCH_SAVE_REGS;
5419 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5421 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5422 for (i = 0; i < mono_array_length (exceptions); ++i) {
5423 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5425 mono_raise_exception (ex);
5432 mono_memberref_is_method (MonoImage *image, guint32 token)
5434 if (!image->dynamic) {
5435 guint32 cols [MONO_MEMBERREF_SIZE];
5437 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5438 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5439 mono_metadata_decode_blob_size (sig, &sig);
5440 return (*sig != 0x6);
5442 MonoClass *handle_class;
5444 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5447 return mono_defaults.methodhandle_class == handle_class;
5452 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5455 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5456 mono_array_addr (type_args, MonoType*, 0));
5458 context->class_inst = NULL;
5460 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5461 mono_array_addr (method_args, MonoType*, 0));
5463 context->method_inst = NULL;
5467 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5470 int table = mono_metadata_token_table (token);
5471 int index = mono_metadata_token_index (token);
5472 MonoGenericContext context;
5474 *error = ResolveTokenError_Other;
5476 /* Validate token */
5477 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5478 (table != MONO_TABLE_TYPESPEC)) {
5479 *error = ResolveTokenError_BadTable;
5483 if (image->dynamic) {
5484 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5485 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5486 return klass ? &klass->byval_arg : NULL;
5489 init_generic_context_from_args (&context, type_args, method_args);
5490 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5491 return klass ? &klass->byval_arg : NULL;
5494 if ((index <= 0) || (index > image->tables [table].rows)) {
5495 *error = ResolveTokenError_OutOfRange;
5499 init_generic_context_from_args (&context, type_args, method_args);
5500 klass = mono_class_get_full (image, token, &context);
5502 if (mono_loader_get_last_error ())
5503 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5506 return &klass->byval_arg;
5512 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5514 int table = mono_metadata_token_table (token);
5515 int index = mono_metadata_token_index (token);
5516 MonoGenericContext context;
5519 *error = ResolveTokenError_Other;
5521 /* Validate token */
5522 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5523 (table != MONO_TABLE_MEMBERREF)) {
5524 *error = ResolveTokenError_BadTable;
5528 if (image->dynamic) {
5529 if (table == MONO_TABLE_METHOD)
5530 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5532 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5533 *error = ResolveTokenError_BadTable;
5537 init_generic_context_from_args (&context, type_args, method_args);
5538 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5541 if ((index <= 0) || (index > image->tables [table].rows)) {
5542 *error = ResolveTokenError_OutOfRange;
5545 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5546 *error = ResolveTokenError_BadTable;
5550 init_generic_context_from_args (&context, type_args, method_args);
5551 method = mono_get_method_full (image, token, NULL, &context);
5553 if (mono_loader_get_last_error ())
5554 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5560 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5562 int index = mono_metadata_token_index (token);
5564 *error = ResolveTokenError_Other;
5566 /* Validate token */
5567 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5568 *error = ResolveTokenError_BadTable;
5573 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5575 if ((index <= 0) || (index >= image->heap_us.size)) {
5576 *error = ResolveTokenError_OutOfRange;
5580 /* FIXME: What to do if the index points into the middle of a string ? */
5582 return mono_ldstr (mono_domain_get (), image, index);
5585 static MonoClassField*
5586 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5589 int table = mono_metadata_token_table (token);
5590 int index = mono_metadata_token_index (token);
5591 MonoGenericContext context;
5592 MonoClassField *field;
5594 *error = ResolveTokenError_Other;
5596 /* Validate token */
5597 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5598 *error = ResolveTokenError_BadTable;
5602 if (image->dynamic) {
5603 if (table == MONO_TABLE_FIELD)
5604 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5606 if (mono_memberref_is_method (image, token)) {
5607 *error = ResolveTokenError_BadTable;
5611 init_generic_context_from_args (&context, type_args, method_args);
5612 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5615 if ((index <= 0) || (index > image->tables [table].rows)) {
5616 *error = ResolveTokenError_OutOfRange;
5619 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5620 *error = ResolveTokenError_BadTable;
5624 init_generic_context_from_args (&context, type_args, method_args);
5625 field = mono_field_from_token (image, token, &klass, &context);
5627 if (mono_loader_get_last_error ())
5628 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5635 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5637 int table = mono_metadata_token_table (token);
5639 *error = ResolveTokenError_Other;
5642 case MONO_TABLE_TYPEDEF:
5643 case MONO_TABLE_TYPEREF:
5644 case MONO_TABLE_TYPESPEC: {
5645 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5647 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5651 case MONO_TABLE_METHOD:
5652 case MONO_TABLE_METHODSPEC: {
5653 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5655 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5659 case MONO_TABLE_FIELD: {
5660 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5662 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5666 case MONO_TABLE_MEMBERREF:
5667 if (mono_memberref_is_method (image, token)) {
5668 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5670 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5675 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5677 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5684 *error = ResolveTokenError_BadTable;
5691 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5693 int table = mono_metadata_token_table (token);
5694 int idx = mono_metadata_token_index (token);
5695 MonoTableInfo *tables = image->tables;
5700 *error = ResolveTokenError_OutOfRange;
5702 /* FIXME: Support other tables ? */
5703 if (table != MONO_TABLE_STANDALONESIG)
5709 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5712 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5714 ptr = mono_metadata_blob_heap (image, sig);
5715 len = mono_metadata_decode_blob_size (ptr, &ptr);
5717 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5718 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5722 static MonoReflectionType*
5723 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5726 int isbyref = 0, rank;
5727 char *str = mono_string_to_utf8 (smodifiers);
5730 MONO_ARCH_SAVE_REGS;
5732 klass = mono_class_from_mono_type (tb->type.type);
5734 /* logic taken from mono_reflection_parse_type(): keep in sync */
5738 if (isbyref) { /* only one level allowed by the spec */
5745 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5748 klass = mono_ptr_class_get (&klass->byval_arg);
5749 mono_class_init (klass);
5760 else if (*p != '*') { /* '*' means unknown lower bound */
5771 klass = mono_array_class_get (klass, rank);
5772 mono_class_init (klass);
5779 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5783 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5788 MONO_ARCH_SAVE_REGS;
5791 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5797 check_for_invalid_type (MonoClass *klass)
5801 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5804 name = mono_type_get_full_name (klass);
5805 str = mono_string_new (mono_domain_get (), name);
5807 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5810 static MonoReflectionType *
5811 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5813 MonoClass *klass, *aklass;
5815 MONO_ARCH_SAVE_REGS;
5817 klass = mono_class_from_mono_type (type->type);
5818 check_for_invalid_type (klass);
5820 if (rank == 0) //single dimentional array
5821 aklass = mono_array_class_get (klass, 1);
5823 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5825 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5828 static MonoReflectionType *
5829 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5833 MONO_ARCH_SAVE_REGS;
5835 klass = mono_class_from_mono_type (type->type);
5836 mono_class_init_or_throw (klass);
5837 check_for_invalid_type (klass);
5839 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5842 static MonoReflectionType *
5843 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5845 MonoClass *klass, *pklass;
5847 klass = mono_class_from_mono_type (type->type);
5848 mono_class_init_or_throw (klass);
5849 check_for_invalid_type (klass);
5851 pklass = mono_ptr_class_get (type->type);
5853 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5857 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5858 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5860 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5861 MonoObject *delegate;
5863 MonoMethod *method = info->method;
5865 MONO_ARCH_SAVE_REGS;
5867 mono_class_init_or_throw (delegate_class);
5869 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5871 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5872 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5876 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5878 if (method->dynamic) {
5879 /* Creating a trampoline would leak memory */
5880 func = mono_compile_method (method);
5882 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5883 method = mono_object_get_virtual_method (target, method);
5884 func = mono_create_ftnptr (mono_domain_get (),
5885 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5888 mono_delegate_ctor_with_method (delegate, target, func, method);
5894 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5896 /* Reset the invoke impl to the default one */
5897 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5901 * Magic number to convert a time which is relative to
5902 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5904 #define EPOCH_ADJUST ((guint64)62135596800LL)
5907 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5909 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5912 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5914 convert_to_absolute_date(SYSTEMTIME *date)
5916 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5917 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5918 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5919 /* from the calendar FAQ */
5920 int a = (14 - date->wMonth) / 12;
5921 int y = date->wYear - a;
5922 int m = date->wMonth + 12 * a - 2;
5923 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5925 /* d is now the day of the week for the first of the month (0 == Sunday) */
5927 int day_of_week = date->wDayOfWeek;
5929 /* set day_in_month to the first day in the month which falls on day_of_week */
5930 int day_in_month = 1 + (day_of_week - d);
5931 if (day_in_month <= 0)
5934 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5935 date->wDay = day_in_month + (date->wDay - 1) * 7;
5936 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5943 * Return's the offset from GMT of a local time.
5945 * tm is a local time
5946 * t is the same local time as seconds.
5949 gmt_offset(struct tm *tm, time_t t)
5951 #if defined (HAVE_TM_GMTOFF)
5952 return tm->tm_gmtoff;
5957 g.tm_isdst = tm->tm_isdst;
5959 return (int)difftime(t, t2);
5964 * This is heavily based on zdump.c from glibc 2.2.
5966 * * data[0]: start of daylight saving time (in DateTime ticks).
5967 * * data[1]: end of daylight saving time (in DateTime ticks).
5968 * * data[2]: utcoffset (in TimeSpan ticks).
5969 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5970 * * name[0]: name of this timezone when not daylight saving.
5971 * * name[1]: name of this timezone when daylight saving.
5973 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5974 * the class library allows years between 1 and 9999.
5976 * Returns true on success and zero on failure.
5979 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5982 MonoDomain *domain = mono_domain_get ();
5983 struct tm start, tt;
5987 int is_daylight = 0, day;
5990 MONO_ARCH_SAVE_REGS;
5992 MONO_CHECK_ARG_NULL (data);
5993 MONO_CHECK_ARG_NULL (names);
5995 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5996 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5999 * no info is better than crashing: we'll need our own tz data
6000 * to make this work properly, anyway. The range is probably
6001 * reduced to 1970 .. 2037 because that is what mktime is
6002 * guaranteed to support (we get into an infinite loop
6006 memset (&start, 0, sizeof (start));
6009 start.tm_year = year-1900;
6011 t = mktime (&start);
6013 if ((year < 1970) || (year > 2037) || (t == -1)) {
6015 tt = *localtime (&t);
6016 strftime (tzone, sizeof (tzone), "%Z", &tt);
6017 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6018 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6022 gmtoff = gmt_offset (&start, t);
6024 /* For each day of the year, calculate the tm_gmtoff. */
6025 for (day = 0; day < 365; day++) {
6028 tt = *localtime (&t);
6030 /* Daylight saving starts or ends here. */
6031 if (gmt_offset (&tt, t) != gmtoff) {
6035 /* Try to find the exact hour when daylight saving starts/ends. */
6039 tt1 = *localtime (&t1);
6040 } while (gmt_offset (&tt1, t1) != gmtoff);
6042 /* Try to find the exact minute when daylight saving starts/ends. */
6045 tt1 = *localtime (&t1);
6046 } while (gmt_offset (&tt1, t1) == gmtoff);
6048 strftime (tzone, sizeof (tzone), "%Z", &tt);
6050 /* Write data, if we're already in daylight saving, we're done. */
6052 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6053 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6056 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6057 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6061 /* This is only set once when we enter daylight saving. */
6062 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6063 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6065 gmtoff = gmt_offset (&tt, t);
6070 strftime (tzone, sizeof (tzone), "%Z", &tt);
6071 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6072 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6073 mono_array_set ((*data), gint64, 0, 0);
6074 mono_array_set ((*data), gint64, 1, 0);
6075 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6076 mono_array_set ((*data), gint64, 3, 0);
6081 MonoDomain *domain = mono_domain_get ();
6082 TIME_ZONE_INFORMATION tz_info;
6087 tz_id = GetTimeZoneInformation (&tz_info);
6088 if (tz_id == TIME_ZONE_ID_INVALID)
6091 MONO_CHECK_ARG_NULL (data);
6092 MONO_CHECK_ARG_NULL (names);
6094 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6095 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6097 for (i = 0; i < 32; ++i)
6098 if (!tz_info.DaylightName [i])
6100 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6101 for (i = 0; i < 32; ++i)
6102 if (!tz_info.StandardName [i])
6104 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6106 if ((year <= 1601) || (year > 30827)) {
6108 * According to MSDN, the MS time functions can't handle dates outside
6114 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6115 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6116 tz_info.StandardDate.wYear = year;
6117 convert_to_absolute_date(&tz_info.StandardDate);
6118 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6123 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6124 tz_info.DaylightDate.wYear = year;
6125 convert_to_absolute_date(&tz_info.DaylightDate);
6126 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6131 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6133 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6134 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6141 ves_icall_System_Object_obj_address (MonoObject *this)
6143 MONO_ARCH_SAVE_REGS;
6150 static inline gint32
6151 mono_array_get_byte_length (MonoArray *array)
6157 klass = array->obj.vtable->klass;
6159 if (array->bounds == NULL)
6160 length = array->max_length;
6163 for (i = 0; i < klass->rank; ++ i)
6164 length *= array->bounds [i].length;
6167 switch (klass->element_class->byval_arg.type) {
6170 case MONO_TYPE_BOOLEAN:
6174 case MONO_TYPE_CHAR:
6182 return length * sizeof (gpointer);
6193 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6195 MONO_ARCH_SAVE_REGS;
6197 return mono_array_get_byte_length (array);
6201 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6203 MONO_ARCH_SAVE_REGS;
6205 return mono_array_get (array, gint8, idx);
6209 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6211 MONO_ARCH_SAVE_REGS;
6213 mono_array_set (array, gint8, idx, value);
6217 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6219 guint8 *src_buf, *dest_buf;
6221 MONO_ARCH_SAVE_REGS;
6223 /* watch out for integer overflow */
6224 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6227 src_buf = (guint8 *)src->vector + src_offset;
6228 dest_buf = (guint8 *)dest->vector + dest_offset;
6231 memcpy (dest_buf, src_buf, count);
6233 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6239 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6241 MonoDomain *domain = mono_object_domain (this);
6243 MonoRealProxy *rp = ((MonoRealProxy *)this);
6244 MonoTransparentProxy *tp;
6248 MONO_ARCH_SAVE_REGS;
6250 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6251 tp = (MonoTransparentProxy*) res;
6253 MONO_OBJECT_SETREF (tp, rp, rp);
6254 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6255 klass = mono_class_from_mono_type (type);
6257 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6258 tp->remote_class = mono_remote_class (domain, class_name, klass);
6260 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6264 static MonoReflectionType *
6265 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6267 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6270 /* System.Environment */
6273 ves_icall_System_Environment_get_UserName (void)
6275 MONO_ARCH_SAVE_REGS;
6277 /* using glib is more portable */
6278 return mono_string_new (mono_domain_get (), g_get_user_name ());
6283 ves_icall_System_Environment_get_MachineName (void)
6285 #if defined (HOST_WIN32)
6290 len = MAX_COMPUTERNAME_LENGTH + 1;
6291 buf = g_new (gunichar2, len);
6294 if (GetComputerName (buf, (PDWORD) &len))
6295 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6299 #elif !defined(DISABLE_SOCKETS)
6303 if (gethostname (buf, sizeof (buf)) == 0)
6304 result = mono_string_new (mono_domain_get (), buf);
6310 return mono_string_new (mono_domain_get (), "mono");
6315 ves_icall_System_Environment_get_Platform (void)
6317 #if defined (TARGET_WIN32)
6320 #elif defined(__MACH__)
6323 // Notice that the value is hidden from user code, and only exposed
6324 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6325 // define and making assumptions based on Unix/128/4 values before there
6326 // was a MacOS define. Lots of code would assume that not-Unix meant
6327 // Windows, but in this case, it would be OSX.
6337 ves_icall_System_Environment_get_NewLine (void)
6339 MONO_ARCH_SAVE_REGS;
6341 #if defined (HOST_WIN32)
6342 return mono_string_new (mono_domain_get (), "\r\n");
6344 return mono_string_new (mono_domain_get (), "\n");
6349 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6354 MONO_ARCH_SAVE_REGS;
6359 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6360 value = g_getenv (utf8_name);
6367 return mono_string_new (mono_domain_get (), value);
6371 * There is no standard way to get at environ.
6374 #ifndef __MINGW32_VERSION
6375 #if defined(__APPLE__) && !defined (__arm__)
6376 /* Apple defines this in crt_externs.h but doesn't provide that header for
6377 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6378 * in fact exist on all implementations (so far)
6380 gchar ***_NSGetEnviron(void);
6381 #define environ (*_NSGetEnviron())
6390 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6401 env_strings = GetEnvironmentStrings();
6404 env_string = env_strings;
6405 while (*env_string != '\0') {
6406 /* weird case that MS seems to skip */
6407 if (*env_string != '=')
6409 while (*env_string != '\0')
6415 domain = mono_domain_get ();
6416 names = mono_array_new (domain, mono_defaults.string_class, n);
6420 env_string = env_strings;
6421 while (*env_string != '\0') {
6422 /* weird case that MS seems to skip */
6423 if (*env_string != '=') {
6424 equal_str = wcschr(env_string, '=');
6425 g_assert(equal_str);
6426 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6427 mono_array_setref (names, n, str);
6430 while (*env_string != '\0')
6435 FreeEnvironmentStrings (env_strings);
6447 MONO_ARCH_SAVE_REGS;
6450 for (e = environ; *e != 0; ++ e)
6453 domain = mono_domain_get ();
6454 names = mono_array_new (domain, mono_defaults.string_class, n);
6457 for (e = environ; *e != 0; ++ e) {
6458 parts = g_strsplit (*e, "=", 2);
6460 str = mono_string_new (domain, *parts);
6461 mono_array_setref (names, n, str);
6474 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6476 #if !GLIB_CHECK_VERSION(2,4,0)
6477 #define g_setenv(a,b,c) setenv(a,b,c)
6478 #define g_unsetenv(a) unsetenv(a)
6482 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6487 gunichar2 *utf16_name, *utf16_value;
6489 gchar *utf8_name, *utf8_value;
6492 MONO_ARCH_SAVE_REGS;
6495 utf16_name = mono_string_to_utf16 (name);
6496 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6497 SetEnvironmentVariable (utf16_name, NULL);
6498 g_free (utf16_name);
6502 utf16_value = mono_string_to_utf16 (value);
6504 SetEnvironmentVariable (utf16_name, utf16_value);
6506 g_free (utf16_name);
6507 g_free (utf16_value);
6509 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6511 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6512 g_unsetenv (utf8_name);
6517 utf8_value = mono_string_to_utf8_checked (value, &error);
6518 if (!mono_error_ok (&error)) {
6520 mono_error_raise_exception (&error);
6522 g_setenv (utf8_name, utf8_value, TRUE);
6525 g_free (utf8_value);
6530 ves_icall_System_Environment_Exit (int result)
6532 MONO_ARCH_SAVE_REGS;
6534 mono_threads_set_shutting_down ();
6536 mono_runtime_set_shutting_down ();
6538 /* This will kill the tp threads which cannot be suspended */
6539 mono_thread_pool_cleanup ();
6541 /* Suspend all managed threads since the runtime is going away */
6542 mono_thread_suspend_all_other_threads ();
6544 mono_runtime_quit ();
6546 /* we may need to do some cleanup here... */
6551 ves_icall_System_Environment_GetGacPath (void)
6553 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6557 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6559 #if defined (HOST_WIN32)
6560 #ifndef CSIDL_FLAG_CREATE
6561 #define CSIDL_FLAG_CREATE 0x8000
6564 WCHAR path [MAX_PATH];
6565 /* Create directory if no existing */
6566 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6570 return mono_string_new_utf16 (mono_domain_get (), path, len);
6573 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6575 return mono_string_new (mono_domain_get (), "");
6579 ves_icall_System_Environment_GetLogicalDrives (void)
6581 gunichar2 buf [256], *ptr, *dname;
6583 guint initial_size = 127, size = 128;
6586 MonoString *drivestr;
6587 MonoDomain *domain = mono_domain_get ();
6590 MONO_ARCH_SAVE_REGS;
6595 while (size > initial_size) {
6596 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6597 if (size > initial_size) {
6600 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6601 initial_size = size;
6615 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6620 while (*u16) { u16++; len ++; }
6621 drivestr = mono_string_new_utf16 (domain, dname, len);
6622 mono_array_setref (result, ndrives++, drivestr);
6633 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6635 gunichar2 volume_name [MAX_PATH + 1];
6637 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6639 return mono_string_from_utf16 (volume_name);
6643 ves_icall_System_Environment_InternalGetHome (void)
6645 MONO_ARCH_SAVE_REGS;
6647 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6650 static const char *encodings [] = {
6652 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6653 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6654 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6656 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6657 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6658 "x_unicode_2_0_utf_7",
6660 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6661 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6663 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6666 "unicodefffe", "utf_16be",
6673 * Returns the internal codepage, if the value of "int_code_page" is
6674 * 1 at entry, and we can not compute a suitable code page number,
6675 * returns the code page as a string
6678 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6683 char *codepage = NULL;
6685 int want_name = *int_code_page;
6688 *int_code_page = -1;
6689 MONO_ARCH_SAVE_REGS;
6691 g_get_charset (&cset);
6692 c = codepage = strdup (cset);
6693 for (c = codepage; *c; c++){
6694 if (isascii (*c) && isalpha (*c))
6699 /* g_print ("charset: %s\n", cset); */
6701 /* handle some common aliases */
6704 for (i = 0; p != 0; ){
6705 if ((gssize) p < 7){
6707 p = encodings [++i];
6710 if (strcmp (p, codepage) == 0){
6711 *int_code_page = code;
6714 p = encodings [++i];
6717 if (strstr (codepage, "utf_8") != NULL)
6718 *int_code_page |= 0x10000000;
6721 if (want_name && *int_code_page == -1)
6722 return mono_string_new (mono_domain_get (), cset);
6728 ves_icall_System_Environment_get_HasShutdownStarted (void)
6730 if (mono_runtime_is_shutting_down ())
6733 if (mono_domain_is_unloading (mono_domain_get ()))
6740 ves_icall_System_Environment_BroadcastSettingChange (void)
6743 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6748 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6749 MonoReflectionMethod *method,
6750 MonoArray *out_args)
6752 MONO_ARCH_SAVE_REGS;
6754 mono_message_init (mono_object_domain (this), this, method, out_args);
6758 ves_icall_IsTransparentProxy (MonoObject *proxy)
6760 MONO_ARCH_SAVE_REGS;
6765 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6771 static MonoReflectionMethod *
6772 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6773 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6777 MonoMethod **vtable;
6778 MonoMethod *res = NULL;
6780 MONO_CHECK_ARG_NULL (rtype);
6781 MONO_CHECK_ARG_NULL (rmethod);
6783 method = rmethod->method;
6784 klass = mono_class_from_mono_type (rtype->type);
6785 mono_class_init_or_throw (klass);
6787 if (MONO_CLASS_IS_INTERFACE (klass))
6790 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6793 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6794 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6800 mono_class_setup_vtable (klass);
6801 vtable = klass->vtable;
6803 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6804 gboolean variance_used = FALSE;
6805 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6806 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6808 res = vtable [offs + method->slot];
6810 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6813 if (method->slot != -1)
6814 res = vtable [method->slot];
6820 return mono_method_get_object (mono_domain_get (), res, NULL);
6824 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6829 MONO_ARCH_SAVE_REGS;
6831 klass = mono_class_from_mono_type (type->type);
6832 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6834 if (enable) vtable->remote = 1;
6835 else vtable->remote = 0;
6839 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6844 MONO_ARCH_SAVE_REGS;
6846 domain = mono_object_domain (type);
6847 klass = mono_class_from_mono_type (type->type);
6848 mono_class_init_or_throw (klass);
6850 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6851 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6853 if (klass->rank >= 1) {
6854 g_assert (klass->rank == 1);
6855 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6857 /* Bypass remoting object creation check */
6858 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6863 ves_icall_System_IO_get_temp_path (void)
6865 MONO_ARCH_SAVE_REGS;
6867 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6870 #ifndef PLATFORM_NO_DRIVEINFO
6872 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6873 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6877 ULARGE_INTEGER wapi_free_bytes_avail;
6878 ULARGE_INTEGER wapi_total_number_of_bytes;
6879 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6881 MONO_ARCH_SAVE_REGS;
6883 *error = ERROR_SUCCESS;
6884 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6885 &wapi_total_number_of_free_bytes);
6888 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6889 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6890 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6892 *free_bytes_avail = 0;
6893 *total_number_of_bytes = 0;
6894 *total_number_of_free_bytes = 0;
6895 *error = GetLastError ();
6902 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6904 MONO_ARCH_SAVE_REGS;
6906 return GetDriveType (mono_string_chars (root_path_name));
6911 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6913 MONO_ARCH_SAVE_REGS;
6915 return mono_compile_method (method);
6919 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6924 MONO_ARCH_SAVE_REGS;
6926 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6928 #if defined (HOST_WIN32)
6929 /* Avoid mixing '/' and '\\' */
6932 for (i = strlen (path) - 1; i >= 0; i--)
6933 if (path [i] == '/')
6937 mcpath = mono_string_new (mono_domain_get (), path);
6944 get_bundled_app_config (void)
6946 const gchar *app_config;
6949 gchar *config_file_name, *config_file_path;
6953 MONO_ARCH_SAVE_REGS;
6955 domain = mono_domain_get ();
6956 file = domain->setup->configuration_file;
6960 // Retrieve config file and remove the extension
6961 config_file_name = mono_string_to_utf8 (file);
6962 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6963 if (!config_file_path)
6964 config_file_path = config_file_name;
6965 len = strlen (config_file_path) - strlen (".config");
6966 module = g_malloc0 (len + 1);
6967 memcpy (module, config_file_path, len);
6968 // Get the config file from the module name
6969 app_config = mono_config_string_for_assembly_file (module);
6972 if (config_file_name != config_file_path)
6973 g_free (config_file_name);
6974 g_free (config_file_path);
6979 return mono_string_new (mono_domain_get (), app_config);
6983 get_bundled_machine_config (void)
6985 const gchar *machine_config;
6987 MONO_ARCH_SAVE_REGS;
6989 machine_config = mono_get_machine_config ();
6991 if (!machine_config)
6994 return mono_string_new (mono_domain_get (), machine_config);
6998 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7003 MONO_ARCH_SAVE_REGS;
7005 path = g_path_get_dirname (mono_get_config_dir ());
7007 #if defined (HOST_WIN32)
7008 /* Avoid mixing '/' and '\\' */
7011 for (i = strlen (path) - 1; i >= 0; i--)
7012 if (path [i] == '/')
7016 ipath = mono_string_new (mono_domain_get (), path);
7023 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7025 MonoPEResourceDataEntry *entry;
7028 MONO_ARCH_SAVE_REGS;
7030 if (!assembly || !result || !size)
7035 image = assembly->assembly->image;
7036 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7040 *result = mono_image_rva_map (image, entry->rde_data_offset);
7045 *size = entry->rde_size;
7051 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7053 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7057 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7059 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7060 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7066 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7068 if (mono_get_runtime_callbacks ()->debug_log)
7069 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7073 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7075 #if defined (HOST_WIN32)
7076 OutputDebugString (mono_string_chars (message));
7078 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7082 /* Only used for value types */
7084 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7089 MONO_ARCH_SAVE_REGS;
7091 domain = mono_object_domain (type);
7092 klass = mono_class_from_mono_type (type->type);
7093 mono_class_init_or_throw (klass);
7095 if (mono_class_is_nullable (klass))
7096 /* No arguments -> null */
7099 return mono_object_new (domain, klass);
7102 static MonoReflectionMethod *
7103 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7105 MonoClass *klass, *parent;
7106 MonoMethod *method = m->method;
7107 MonoMethod *result = NULL;
7110 MONO_ARCH_SAVE_REGS;
7112 if (method->klass == NULL)
7115 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7116 MONO_CLASS_IS_INTERFACE (method->klass) ||
7117 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7120 slot = mono_method_get_vtable_slot (method);
7124 klass = method->klass;
7125 if (klass->generic_class)
7126 klass = klass->generic_class->container_class;
7129 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7130 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7131 mono_class_setup_vtable (parent);
7132 if (parent->vtable_size <= slot)
7137 klass = klass->parent;
7142 if (klass == method->klass)
7145 /*This is possible if definition == FALSE.
7146 * Do it here to be really sure we don't read invalid memory.
7148 if (slot >= klass->vtable_size)
7151 mono_class_setup_vtable (klass);
7153 result = klass->vtable [slot];
7154 if (result == NULL) {
7155 /* It is an abstract method */
7156 gpointer iter = NULL;
7157 while ((result = mono_class_get_methods (klass, &iter)))
7158 if (result->slot == slot)
7165 return mono_method_get_object (mono_domain_get (), result, NULL);
7169 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7171 MonoMethod *method = m->method;
7173 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7178 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7180 MONO_ARCH_SAVE_REGS;
7182 iter->sig = *(MonoMethodSignature**)argsp;
7184 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7185 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7188 /* FIXME: it's not documented what start is exactly... */
7192 iter->args = argsp + sizeof (gpointer);
7194 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7196 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7200 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7202 guint32 i, arg_size;
7205 MONO_ARCH_SAVE_REGS;
7207 i = iter->sig->sentinelpos + iter->next_arg;
7209 g_assert (i < iter->sig->param_count);
7211 res.type = iter->sig->params [i];
7212 res.klass = mono_class_from_mono_type (res.type);
7213 arg_size = mono_type_stack_size (res.type, &align);
7214 #if defined(__arm__)
7215 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7217 res.value = iter->args;
7218 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7219 if (arg_size <= sizeof (gpointer)) {
7221 int padding = arg_size - mono_type_size (res.type, &dummy);
7222 res.value = (guint8*)res.value + padding;
7225 iter->args = (char*)iter->args + arg_size;
7228 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7234 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7236 guint32 i, arg_size;
7239 MONO_ARCH_SAVE_REGS;
7241 i = iter->sig->sentinelpos + iter->next_arg;
7243 g_assert (i < iter->sig->param_count);
7245 while (i < iter->sig->param_count) {
7246 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7248 res.type = iter->sig->params [i];
7249 res.klass = mono_class_from_mono_type (res.type);
7250 /* FIXME: endianess issue... */
7251 arg_size = mono_type_stack_size (res.type, &align);
7252 #if defined(__arm__)
7253 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7255 res.value = iter->args;
7256 iter->args = (char*)iter->args + arg_size;
7258 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7261 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7270 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7273 MONO_ARCH_SAVE_REGS;
7275 i = iter->sig->sentinelpos + iter->next_arg;
7277 g_assert (i < iter->sig->param_count);
7279 return iter->sig->params [i];
7283 mono_TypedReference_ToObject (MonoTypedRef tref)
7285 MONO_ARCH_SAVE_REGS;
7287 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7288 MonoObject** objp = tref.value;
7292 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7296 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7298 MONO_ARCH_SAVE_REGS;
7300 if (MONO_TYPE_IS_REFERENCE (type)) {
7301 MonoObject** objp = value;
7305 return mono_value_box (mono_domain_get (), klass, value);
7309 prelink_method (MonoMethod *method)
7311 const char *exc_class, *exc_arg;
7312 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7314 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7316 mono_raise_exception(
7317 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7319 /* create the wrapper, too? */
7323 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7325 MONO_ARCH_SAVE_REGS;
7326 prelink_method (method->method);
7330 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7332 MonoClass *klass = mono_class_from_mono_type (type->type);
7334 gpointer iter = NULL;
7335 MONO_ARCH_SAVE_REGS;
7337 mono_class_init_or_throw (klass);
7339 while ((m = mono_class_get_methods (klass, &iter)))
7343 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7345 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7346 gint32 const **exponents,
7347 gunichar2 const **digitLowerTable,
7348 gunichar2 const **digitUpperTable,
7349 gint64 const **tenPowersList,
7350 gint32 const **decHexDigits)
7352 *mantissas = Formatter_MantissaBitsTable;
7353 *exponents = Formatter_TensExponentTable;
7354 *digitLowerTable = Formatter_DigitLowerTable;
7355 *digitUpperTable = Formatter_DigitUpperTable;
7356 *tenPowersList = Formatter_TenPowersList;
7357 *decHexDigits = Formatter_DecHexDigits;
7360 /* These parameters are "readonly" in corlib/System/Char.cs */
7362 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7363 guint8 const **numeric_data,
7364 gdouble const **numeric_data_values,
7365 guint16 const **to_lower_data_low,
7366 guint16 const **to_lower_data_high,
7367 guint16 const **to_upper_data_low,
7368 guint16 const **to_upper_data_high)
7370 *category_data = CategoryData;
7371 *numeric_data = NumericData;
7372 *numeric_data_values = NumericDataValues;
7373 *to_lower_data_low = ToLowerDataLow;
7374 *to_lower_data_high = ToLowerDataHigh;
7375 *to_upper_data_low = ToUpperDataLow;
7376 *to_upper_data_high = ToUpperDataHigh;
7380 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7382 return method->method->token;
7386 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7387 * and avoid useless allocations.
7390 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7394 for (i = 0; i < type->num_mods; ++i) {
7395 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7400 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7402 for (i = 0; i < type->num_mods; ++i) {
7403 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7404 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7405 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7413 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7415 MonoType *type = param->ClassImpl->type;
7416 MonoClass *member_class = mono_object_class (param->MemberImpl);
7417 MonoMethod *method = NULL;
7420 MonoMethodSignature *sig;
7422 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7423 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7424 method = rmethod->method;
7425 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7426 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7427 if (!(method = prop->property->get))
7428 method = prop->property->set;
7431 char *type_name = mono_type_get_full_name (member_class);
7432 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7433 MonoException *ex = mono_get_exception_not_supported (msg);
7436 mono_raise_exception (ex);
7439 image = method->klass->image;
7440 pos = param->PositionImpl;
7441 sig = mono_method_signature (method);
7445 type = sig->params [pos];
7447 return type_array_from_modifiers (image, type, optional);
7451 get_property_type (MonoProperty *prop)
7453 MonoMethodSignature *sig;
7455 sig = mono_method_signature (prop->get);
7457 } else if (prop->set) {
7458 sig = mono_method_signature (prop->set);
7459 return sig->params [sig->param_count - 1];
7465 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7467 MonoType *type = get_property_type (property->property);
7468 MonoImage *image = property->klass->image;
7472 return type_array_from_modifiers (image, type, optional);
7476 *Construct a MonoType suited to be used to decode a constant blob object.
7478 * @type is the target type which will be constructed
7479 * @blob_type is the blob type, for example, that comes from the constant table
7480 * @real_type is the expected constructed type.
7483 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7485 type->type = blob_type;
7486 type->data.klass = NULL;
7487 if (blob_type == MONO_TYPE_CLASS)
7488 type->data.klass = mono_defaults.object_class;
7489 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7490 /* For enums, we need to use the base type */
7491 type->type = MONO_TYPE_VALUETYPE;
7492 type->data.klass = mono_class_from_mono_type (real_type);
7494 type->data.klass = mono_class_from_mono_type (real_type);
7498 property_info_get_default_value (MonoReflectionProperty *property)
7501 MonoProperty *prop = property->property;
7502 MonoType *type = get_property_type (prop);
7503 MonoDomain *domain = mono_object_domain (property);
7504 MonoTypeEnum def_type;
7505 const char *def_value;
7508 mono_class_init (prop->parent);
7510 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7511 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7513 def_value = mono_class_get_property_default_value (prop, &def_type);
7515 mono_type_from_blob_type (&blob_type, def_type, type);
7516 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7522 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7524 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7525 MonoCustomAttrInfo *cinfo;
7528 mono_class_init_or_throw (attr_class);
7530 cinfo = mono_reflection_get_custom_attrs_info (obj);
7533 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7535 mono_custom_attrs_free (cinfo);
7540 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7542 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7547 mono_class_init_or_throw (attr_class);
7549 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7550 if (!mono_error_ok (&error))
7551 mono_error_raise_exception (&error);
7552 if (mono_loader_get_last_error ()) {
7553 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7554 g_assert_not_reached ();
7563 ves_icall_Mono_Runtime_GetDisplayName (void)
7566 MonoString *display_name;
7568 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7569 display_name = mono_string_new (mono_domain_get (), info);
7571 return display_name;
7575 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7577 MonoString *message;
7581 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7582 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7585 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7587 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7595 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7596 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7597 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7598 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7599 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7600 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7601 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7602 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7606 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7611 gunichar2 last, prev_last, prev2_last;
7619 last = prev_last = 0, prev2_last = 0;
7620 for (i = 0; i < ilength; i++) {
7622 if (c >= sizeof (dbase64)) {
7623 exc = mono_exception_from_name_msg (mono_get_corlib (),
7624 "System", "FormatException",
7625 "Invalid character found.");
7626 mono_raise_exception (exc);
7627 } else if (isspace (c)) {
7630 prev2_last = prev_last;
7636 olength = ilength - ignored;
7638 if (allowWhitespaceOnly && olength == 0) {
7639 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7642 if ((olength & 3) != 0 || olength <= 0) {
7643 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7644 "FormatException", "Invalid length.");
7645 mono_raise_exception (exc);
7648 if (prev2_last == '=') {
7649 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7650 mono_raise_exception (exc);
7653 olength = (olength * 3) / 4;
7657 if (prev_last == '=')
7660 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7661 res_ptr = mono_array_addr (result, guchar, 0);
7662 for (i = 0; i < ilength; ) {
7665 for (k = 0; k < 4 && i < ilength;) {
7671 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7672 exc = mono_exception_from_name_msg (mono_get_corlib (),
7673 "System", "FormatException",
7674 "Invalid character found.");
7675 mono_raise_exception (exc);
7680 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7682 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7684 *res_ptr++ = (b [2] << 6) | b [3];
7686 while (i < ilength && isspace (start [i]))
7694 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7696 MONO_ARCH_SAVE_REGS;
7698 return base64_to_byte_array (mono_string_chars (str),
7699 mono_string_length (str), allowWhitespaceOnly);
7703 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7705 MONO_ARCH_SAVE_REGS;
7707 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7711 #define ICALL_TYPE(id,name,first)
7712 #define ICALL(id,name,func) Icall_ ## id,
7715 #include "metadata/icall-def.h"
7721 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7722 #define ICALL(id,name,func)
7724 #include "metadata/icall-def.h"
7730 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7731 #define ICALL(id,name,func)
7733 guint16 first_icall;
7736 static const IcallTypeDesc
7737 icall_type_descs [] = {
7738 #include "metadata/icall-def.h"
7742 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7745 #define ICALL_TYPE(id,name,first)
7748 #ifdef HAVE_ARRAY_ELEM_INIT
7749 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7750 #define MSGSTRFIELD1(line) str##line
7752 static const struct msgstrtn_t {
7753 #define ICALL(id,name,func)
7755 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7756 #include "metadata/icall-def.h"
7758 } icall_type_names_str = {
7759 #define ICALL_TYPE(id,name,first) (name),
7760 #include "metadata/icall-def.h"
7763 static const guint16 icall_type_names_idx [] = {
7764 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7765 #include "metadata/icall-def.h"
7768 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7770 static const struct msgstr_t {
7772 #define ICALL_TYPE(id,name,first)
7773 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7774 #include "metadata/icall-def.h"
7776 } icall_names_str = {
7777 #define ICALL(id,name,func) (name),
7778 #include "metadata/icall-def.h"
7781 static const guint16 icall_names_idx [] = {
7782 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7783 #include "metadata/icall-def.h"
7786 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7792 #define ICALL_TYPE(id,name,first) name,
7793 #define ICALL(id,name,func)
7794 static const char* const
7795 icall_type_names [] = {
7796 #include "metadata/icall-def.h"
7800 #define icall_type_name_get(id) (icall_type_names [(id)])
7804 #define ICALL_TYPE(id,name,first)
7805 #define ICALL(id,name,func) name,
7806 static const char* const
7808 #include "metadata/icall-def.h"
7811 #define icall_name_get(id) icall_names [(id)]
7813 #endif /* !HAVE_ARRAY_ELEM_INIT */
7817 #define ICALL_TYPE(id,name,first)
7818 #define ICALL(id,name,func) func,
7819 static const gconstpointer
7820 icall_functions [] = {
7821 #include "metadata/icall-def.h"
7825 static GHashTable *icall_hash = NULL;
7826 static GHashTable *jit_icall_hash_name = NULL;
7827 static GHashTable *jit_icall_hash_addr = NULL;
7830 mono_icall_init (void)
7834 /* check that tables are sorted: disable in release */
7837 const char *prev_class = NULL;
7838 const char *prev_method;
7840 for (i = 0; i < Icall_type_num; ++i) {
7841 const IcallTypeDesc *desc;
7844 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7845 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7846 prev_class = icall_type_name_get (i);
7847 desc = &icall_type_descs [i];
7848 num_icalls = icall_desc_num_icalls (desc);
7849 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7850 for (j = 0; j < num_icalls; ++j) {
7851 const char *methodn = icall_name_get (desc->first_icall + j);
7852 if (prev_method && strcmp (prev_method, methodn) >= 0)
7853 g_print ("method %s should come before method %s\n", methodn, prev_method);
7854 prev_method = methodn;
7859 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7863 mono_icall_cleanup (void)
7865 g_hash_table_destroy (icall_hash);
7866 g_hash_table_destroy (jit_icall_hash_name);
7867 g_hash_table_destroy (jit_icall_hash_addr);
7871 mono_add_internal_call (const char *name, gconstpointer method)
7873 mono_loader_lock ();
7875 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7877 mono_loader_unlock ();
7880 #ifdef HAVE_ARRAY_ELEM_INIT
7882 compare_method_imap (const void *key, const void *elem)
7884 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7885 return strcmp (key, method_name);
7889 find_method_icall (const IcallTypeDesc *imap, const char *name)
7891 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7894 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7898 compare_class_imap (const void *key, const void *elem)
7900 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7901 return strcmp (key, class_name);
7904 static const IcallTypeDesc*
7905 find_class_icalls (const char *name)
7907 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7910 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7915 compare_method_imap (const void *key, const void *elem)
7917 const char** method_name = (const char**)elem;
7918 return strcmp (key, *method_name);
7922 find_method_icall (const IcallTypeDesc *imap, const char *name)
7924 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7927 return (gpointer)icall_functions [(nameslot - icall_names)];
7931 compare_class_imap (const void *key, const void *elem)
7933 const char** class_name = (const char**)elem;
7934 return strcmp (key, *class_name);
7937 static const IcallTypeDesc*
7938 find_class_icalls (const char *name)
7940 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7943 return &icall_type_descs [nameslot - icall_type_names];
7949 * we should probably export this as an helper (handle nested types).
7950 * Returns the number of chars written in buf.
7953 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7955 int nspacelen, cnamelen;
7956 nspacelen = strlen (klass->name_space);
7957 cnamelen = strlen (klass->name);
7958 if (nspacelen + cnamelen + 2 > bufsize)
7961 memcpy (buf, klass->name_space, nspacelen);
7962 buf [nspacelen ++] = '.';
7964 memcpy (buf + nspacelen, klass->name, cnamelen);
7965 buf [nspacelen + cnamelen] = 0;
7966 return nspacelen + cnamelen;
7970 mono_lookup_internal_call (MonoMethod *method)
7975 int typelen = 0, mlen, siglen;
7977 const IcallTypeDesc *imap;
7979 g_assert (method != NULL);
7981 if (method->is_inflated)
7982 method = ((MonoMethodInflated *) method)->declaring;
7984 if (method->klass->nested_in) {
7985 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7989 mname [pos++] = '/';
7992 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7998 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8003 imap = find_class_icalls (mname);
8005 mname [typelen] = ':';
8006 mname [typelen + 1] = ':';
8008 mlen = strlen (method->name);
8009 memcpy (mname + typelen + 2, method->name, mlen);
8010 sigstart = mname + typelen + 2 + mlen;
8013 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8014 siglen = strlen (tmpsig);
8015 if (typelen + mlen + siglen + 6 > sizeof (mname))
8018 memcpy (sigstart + 1, tmpsig, siglen);
8019 sigstart [siglen + 1] = ')';
8020 sigstart [siglen + 2] = 0;
8023 mono_loader_lock ();
8025 res = g_hash_table_lookup (icall_hash, mname);
8027 mono_loader_unlock ();
8030 /* try without signature */
8032 res = g_hash_table_lookup (icall_hash, mname);
8034 mono_loader_unlock ();
8038 /* it wasn't found in the static call tables */
8040 mono_loader_unlock ();
8043 res = find_method_icall (imap, sigstart - mlen);
8045 mono_loader_unlock ();
8048 /* try _with_ signature */
8050 res = find_method_icall (imap, sigstart - mlen);
8052 mono_loader_unlock ();
8056 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8057 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8058 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8059 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8060 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");
8061 g_print ("If you see other errors or faults after this message they are probably related\n");
8062 g_print ("and you need to fix your mono install first.\n");
8064 mono_loader_unlock ();
8070 type_from_typename (char *typename)
8072 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8074 if (!strcmp (typename, "int"))
8075 klass = mono_defaults.int_class;
8076 else if (!strcmp (typename, "ptr"))
8077 klass = mono_defaults.int_class;
8078 else if (!strcmp (typename, "void"))
8079 klass = mono_defaults.void_class;
8080 else if (!strcmp (typename, "int32"))
8081 klass = mono_defaults.int32_class;
8082 else if (!strcmp (typename, "uint32"))
8083 klass = mono_defaults.uint32_class;
8084 else if (!strcmp (typename, "int8"))
8085 klass = mono_defaults.sbyte_class;
8086 else if (!strcmp (typename, "uint8"))
8087 klass = mono_defaults.byte_class;
8088 else if (!strcmp (typename, "int16"))
8089 klass = mono_defaults.int16_class;
8090 else if (!strcmp (typename, "uint16"))
8091 klass = mono_defaults.uint16_class;
8092 else if (!strcmp (typename, "long"))
8093 klass = mono_defaults.int64_class;
8094 else if (!strcmp (typename, "ulong"))
8095 klass = mono_defaults.uint64_class;
8096 else if (!strcmp (typename, "float"))
8097 klass = mono_defaults.single_class;
8098 else if (!strcmp (typename, "double"))
8099 klass = mono_defaults.double_class;
8100 else if (!strcmp (typename, "object"))
8101 klass = mono_defaults.object_class;
8102 else if (!strcmp (typename, "obj"))
8103 klass = mono_defaults.object_class;
8104 else if (!strcmp (typename, "string"))
8105 klass = mono_defaults.string_class;
8106 else if (!strcmp (typename, "bool"))
8107 klass = mono_defaults.boolean_class;
8108 else if (!strcmp (typename, "boolean"))
8109 klass = mono_defaults.boolean_class;
8111 g_error ("%s", typename);
8112 g_assert_not_reached ();
8114 return &klass->byval_arg;
8117 MonoMethodSignature*
8118 mono_create_icall_signature (const char *sigstr)
8123 MonoMethodSignature *res;
8125 mono_loader_lock ();
8126 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8128 mono_loader_unlock ();
8132 parts = g_strsplit (sigstr, " ", 256);
8141 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8146 * Under windows, the default pinvoke calling convention is STDCALL but
8149 res->call_convention = MONO_CALL_C;
8152 res->ret = type_from_typename (parts [0]);
8153 for (i = 1; i < len; ++i) {
8154 res->params [i - 1] = type_from_typename (parts [i]);
8159 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8161 mono_loader_unlock ();
8167 mono_find_jit_icall_by_name (const char *name)
8169 MonoJitICallInfo *info;
8170 g_assert (jit_icall_hash_name);
8172 mono_loader_lock ();
8173 info = g_hash_table_lookup (jit_icall_hash_name, name);
8174 mono_loader_unlock ();
8179 mono_find_jit_icall_by_addr (gconstpointer addr)
8181 MonoJitICallInfo *info;
8182 g_assert (jit_icall_hash_addr);
8184 mono_loader_lock ();
8185 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8186 mono_loader_unlock ();
8192 * mono_get_jit_icall_info:
8194 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8195 * caller should access it while holding the loader lock.
8198 mono_get_jit_icall_info (void)
8200 return jit_icall_hash_name;
8204 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8206 mono_loader_lock ();
8207 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8208 mono_loader_unlock ();
8212 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8214 MonoJitICallInfo *info;
8219 mono_loader_lock ();
8221 if (!jit_icall_hash_name) {
8222 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8223 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8226 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8227 g_warning ("jit icall already defined \"%s\"\n", name);
8228 g_assert_not_reached ();
8231 info = g_new0 (MonoJitICallInfo, 1);
8238 info->wrapper = func;
8240 info->wrapper = NULL;
8243 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8244 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8246 mono_loader_unlock ();