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);
1933 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1937 case MONO_TYPE_BOOLEAN:
1940 case MONO_TYPE_CHAR:
1948 case MONO_TYPE_R8: {
1951 /* boxed value type */
1952 t = g_new0 (MonoType, 1);
1954 klass = mono_class_from_mono_type (t);
1956 o = mono_object_new (domain, klass);
1957 v = ((gchar *) o) + sizeof (MonoObject);
1958 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1961 case MONO_TYPE_STRING:
1962 case MONO_TYPE_CLASS:
1963 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1966 g_assert_not_reached ();
1972 static MonoReflectionType*
1973 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1976 MonoClassField *field = ref_field->field;
1977 MonoType *type = mono_field_get_type_checked (field, &error);
1978 if (!mono_error_ok (&error))
1979 mono_error_raise_exception (&error);
1980 return mono_type_get_object (mono_object_domain (ref_field), type);
1983 static MonoReflectionType*
1984 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1986 MonoMethod *method = rmethod->method.method;
1988 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1991 /* From MonoProperty.cs */
1993 PInfo_Attributes = 1,
1994 PInfo_GetMethod = 1 << 1,
1995 PInfo_SetMethod = 1 << 2,
1996 PInfo_ReflectedType = 1 << 3,
1997 PInfo_DeclaringType = 1 << 4,
2002 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2004 MonoDomain *domain = mono_object_domain (property);
2006 MONO_ARCH_SAVE_REGS;
2008 if ((req_info & PInfo_ReflectedType) != 0)
2009 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2010 if ((req_info & PInfo_DeclaringType) != 0)
2011 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2013 if ((req_info & PInfo_Name) != 0)
2014 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2016 if ((req_info & PInfo_Attributes) != 0)
2017 info->attrs = property->property->attrs;
2019 if ((req_info & PInfo_GetMethod) != 0)
2020 MONO_STRUCT_SETREF (info, get, property->property->get ?
2021 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2023 if ((req_info & PInfo_SetMethod) != 0)
2024 MONO_STRUCT_SETREF (info, set, property->property->set ?
2025 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2027 * There may be other methods defined for properties, though, it seems they are not exposed
2028 * in the reflection API
2033 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2035 MonoDomain *domain = mono_object_domain (event);
2037 MONO_ARCH_SAVE_REGS;
2039 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2040 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2042 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2043 info->attrs = event->event->attrs;
2044 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2045 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2046 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2048 #ifndef MONO_SMALL_CONFIG
2049 if (event->event->other) {
2051 while (event->event->other [n])
2053 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2055 for (i = 0; i < n; i++)
2056 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2062 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2067 mono_class_setup_interfaces (klass, error);
2068 if (!mono_error_ok (error))
2071 for (i = 0; i < klass->interface_count; i++) {
2072 ic = klass->interfaces [i];
2073 g_hash_table_insert (ifaces, ic, ic);
2075 collect_interfaces (ic, ifaces, error);
2076 if (!mono_error_ok (error))
2082 MonoArray *iface_array;
2083 MonoGenericContext *context;
2087 } FillIfaceArrayData;
2090 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2092 FillIfaceArrayData *data = user_data;
2093 MonoClass *ic = key;
2094 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2096 if (!mono_error_ok (data->error))
2099 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2100 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2101 if (!mono_error_ok (data->error))
2105 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2108 mono_metadata_free_type (inflated);
2112 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2115 MonoClass *class = mono_class_from_mono_type (type->type);
2117 FillIfaceArrayData data = { 0 };
2120 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2122 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2123 data.context = mono_class_get_context (class);
2124 class = class->generic_class->container_class;
2127 for (parent = class; parent; parent = parent->parent) {
2128 mono_class_setup_interfaces (parent, &error);
2129 if (!mono_error_ok (&error))
2131 collect_interfaces (parent, iface_hash, &error);
2132 if (!mono_error_ok (&error))
2136 data.error = &error;
2137 data.domain = mono_object_domain (type);
2139 len = g_hash_table_size (iface_hash);
2141 g_hash_table_destroy (iface_hash);
2142 if (!data.domain->empty_types)
2143 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2144 return data.domain->empty_types;
2147 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2148 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2149 if (!mono_error_ok (&error))
2152 g_hash_table_destroy (iface_hash);
2153 return data.iface_array;
2156 g_hash_table_destroy (iface_hash);
2157 mono_error_raise_exception (&error);
2162 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2164 gboolean variance_used;
2165 MonoClass *class = mono_class_from_mono_type (type->type);
2166 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2167 MonoReflectionMethod *member;
2170 int i = 0, len, ioffset;
2173 MONO_ARCH_SAVE_REGS;
2174 mono_class_init_or_throw (class);
2175 mono_class_init_or_throw (iclass);
2177 mono_class_setup_vtable (class);
2179 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2183 len = mono_class_num_methods (iclass);
2184 domain = mono_object_domain (type);
2185 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2186 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2188 while ((method = mono_class_get_methods (iclass, &iter))) {
2189 member = mono_method_get_object (domain, method, iclass);
2190 mono_array_setref (*methods, i, member);
2191 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2192 mono_array_setref (*targets, i, member);
2199 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2201 MonoClass *klass = mono_class_from_mono_type (type->type);
2202 mono_class_init_or_throw (klass);
2204 if (klass->image->dynamic) {
2205 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2206 *packing = tb->packing_size;
2207 *size = tb->class_size;
2209 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2213 static MonoReflectionType*
2214 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2218 MONO_ARCH_SAVE_REGS;
2220 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2221 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2223 class = mono_class_from_mono_type (type->type);
2224 mono_class_init_or_throw (class);
2226 // GetElementType should only return a type for:
2227 // Array Pointer PassedByRef
2228 if (type->type->byref)
2229 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2230 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2231 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2232 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2233 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2238 static MonoReflectionType*
2239 ves_icall_get_type_parent (MonoReflectionType *type)
2241 MonoClass *class = mono_class_from_mono_type (type->type);
2242 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2246 ves_icall_type_ispointer (MonoReflectionType *type)
2248 MONO_ARCH_SAVE_REGS;
2250 return type->type->type == MONO_TYPE_PTR;
2254 ves_icall_type_isprimitive (MonoReflectionType *type)
2256 MONO_ARCH_SAVE_REGS;
2258 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)));
2262 ves_icall_type_isbyref (MonoReflectionType *type)
2264 MONO_ARCH_SAVE_REGS;
2266 return type->type->byref;
2270 ves_icall_type_iscomobject (MonoReflectionType *type)
2272 MonoClass *klass = mono_class_from_mono_type (type->type);
2273 mono_class_init_or_throw (klass);
2275 return (klass && klass->is_com_object);
2278 static MonoReflectionModule*
2279 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2281 MonoClass *class = mono_class_from_mono_type (type->type);
2282 return mono_module_get_object (mono_object_domain (type), class->image);
2285 static MonoReflectionAssembly*
2286 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2288 MonoDomain *domain = mono_domain_get ();
2289 MonoClass *class = mono_class_from_mono_type (type->type);
2290 return mono_assembly_get_object (domain, class->image->assembly);
2293 static MonoReflectionType*
2294 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2296 MonoDomain *domain = mono_domain_get ();
2299 MONO_ARCH_SAVE_REGS;
2301 if (type->type->byref)
2303 if (type->type->type == MONO_TYPE_VAR)
2304 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2305 else if (type->type->type == MONO_TYPE_MVAR)
2306 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2308 class = mono_class_from_mono_type (type->type)->nested_in;
2310 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2314 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2316 MonoDomain *domain = mono_domain_get ();
2317 MonoClass *class = mono_class_from_mono_type (type->type);
2319 if (type->type->byref) {
2320 char *n = g_strdup_printf ("%s&", class->name);
2321 MonoString *res = mono_string_new (domain, n);
2327 return mono_string_new (domain, class->name);
2332 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2334 MonoDomain *domain = mono_domain_get ();
2335 MonoClass *class = mono_class_from_mono_type (type->type);
2337 while (class->nested_in)
2338 class = class->nested_in;
2340 if (class->name_space [0] == '\0')
2343 return mono_string_new (domain, class->name_space);
2347 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2351 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2352 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2354 class = mono_class_from_mono_type (type->type);
2360 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2363 MonoClass *klass, *pklass;
2364 MonoDomain *domain = mono_object_domain (type);
2365 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2367 MONO_ARCH_SAVE_REGS;
2369 klass = mono_class_from_mono_type (type->type);
2371 if (klass->generic_container) {
2372 MonoGenericContainer *container = klass->generic_container;
2373 res = mono_array_new_specific (array_vtable, container->type_argc);
2374 for (i = 0; i < container->type_argc; ++i) {
2375 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2376 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2378 } else if (klass->generic_class) {
2379 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2380 res = mono_array_new_specific (array_vtable, inst->type_argc);
2381 for (i = 0; i < inst->type_argc; ++i)
2382 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2384 res = mono_array_new_specific (array_vtable, 0);
2390 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2393 MONO_ARCH_SAVE_REGS;
2395 if (!IS_MONOTYPE (type))
2398 if (type->type->byref)
2401 klass = mono_class_from_mono_type (type->type);
2402 return klass->generic_container != NULL;
2405 static MonoReflectionType*
2406 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2409 MONO_ARCH_SAVE_REGS;
2411 if (type->type->byref)
2414 klass = mono_class_from_mono_type (type->type);
2416 if (klass->generic_container) {
2417 return type; /* check this one */
2419 if (klass->generic_class) {
2420 MonoClass *generic_class = klass->generic_class->container_class;
2423 tb = mono_class_get_ref_info (generic_class);
2425 if (generic_class->wastypebuilder && tb)
2428 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2433 static MonoReflectionType*
2434 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2437 MonoType *geninst, **types;
2440 g_assert (IS_MONOTYPE (type));
2441 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2443 count = mono_array_length (type_array);
2444 types = g_new0 (MonoType *, count);
2446 for (i = 0; i < count; i++) {
2447 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2448 types [i] = t->type;
2451 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2456 class = mono_class_from_mono_type (geninst);
2458 /*we might inflate to the GTD*/
2459 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2460 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2462 return mono_type_get_object (mono_object_domain (type), geninst);
2466 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2469 MONO_ARCH_SAVE_REGS;
2471 if (type->type->byref)
2474 klass = mono_class_from_mono_type (type->type);
2476 return klass->generic_class != NULL;
2480 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2483 MONO_ARCH_SAVE_REGS;
2485 if (!IS_MONOTYPE (type))
2488 if (type->type->byref)
2491 klass = mono_class_from_mono_type (type->type);
2492 return klass->generic_class != NULL || klass->generic_container != NULL;
2496 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2498 MONO_ARCH_SAVE_REGS;
2500 if (!IS_MONOTYPE (type))
2503 if (is_generic_parameter (type->type))
2504 return mono_type_get_generic_param_num (type->type);
2508 static GenericParameterAttributes
2509 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2511 MONO_ARCH_SAVE_REGS;
2513 g_assert (IS_MONOTYPE (type));
2514 g_assert (is_generic_parameter (type->type));
2515 return mono_generic_param_info (type->type->data.generic_param)->flags;
2519 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2521 MonoGenericParamInfo *param_info;
2527 MONO_ARCH_SAVE_REGS;
2529 g_assert (IS_MONOTYPE (type));
2531 domain = mono_object_domain (type);
2532 param_info = mono_generic_param_info (type->type->data.generic_param);
2533 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2536 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2537 for (i = 0; i < count; i++)
2538 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2545 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2547 MONO_ARCH_SAVE_REGS;
2548 return is_generic_parameter (type->type);
2552 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2554 MONO_ARCH_SAVE_REGS;
2555 return is_generic_parameter (tb->type.type);
2559 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2560 MonoReflectionType *t)
2562 enumtype->type = t->type;
2565 static MonoReflectionMethod*
2566 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2567 MonoReflectionMethod* generic)
2574 MONO_ARCH_SAVE_REGS;
2576 domain = ((MonoObject *)type)->vtable->domain;
2578 klass = mono_class_from_mono_type (type->type);
2579 mono_class_init_or_throw (klass);
2582 while ((method = mono_class_get_methods (klass, &iter))) {
2583 if (method->token == generic->method->token)
2584 return mono_method_get_object (domain, method, klass);
2592 static MonoReflectionMethod *
2593 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2596 MonoType *type = ref_type->type;
2598 MONO_ARCH_SAVE_REGS;
2600 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2601 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2602 if (type->type == MONO_TYPE_VAR)
2605 method = mono_type_get_generic_param_owner (type)->owner.method;
2607 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2610 static MonoReflectionDllImportAttribute*
2611 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2613 static MonoClass *DllImportAttributeClass = NULL;
2614 MonoDomain *domain = mono_domain_get ();
2615 MonoReflectionDllImportAttribute *attr;
2616 MonoImage *image = method->klass->image;
2617 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2618 MonoTableInfo *tables = image->tables;
2619 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2620 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2621 guint32 im_cols [MONO_IMPLMAP_SIZE];
2622 guint32 scope_token;
2623 const char *import = NULL;
2624 const char *scope = NULL;
2627 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2630 if (!DllImportAttributeClass) {
2631 DllImportAttributeClass =
2632 mono_class_from_name (mono_defaults.corlib,
2633 "System.Runtime.InteropServices", "DllImportAttribute");
2634 g_assert (DllImportAttributeClass);
2637 if (method->klass->image->dynamic) {
2638 MonoReflectionMethodAux *method_aux =
2639 g_hash_table_lookup (
2640 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2642 import = method_aux->dllentry;
2643 scope = method_aux->dll;
2646 if (!import || !scope) {
2647 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2652 if (piinfo->implmap_idx) {
2653 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2655 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2656 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2657 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2658 scope = mono_metadata_string_heap (image, scope_token);
2661 flags = piinfo->piflags;
2663 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2665 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2666 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2667 attr->call_conv = (flags & 0x700) >> 8;
2668 attr->charset = ((flags & 0x6) >> 1) + 1;
2669 if (attr->charset == 1)
2671 attr->exact_spelling = (flags & 0x1) != 0;
2672 attr->set_last_error = (flags & 0x40) != 0;
2673 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2674 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2675 attr->preserve_sig = FALSE;
2680 static MonoReflectionMethod *
2681 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2683 MonoMethodInflated *imethod;
2686 MONO_ARCH_SAVE_REGS;
2688 if (method->method->is_generic)
2691 if (!method->method->is_inflated)
2694 imethod = (MonoMethodInflated *) method->method;
2696 result = imethod->declaring;
2697 /* Not a generic method. */
2698 if (!result->is_generic)
2701 if (method->method->klass->image->dynamic) {
2702 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2703 MonoReflectionMethod *res;
2706 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2707 * the dynamic case as well ?
2709 mono_loader_lock ();
2710 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2711 mono_loader_unlock ();
2717 if (imethod->context.class_inst) {
2718 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2719 /*Generic methods gets the context of the GTD.*/
2720 if (mono_class_get_context (klass))
2721 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2724 return mono_method_get_object (mono_object_domain (method), result, NULL);
2728 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2730 MONO_ARCH_SAVE_REGS;
2732 return mono_method_signature (method->method)->generic_param_count != 0;
2736 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2738 MONO_ARCH_SAVE_REGS;
2740 return method->method->is_generic;
2744 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2749 MONO_ARCH_SAVE_REGS;
2751 domain = mono_object_domain (method);
2753 if (method->method->is_inflated) {
2754 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2757 count = inst->type_argc;
2758 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2760 for (i = 0; i < count; i++)
2761 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2767 count = mono_method_signature (method->method)->generic_param_count;
2768 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2770 for (i = 0; i < count; i++) {
2771 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2772 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2773 MonoClass *pklass = mono_class_from_generic_parameter (
2774 param, method->method->klass->image, TRUE);
2775 mono_array_setref (res, i,
2776 mono_type_get_object (domain, &pklass->byval_arg));
2783 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2786 * Invoke from reflection is supposed to always be a virtual call (the API
2787 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2788 * greater flexibility.
2790 MonoMethod *m = method->method;
2794 MONO_ARCH_SAVE_REGS;
2798 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2799 mono_security_core_clr_ensure_reflection_access_method (m);
2801 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2802 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2803 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2808 if (!mono_object_isinst (this, m->klass)) {
2809 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2812 m = mono_object_get_virtual_method (this, m);
2813 /* must pass the pointer to the value for valuetype methods */
2814 if (m->klass->valuetype)
2815 obj = mono_object_unbox (this);
2816 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2817 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2822 pcount = params? mono_array_length (params): 0;
2823 if (pcount != mono_method_signature (m)->param_count) {
2824 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2828 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2829 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."));
2833 if (m->klass->image->assembly->ref_only) {
2834 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."));
2838 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2841 intptr_t *lower_bounds;
2842 pcount = mono_array_length (params);
2843 lengths = alloca (sizeof (uintptr_t) * pcount);
2844 /* Note: the synthetized array .ctors have int32 as argument type */
2845 for (i = 0; i < pcount; ++i)
2846 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2848 if (m->klass->rank == pcount) {
2849 /* Only lengths provided. */
2850 lower_bounds = NULL;
2852 g_assert (pcount == (m->klass->rank * 2));
2853 /* lower bounds are first. */
2854 lower_bounds = (intptr_t*)lengths;
2855 lengths += m->klass->rank;
2858 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2860 return mono_runtime_invoke_array (m, obj, params, NULL);
2864 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2866 MonoDomain *domain = mono_object_domain (method);
2867 MonoMethod *m = method->method;
2868 MonoMethodSignature *sig = mono_method_signature (m);
2869 MonoArray *out_args;
2871 int i, j, outarg_count = 0;
2873 MONO_ARCH_SAVE_REGS;
2875 if (m->klass == mono_defaults.object_class) {
2877 if (!strcmp (m->name, "FieldGetter")) {
2878 MonoClass *k = this->vtable->klass;
2882 /* If this is a proxy, then it must be a CBO */
2883 if (k == mono_defaults.transparent_proxy_class) {
2884 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2885 this = tp->rp->unwrapped_server;
2887 k = this->vtable->klass;
2890 name = mono_array_get (params, MonoString *, 1);
2891 str = mono_string_to_utf8 (name);
2894 MonoClassField* field = mono_class_get_field_from_name (k, str);
2896 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2897 if (field_klass->valuetype)
2898 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2900 result = *((gpointer *)((char *)this + field->offset));
2902 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2903 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2904 mono_array_setref (out_args, 0, result);
2912 g_assert_not_reached ();
2914 } else if (!strcmp (m->name, "FieldSetter")) {
2915 MonoClass *k = this->vtable->klass;
2921 /* If this is a proxy, then it must be a CBO */
2922 if (k == mono_defaults.transparent_proxy_class) {
2923 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2924 this = tp->rp->unwrapped_server;
2926 k = this->vtable->klass;
2929 name = mono_array_get (params, MonoString *, 1);
2930 str = mono_string_to_utf8 (name);
2933 MonoClassField* field = mono_class_get_field_from_name (k, str);
2935 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2936 MonoObject *val = mono_array_get (params, gpointer, 2);
2938 if (field_klass->valuetype) {
2939 size = mono_type_size (field->type, &align);
2940 g_assert (size == mono_class_value_size (field_klass, NULL));
2941 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2943 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2946 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2947 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2957 g_assert_not_reached ();
2962 for (i = 0; i < mono_array_length (params); i++) {
2963 if (sig->params [i]->byref)
2967 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2969 /* handle constructors only for objects already allocated */
2970 if (!strcmp (method->method->name, ".ctor"))
2973 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2974 g_assert (!method->method->klass->valuetype);
2975 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2977 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2978 if (sig->params [i]->byref) {
2980 arg = mono_array_get (params, gpointer, i);
2981 mono_array_setref (out_args, j, arg);
2986 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2992 read_enum_value (char *mem, int type)
2996 return *(guint8*)mem;
2998 return *(gint8*)mem;
3000 return *(guint16*)mem;
3002 return *(gint16*)mem;
3004 return *(guint32*)mem;
3006 return *(gint32*)mem;
3008 return *(guint64*)mem;
3010 return *(gint64*)mem;
3012 g_assert_not_reached ();
3018 write_enum_value (char *mem, int type, guint64 value)
3022 case MONO_TYPE_I1: {
3023 guint8 *p = (guint8*)mem;
3028 case MONO_TYPE_I2: {
3029 guint16 *p = (void*)mem;
3034 case MONO_TYPE_I4: {
3035 guint32 *p = (void*)mem;
3040 case MONO_TYPE_I8: {
3041 guint64 *p = (void*)mem;
3046 g_assert_not_reached ();
3052 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3055 MonoClass *enumc, *objc;
3060 MONO_ARCH_SAVE_REGS;
3062 MONO_CHECK_ARG_NULL (enumType);
3063 MONO_CHECK_ARG_NULL (value);
3065 domain = mono_object_domain (enumType);
3066 enumc = mono_class_from_mono_type (enumType->type);
3068 mono_class_init_or_throw (enumc);
3070 objc = value->vtable->klass;
3072 if (!enumc->enumtype)
3073 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3074 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3075 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."));
3077 etype = mono_class_enum_basetype (enumc);
3079 /* MS throws this for typebuilders */
3080 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3082 res = mono_object_new (domain, enumc);
3083 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3084 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3090 ves_icall_System_Enum_get_value (MonoObject *this)
3098 MONO_ARCH_SAVE_REGS;
3103 g_assert (this->vtable->klass->enumtype);
3105 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3106 res = mono_object_new (mono_object_domain (this), enumc);
3107 dst = (char *)res + sizeof (MonoObject);
3108 src = (char *)this + sizeof (MonoObject);
3109 size = mono_class_value_size (enumc, NULL);
3111 memcpy (dst, src, size);
3116 static MonoReflectionType *
3117 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3122 MONO_ARCH_SAVE_REGS;
3124 klass = mono_class_from_mono_type (type->type);
3125 mono_class_init_or_throw (klass);
3127 etype = mono_class_enum_basetype (klass);
3129 /* MS throws this for typebuilders */
3130 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3132 return mono_type_get_object (mono_object_domain (type), etype);
3136 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3138 gpointer tdata = (char *)this + sizeof (MonoObject);
3139 gpointer odata = (char *)other + sizeof (MonoObject);
3140 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3141 g_assert (basetype);
3143 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3144 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3145 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3148 return me > other ? 1 : -1; \
3151 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3152 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3153 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3156 return me - other; \
3159 switch (basetype->type) {
3161 COMPARE_ENUM_VALUES (guint8);
3163 COMPARE_ENUM_VALUES (gint8);
3164 case MONO_TYPE_CHAR:
3166 COMPARE_ENUM_VALUES_RANGE (guint16);
3168 COMPARE_ENUM_VALUES (gint16);
3170 COMPARE_ENUM_VALUES (guint32);
3172 COMPARE_ENUM_VALUES (gint32);
3174 COMPARE_ENUM_VALUES (guint64);
3176 COMPARE_ENUM_VALUES (gint64);
3178 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3180 #undef COMPARE_ENUM_VALUES_RANGE
3181 #undef COMPARE_ENUM_VALUES
3186 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3188 gpointer data = (char *)this + sizeof (MonoObject);
3189 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3190 g_assert (basetype);
3192 switch (basetype->type) {
3194 return *((gint8*)data);
3196 return *((guint8*)data);
3197 case MONO_TYPE_CHAR:
3199 return *((guint16*)data);
3202 return *((gint16*)data);
3204 return *((guint32*)data);
3206 return *((gint32*)data);
3208 case MONO_TYPE_I8: {
3209 gint64 value = *((gint64*)data);
3210 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3213 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3219 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3221 MonoDomain *domain = mono_object_domain (type);
3222 MonoClass *enumc = mono_class_from_mono_type (type->type);
3223 guint j = 0, nvalues, crow;
3225 MonoClassField *field;
3227 MONO_ARCH_SAVE_REGS;
3229 mono_class_init_or_throw (enumc);
3231 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3232 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3233 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3234 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3238 while ((field = mono_class_get_fields (enumc, &iter))) {
3241 MonoTypeEnum def_type;
3243 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3245 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3247 if (mono_field_is_deleted (field))
3249 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3251 p = mono_class_get_field_default_value (field, &def_type);
3252 len = mono_metadata_decode_blob_size (p, &p);
3253 switch (mono_class_enum_basetype (enumc)->type) {
3256 mono_array_set (info->values, gchar, j, *p);
3258 case MONO_TYPE_CHAR:
3261 mono_array_set (info->values, gint16, j, read16 (p));
3265 mono_array_set (info->values, gint32, j, read32 (p));
3269 mono_array_set (info->values, gint64, j, read64 (p));
3272 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3279 BFLAGS_IgnoreCase = 1,
3280 BFLAGS_DeclaredOnly = 2,
3281 BFLAGS_Instance = 4,
3283 BFLAGS_Public = 0x10,
3284 BFLAGS_NonPublic = 0x20,
3285 BFLAGS_FlattenHierarchy = 0x40,
3286 BFLAGS_InvokeMethod = 0x100,
3287 BFLAGS_CreateInstance = 0x200,
3288 BFLAGS_GetField = 0x400,
3289 BFLAGS_SetField = 0x800,
3290 BFLAGS_GetProperty = 0x1000,
3291 BFLAGS_SetProperty = 0x2000,
3292 BFLAGS_ExactBinding = 0x10000,
3293 BFLAGS_SuppressChangeType = 0x20000,
3294 BFLAGS_OptionalParamBinding = 0x40000
3297 static MonoReflectionField *
3298 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3301 MonoClass *startklass, *klass;
3303 MonoClassField *field;
3306 int (*compare_func) (const char *s1, const char *s2) = NULL;
3307 domain = ((MonoObject *)type)->vtable->domain;
3308 klass = startklass = mono_class_from_mono_type (type->type);
3311 mono_raise_exception (mono_get_exception_argument_null ("name"));
3312 if (type->type->byref)
3315 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3318 if (klass->exception_type != MONO_EXCEPTION_NONE)
3319 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3322 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3323 guint32 flags = mono_field_get_flags (field);
3326 if (mono_field_is_deleted_with_flags (field, flags))
3328 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3329 if (bflags & BFLAGS_Public)
3331 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3332 if (bflags & BFLAGS_NonPublic) {
3339 if (flags & FIELD_ATTRIBUTE_STATIC) {
3340 if (bflags & BFLAGS_Static)
3341 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3344 if (bflags & BFLAGS_Instance)
3351 utf8_name = mono_string_to_utf8 (name);
3353 if (compare_func (mono_field_get_name (field), utf8_name)) {
3359 return mono_field_get_object (domain, klass, field);
3361 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3368 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3371 MonoClass *startklass, *klass, *refklass;
3376 MonoClassField *field;
3377 MonoPtrArray tmp_array;
3379 MONO_ARCH_SAVE_REGS;
3381 domain = ((MonoObject *)type)->vtable->domain;
3382 if (type->type->byref)
3383 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3384 klass = startklass = mono_class_from_mono_type (type->type);
3385 refklass = mono_class_from_mono_type (reftype->type);
3387 mono_ptr_array_init (tmp_array, 2);
3390 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3391 mono_ptr_array_destroy (tmp_array);
3392 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3396 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3397 guint32 flags = mono_field_get_flags (field);
3399 if (mono_field_is_deleted_with_flags (field, flags))
3401 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3402 if (bflags & BFLAGS_Public)
3404 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3405 if (bflags & BFLAGS_NonPublic) {
3412 if (flags & FIELD_ATTRIBUTE_STATIC) {
3413 if (bflags & BFLAGS_Static)
3414 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3417 if (bflags & BFLAGS_Instance)
3423 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3424 mono_ptr_array_append (tmp_array, member);
3426 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3429 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3431 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3432 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3434 mono_ptr_array_destroy (tmp_array);
3440 method_nonpublic (MonoMethod* method, gboolean start_klass)
3442 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3443 case METHOD_ATTRIBUTE_ASSEM:
3444 return (start_klass || mono_defaults.generic_ilist_class);
3445 case METHOD_ATTRIBUTE_PRIVATE:
3447 case METHOD_ATTRIBUTE_PUBLIC:
3455 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3457 static MonoClass *MethodInfo_array;
3459 MonoClass *startklass, *klass, *refklass;
3464 int i, len, match, nslots;
3465 /*FIXME, use MonoBitSet*/
3466 guint32 method_slots_default [8];
3467 guint32 *method_slots = NULL;
3468 gchar *mname = NULL;
3469 int (*compare_func) (const char *s1, const char *s2) = NULL;
3470 MonoVTable *array_vtable;
3472 MonoPtrArray tmp_array;
3474 mono_ptr_array_init (tmp_array, 4);
3476 if (!MethodInfo_array) {
3477 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3478 mono_memory_barrier ();
3479 MethodInfo_array = klass;
3482 domain = ((MonoObject *)type)->vtable->domain;
3483 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3484 if (type->type->byref)
3485 return mono_array_new_specific (array_vtable, 0);
3486 klass = startklass = mono_class_from_mono_type (type->type);
3487 refklass = mono_class_from_mono_type (reftype->type);
3491 mname = mono_string_to_utf8 (name);
3492 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3495 /* An optimization for calls made from Delegate:CreateDelegate () */
3496 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3497 method = mono_get_delegate_invoke (klass);
3498 if (mono_loader_get_last_error ())
3501 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3503 res = mono_array_new_specific (array_vtable, 1);
3504 mono_array_setref (res, 0, member);
3509 mono_class_setup_vtable (klass);
3510 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3513 if (is_generic_parameter (type->type))
3514 nslots = mono_class_get_vtable_size (klass->parent);
3516 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3517 if (nslots >= sizeof (method_slots_default) * 8) {
3518 method_slots = g_new0 (guint32, nslots / 32 + 1);
3520 method_slots = method_slots_default;
3521 memset (method_slots, 0, sizeof (method_slots_default));
3524 mono_class_setup_vtable (klass);
3525 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3529 while ((method = mono_class_get_methods (klass, &iter))) {
3531 if (method->slot != -1) {
3532 g_assert (method->slot < nslots);
3533 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3535 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3536 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3539 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3541 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3542 if (bflags & BFLAGS_Public)
3544 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3550 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3551 if (bflags & BFLAGS_Static)
3552 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3555 if (bflags & BFLAGS_Instance)
3563 if (compare_func (mname, method->name))
3569 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3571 mono_ptr_array_append (tmp_array, member);
3573 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3577 if (method_slots != method_slots_default)
3578 g_free (method_slots);
3580 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3582 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3583 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3585 mono_ptr_array_destroy (tmp_array);
3590 if (method_slots != method_slots_default)
3591 g_free (method_slots);
3592 mono_ptr_array_destroy (tmp_array);
3593 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3594 ex = mono_class_get_exception_for_failure (klass);
3596 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3597 mono_loader_clear_error ();
3599 mono_raise_exception (ex);
3604 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3607 static MonoClass *System_Reflection_ConstructorInfo;
3608 MonoClass *startklass, *klass, *refklass;
3613 gpointer iter = NULL;
3614 MonoPtrArray tmp_array;
3616 MONO_ARCH_SAVE_REGS;
3618 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3620 domain = ((MonoObject *)type)->vtable->domain;
3621 if (type->type->byref)
3622 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3623 klass = startklass = mono_class_from_mono_type (type->type);
3624 refklass = mono_class_from_mono_type (reftype->type);
3626 if (!System_Reflection_ConstructorInfo)
3627 System_Reflection_ConstructorInfo = mono_class_from_name (
3628 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3631 while ((method = mono_class_get_methods (klass, &iter))) {
3633 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3635 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3636 if (bflags & BFLAGS_Public)
3639 if (bflags & BFLAGS_NonPublic)
3645 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3646 if (bflags & BFLAGS_Static)
3647 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3650 if (bflags & BFLAGS_Instance)
3656 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3658 mono_ptr_array_append (tmp_array, member);
3661 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3663 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3664 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3666 mono_ptr_array_destroy (tmp_array);
3672 property_hash (gconstpointer data)
3674 MonoProperty *prop = (MonoProperty*)data;
3676 return g_str_hash (prop->name);
3680 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3682 // Properties are hide-by-name-and-signature
3683 if (!g_str_equal (prop1->name, prop2->name))
3686 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3688 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3694 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3699 return method_nonpublic (accessor, start_klass);
3703 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3707 static MonoClass *System_Reflection_PropertyInfo;
3708 MonoClass *startklass, *klass;
3714 gchar *propname = NULL;
3715 int (*compare_func) (const char *s1, const char *s2) = NULL;
3717 GHashTable *properties = NULL;
3718 MonoPtrArray tmp_array;
3720 MONO_ARCH_SAVE_REGS;
3722 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3724 if (!System_Reflection_PropertyInfo)
3725 System_Reflection_PropertyInfo = mono_class_from_name (
3726 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3728 domain = ((MonoObject *)type)->vtable->domain;
3729 if (type->type->byref)
3730 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3731 klass = startklass = mono_class_from_mono_type (type->type);
3734 propname = mono_string_to_utf8 (name);
3735 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3738 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3740 mono_class_setup_vtable (klass);
3741 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3745 while ((prop = mono_class_get_properties (klass, &iter))) {
3751 flags = method->flags;
3754 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3755 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3756 if (bflags & BFLAGS_Public)
3758 } else if (bflags & BFLAGS_NonPublic) {
3759 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3760 property_accessor_nonpublic(prop->set, startklass == klass)) {
3767 if (flags & METHOD_ATTRIBUTE_STATIC) {
3768 if (bflags & BFLAGS_Static)
3769 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3772 if (bflags & BFLAGS_Instance)
3781 if (compare_func (propname, prop->name))
3785 if (g_hash_table_lookup (properties, prop))
3788 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3790 g_hash_table_insert (properties, prop, prop);
3792 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3795 g_hash_table_destroy (properties);
3798 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3799 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3800 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3802 mono_ptr_array_destroy (tmp_array);
3808 g_hash_table_destroy (properties);
3811 mono_ptr_array_destroy (tmp_array);
3813 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3814 ex = mono_class_get_exception_for_failure (klass);
3816 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3817 mono_loader_clear_error ();
3819 mono_raise_exception (ex);
3823 static MonoReflectionEvent *
3824 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3827 MonoClass *klass, *startklass;
3832 int (*compare_func) (const char *s1, const char *s2);
3834 MONO_ARCH_SAVE_REGS;
3836 event_name = mono_string_to_utf8 (name);
3837 if (type->type->byref)
3839 klass = startklass = mono_class_from_mono_type (type->type);
3840 domain = mono_object_domain (type);
3842 mono_class_init_or_throw (klass);
3844 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3846 if (klass->exception_type != MONO_EXCEPTION_NONE)
3847 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3850 while ((event = mono_class_get_events (klass, &iter))) {
3851 if (compare_func (event->name, event_name))
3854 method = event->add;
3856 method = event->remove;
3858 method = event->raise;
3860 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3861 if (!(bflags & BFLAGS_Public))
3864 if (!(bflags & BFLAGS_NonPublic))
3866 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3870 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3871 if (!(bflags & BFLAGS_Static))
3873 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3876 if (!(bflags & BFLAGS_Instance))
3880 if (!(bflags & BFLAGS_NonPublic))
3883 g_free (event_name);
3884 return mono_event_get_object (domain, startklass, event);
3887 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3890 g_free (event_name);
3895 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3899 static MonoClass *System_Reflection_EventInfo;
3900 MonoClass *startklass, *klass;
3907 MonoPtrArray tmp_array;
3909 MONO_ARCH_SAVE_REGS;
3911 mono_ptr_array_init (tmp_array, 4);
3913 if (!System_Reflection_EventInfo)
3914 System_Reflection_EventInfo = mono_class_from_name (
3915 mono_defaults.corlib, "System.Reflection", "EventInfo");
3917 domain = mono_object_domain (type);
3918 if (type->type->byref)
3919 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3920 klass = startklass = mono_class_from_mono_type (type->type);
3923 mono_class_setup_vtable (klass);
3924 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3928 while ((event = mono_class_get_events (klass, &iter))) {
3930 method = event->add;
3932 method = event->remove;
3934 method = event->raise;
3936 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3937 if (bflags & BFLAGS_Public)
3939 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3940 if (bflags & BFLAGS_NonPublic)
3945 if (bflags & BFLAGS_NonPublic)
3951 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3952 if (bflags & BFLAGS_Static)
3953 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3956 if (bflags & BFLAGS_Instance)
3961 if (bflags & BFLAGS_Instance)
3965 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3967 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3970 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3972 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3973 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3975 mono_ptr_array_destroy (tmp_array);
3980 mono_ptr_array_destroy (tmp_array);
3981 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3982 ex = mono_class_get_exception_for_failure (klass);
3984 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3985 mono_loader_clear_error ();
3987 mono_raise_exception (ex);
3991 static MonoReflectionType *
3992 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4000 MONO_ARCH_SAVE_REGS;
4003 mono_raise_exception (mono_get_exception_argument_null ("name"));
4005 domain = ((MonoObject *)type)->vtable->domain;
4006 if (type->type->byref)
4008 klass = mono_class_from_mono_type (type->type);
4010 str = mono_string_to_utf8 (name);
4013 if (klass->exception_type != MONO_EXCEPTION_NONE)
4014 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4017 * If a nested type is generic, return its generic type definition.
4018 * Note that this means that the return value is essentially a
4019 * nested type of the generic type definition of @klass.
4021 * A note in MSDN claims that a generic type definition can have
4022 * nested types that aren't generic. In any case, the container of that
4023 * nested type would be the generic type definition.
4025 if (klass->generic_class)
4026 klass = klass->generic_class->container_class;
4029 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4031 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4032 if (bflags & BFLAGS_Public)
4035 if (bflags & BFLAGS_NonPublic)
4040 if (strcmp (nested->name, str) == 0){
4042 return mono_type_get_object (domain, &nested->byval_arg);
4045 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4052 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4061 MonoPtrArray tmp_array;
4063 MONO_ARCH_SAVE_REGS;
4065 domain = ((MonoObject *)type)->vtable->domain;
4066 if (type->type->byref)
4067 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4068 klass = mono_class_from_mono_type (type->type);
4071 * If a nested type is generic, return its generic type definition.
4072 * Note that this means that the return value is essentially the set
4073 * of nested types of the generic type definition of @klass.
4075 * A note in MSDN claims that a generic type definition can have
4076 * nested types that aren't generic. In any case, the container of that
4077 * nested type would be the generic type definition.
4079 if (klass->generic_class)
4080 klass = klass->generic_class->container_class;
4082 mono_ptr_array_init (tmp_array, 1);
4084 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4086 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4087 if (bflags & BFLAGS_Public)
4090 if (bflags & BFLAGS_NonPublic)
4095 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4096 mono_ptr_array_append (tmp_array, member);
4099 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4101 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4102 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4104 mono_ptr_array_destroy (tmp_array);
4109 static MonoReflectionType*
4110 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4113 MonoType *type = NULL;
4114 MonoTypeNameParse info;
4115 gboolean type_resolve;
4117 MONO_ARCH_SAVE_REGS;
4119 /* On MS.NET, this does not fire a TypeResolve event */
4120 type_resolve = TRUE;
4121 str = mono_string_to_utf8 (name);
4122 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4123 if (!mono_reflection_parse_type (str, &info)) {
4125 mono_reflection_free_type_info (&info);
4126 if (throwOnError) /* uhm: this is a parse error, though... */
4127 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4128 /*g_print ("failed parse\n");*/
4132 if (info.assembly.name) {
4134 mono_reflection_free_type_info (&info);
4136 /* 1.0 and 2.0 throw different exceptions */
4137 if (mono_defaults.generic_ilist_class)
4138 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4140 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4145 if (module != NULL) {
4147 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4152 if (assembly->assembly->dynamic) {
4153 /* Enumerate all modules */
4154 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4158 if (abuilder->modules) {
4159 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4160 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4161 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4167 if (!type && abuilder->loaded_modules) {
4168 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4169 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4170 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4177 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4179 mono_reflection_free_type_info (&info);
4181 MonoException *e = NULL;
4184 e = mono_get_exception_type_load (name, NULL);
4186 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4187 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4189 mono_loader_clear_error ();
4192 mono_raise_exception (e);
4195 } else if (mono_loader_get_last_error ()) {
4197 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4198 mono_loader_clear_error ();
4201 if (type->type == MONO_TYPE_CLASS) {
4202 MonoClass *klass = mono_type_get_class (type);
4204 if (mono_is_security_manager_active () && !klass->exception_type)
4205 /* Some security problems are detected during generic vtable construction */
4206 mono_class_setup_vtable (klass);
4207 /* need to report exceptions ? */
4208 if (throwOnError && klass->exception_type) {
4209 /* report SecurityException (or others) that occured when loading the assembly */
4210 MonoException *exc = mono_class_get_exception_for_failure (klass);
4211 mono_loader_clear_error ();
4212 mono_raise_exception (exc);
4213 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4218 /* g_print ("got it\n"); */
4219 return mono_type_get_object (mono_object_domain (assembly), type);
4223 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4226 gchar *shadow_ini_file;
4229 /* Check for shadow-copied assembly */
4230 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4231 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4233 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4234 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4240 g_free (shadow_ini_file);
4241 if (content != NULL) {
4244 *filename = content;
4252 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4254 MonoDomain *domain = mono_object_domain (assembly);
4255 MonoAssembly *mass = assembly->assembly;
4256 MonoString *res = NULL;
4261 MONO_ARCH_SAVE_REGS;
4263 if (g_path_is_absolute (mass->image->name)) {
4264 absolute = g_strdup (mass->image->name);
4265 dirname = g_path_get_dirname (absolute);
4267 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4268 dirname = g_strdup (mass->basedir);
4271 replace_shadow_path (domain, dirname, &absolute);
4276 for (i = strlen (absolute) - 1; i >= 0; i--)
4277 if (absolute [i] == '\\')
4282 uri = g_filename_to_uri (absolute, NULL, NULL);
4284 const char *prepend = "file://";
4286 if (*absolute == '/' && *(absolute + 1) == '/') {
4289 prepend = "file:///";
4292 uri = g_strconcat (prepend, absolute, NULL);
4296 res = mono_string_new (domain, uri);
4304 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4306 MonoAssembly *mass = assembly->assembly;
4308 MONO_ARCH_SAVE_REGS;
4310 return mass->in_gac;
4313 static MonoReflectionAssembly*
4314 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4318 MonoImageOpenStatus status;
4320 MONO_ARCH_SAVE_REGS;
4322 name = mono_string_to_utf8 (mname);
4323 res = mono_assembly_load_with_partial_name (name, &status);
4329 return mono_assembly_get_object (mono_domain_get (), res);
4333 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4335 MonoDomain *domain = mono_object_domain (assembly);
4338 MONO_ARCH_SAVE_REGS;
4340 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4346 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4348 MONO_ARCH_SAVE_REGS;
4350 return assembly->assembly->ref_only;
4354 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4356 MonoDomain *domain = mono_object_domain (assembly);
4358 MONO_ARCH_SAVE_REGS;
4360 return mono_string_new (domain, assembly->assembly->image->version);
4363 static MonoReflectionMethod*
4364 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4366 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4368 MONO_ARCH_SAVE_REGS;
4372 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4375 static MonoReflectionModule*
4376 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4378 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4382 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4384 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4385 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4389 MONO_ARCH_SAVE_REGS;
4391 for (i = 0; i < table->rows; ++i) {
4392 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4393 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4399 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4401 static MonoClass *System_Version = NULL;
4402 static MonoMethod *create_version = NULL;
4406 if (!System_Version) {
4407 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4408 g_assert (System_Version);
4411 if (!create_version) {
4412 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4413 create_version = mono_method_desc_search_in_class (desc, System_Version);
4414 g_assert (create_version);
4415 mono_method_desc_free (desc);
4421 args [3] = &revision;
4422 result = mono_object_new (domain, System_Version);
4423 mono_runtime_invoke (create_version, result, args, NULL);
4429 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4431 static MonoClass *System_Reflection_AssemblyName;
4433 MonoDomain *domain = mono_object_domain (assembly);
4435 static MonoMethod *create_culture = NULL;
4436 MonoImage *image = assembly->assembly->image;
4439 MONO_ARCH_SAVE_REGS;
4441 if (!System_Reflection_AssemblyName)
4442 System_Reflection_AssemblyName = mono_class_from_name (
4443 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4445 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4448 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4450 if (count > 0 && !create_culture) {
4451 MonoMethodDesc *desc = mono_method_desc_new (
4452 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4453 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4454 g_assert (create_culture);
4455 mono_method_desc_free (desc);
4458 for (i = 0; i < count; i++) {
4459 MonoReflectionAssemblyName *aname;
4460 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4462 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4464 aname = (MonoReflectionAssemblyName *) mono_object_new (
4465 domain, System_Reflection_AssemblyName);
4467 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4469 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4470 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4471 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4472 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4473 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4474 aname->versioncompat = 1; /* SameMachine (default) */
4475 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4476 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4478 if (create_culture) {
4480 MonoBoolean assembly_ref = 1;
4481 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4482 args [1] = &assembly_ref;
4483 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4486 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4487 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4488 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4490 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4491 /* public key token isn't copied - the class library will
4492 automatically generate it from the public key if required */
4493 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4494 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4496 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4497 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4500 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4503 /* note: this function doesn't return the codebase on purpose (i.e. it can
4504 be used under partial trust as path information isn't present). */
4506 mono_array_setref (result, i, aname);
4517 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4519 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4521 mono_array_setref (info->res, info->idx, name);
4526 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4528 MonoImage *img = assembly->assembly->image;
4533 MONO_ARCH_SAVE_REGS;
4535 mono_image_lock (img);
4536 mono_image_init_name_cache (img);
4539 len = g_hash_table_size (img->name_cache);
4540 mono_image_unlock (img);
4542 /*we can't create objects holding the image lock */
4543 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4545 mono_image_lock (img);
4546 /*len might have changed, create a new array*/
4547 if (len != g_hash_table_size (img->name_cache))
4552 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4553 mono_image_unlock (img);
4558 /* move this in some file in mono/util/ */
4560 g_concat_dir_and_file (const char *dir, const char *file)
4562 g_return_val_if_fail (dir != NULL, NULL);
4563 g_return_val_if_fail (file != NULL, NULL);
4566 * If the directory name doesn't have a / on the end, we need
4567 * to add one so we get a proper path to the file
4569 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4570 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4572 return g_strconcat (dir, file, NULL);
4576 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4578 char *n = mono_string_to_utf8 (name);
4579 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4581 guint32 cols [MONO_MANIFEST_SIZE];
4582 guint32 impl, file_idx;
4586 MONO_ARCH_SAVE_REGS;
4588 for (i = 0; i < table->rows; ++i) {
4589 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4590 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4591 if (strcmp (val, n) == 0)
4595 if (i == table->rows)
4598 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4601 * this code should only be called after obtaining the
4602 * ResourceInfo and handling the other cases.
4604 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4605 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4607 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4612 module = assembly->assembly->image;
4614 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4616 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4620 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4622 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4624 guint32 cols [MONO_MANIFEST_SIZE];
4625 guint32 file_cols [MONO_FILE_SIZE];
4629 MONO_ARCH_SAVE_REGS;
4631 n = mono_string_to_utf8 (name);
4632 for (i = 0; i < table->rows; ++i) {
4633 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4634 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4635 if (strcmp (val, n) == 0)
4639 if (i == table->rows)
4642 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4643 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4646 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4647 case MONO_IMPLEMENTATION_FILE:
4648 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4649 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4650 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4651 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4652 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4653 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4656 info->location = RESOURCE_LOCATION_EMBEDDED;
4659 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4660 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4661 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4662 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4663 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4664 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4666 mono_raise_exception (ex);
4668 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4670 /* Obtain info recursively */
4671 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4672 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4675 case MONO_IMPLEMENTATION_EXP_TYPE:
4676 g_assert_not_reached ();
4685 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4687 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4688 MonoArray *result = NULL;
4693 MONO_ARCH_SAVE_REGS;
4695 /* check hash if needed */
4697 n = mono_string_to_utf8 (name);
4698 for (i = 0; i < table->rows; ++i) {
4699 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4700 if (strcmp (val, n) == 0) {
4703 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4704 fn = mono_string_new (mono_object_domain (assembly), n);
4706 return (MonoObject*)fn;
4714 for (i = 0; i < table->rows; ++i) {
4715 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4719 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4722 for (i = 0; i < table->rows; ++i) {
4723 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4724 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4725 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4726 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4731 return (MonoObject*)result;
4735 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4737 MonoDomain *domain = mono_domain_get();
4740 int i, j, file_count = 0;
4741 MonoImage **modules;
4742 guint32 module_count, real_module_count;
4743 MonoTableInfo *table;
4744 guint32 cols [MONO_FILE_SIZE];
4745 MonoImage *image = assembly->assembly->image;
4747 g_assert (image != NULL);
4748 g_assert (!assembly->assembly->dynamic);
4750 table = &image->tables [MONO_TABLE_FILE];
4751 file_count = table->rows;
4753 modules = image->modules;
4754 module_count = image->module_count;
4756 real_module_count = 0;
4757 for (i = 0; i < module_count; ++i)
4759 real_module_count ++;
4761 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4762 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4764 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4766 for (i = 0; i < module_count; ++i)
4768 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4772 for (i = 0; i < file_count; ++i, ++j) {
4773 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4774 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4775 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4777 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4779 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4780 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4782 mono_array_setref (res, j, mono_module_get_object (domain, m));
4789 static MonoReflectionMethod*
4790 ves_icall_GetCurrentMethod (void)
4792 MonoMethod *m = mono_method_get_last_managed ();
4794 while (m->is_inflated)
4795 m = ((MonoMethodInflated*)m)->declaring;
4797 return mono_method_get_object (mono_domain_get (), m, NULL);
4802 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4805 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4806 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4807 //method is inflated, we should inflate it on the other class
4808 MonoGenericContext ctx;
4809 ctx.method_inst = inflated->context.method_inst;
4810 ctx.class_inst = inflated->context.class_inst;
4811 if (klass->generic_class)
4812 ctx.class_inst = klass->generic_class->context.class_inst;
4813 else if (klass->generic_container)
4814 ctx.class_inst = klass->generic_container->context.class_inst;
4815 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4818 mono_class_setup_methods (method->klass);
4819 if (method->klass->exception_type)
4821 for (i = 0; i < method->klass->method.count; ++i) {
4822 if (method->klass->methods [i] == method) {
4827 mono_class_setup_methods (klass);
4828 if (klass->exception_type)
4830 g_assert (offset >= 0 && offset < klass->method.count);
4831 return klass->methods [offset];
4834 static MonoReflectionMethod*
4835 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4839 klass = mono_class_from_mono_type (type);
4840 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4842 if (method->klass != klass) {
4843 method = mono_method_get_equivalent_method (method, klass);
4848 klass = method->klass;
4849 return mono_method_get_object (mono_domain_get (), method, klass);
4852 static MonoReflectionMethod*
4853 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4855 return mono_method_get_object (mono_domain_get (), method, NULL);
4858 static MonoReflectionMethodBody*
4859 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4861 return mono_method_body_get_object (mono_domain_get (), method);
4864 static MonoReflectionAssembly*
4865 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4867 MonoMethod *dest = NULL;
4869 MONO_ARCH_SAVE_REGS;
4871 mono_stack_walk_no_il (get_executing, &dest);
4872 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4876 static MonoReflectionAssembly*
4877 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4879 MonoDomain* domain = mono_domain_get ();
4881 MONO_ARCH_SAVE_REGS;
4883 if (!domain->entry_assembly)
4886 return mono_assembly_get_object (domain, domain->entry_assembly);
4889 static MonoReflectionAssembly*
4890 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4895 MONO_ARCH_SAVE_REGS;
4898 mono_stack_walk_no_il (get_executing, &dest);
4900 mono_stack_walk_no_il (get_caller, &dest);
4903 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4907 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4908 gboolean assembly_qualified)
4910 MonoDomain *domain = mono_object_domain (object);
4911 MonoTypeNameFormat format;
4916 format = assembly_qualified ?
4917 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4918 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4920 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4922 name = mono_type_get_name_full (object->type, format);
4926 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4931 res = mono_string_new (domain, name);
4938 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4940 MonoClass *klass = mono_class_from_mono_type (this->type);
4941 mono_class_init_or_throw (klass);
4942 return mono_security_core_clr_class_level (klass);
4946 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4948 static MonoMethod *create_culture = NULL;
4951 const char *pkey_ptr;
4953 MonoBoolean assembly_ref = 0;
4955 MONO_ARCH_SAVE_REGS;
4957 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4958 aname->major = name->major;
4959 aname->minor = name->minor;
4960 aname->build = name->build;
4961 aname->flags = name->flags;
4962 aname->revision = name->revision;
4963 aname->hashalg = name->hash_alg;
4964 aname->versioncompat = 1; /* SameMachine (default) */
4965 aname->processor_architecture = name->arch;
4967 if (by_default_version)
4968 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4971 if (absolute != NULL && *absolute != '\0') {
4972 const gchar *prepend = "file://";
4975 codebase = g_strdup (absolute);
4980 for (i = strlen (codebase) - 1; i >= 0; i--)
4981 if (codebase [i] == '\\')
4984 if (*codebase == '/' && *(codebase + 1) == '/') {
4987 prepend = "file:///";
4991 result = g_strconcat (prepend, codebase, NULL);
4997 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5001 if (!create_culture) {
5002 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5003 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5004 g_assert (create_culture);
5005 mono_method_desc_free (desc);
5008 if (name->culture) {
5009 args [0] = mono_string_new (domain, name->culture);
5010 args [1] = &assembly_ref;
5011 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5014 if (name->public_key) {
5015 pkey_ptr = (char*)name->public_key;
5016 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5018 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5019 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5020 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5021 } else if (default_publickey) {
5022 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5023 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5026 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5027 if (name->public_key_token [0]) {
5031 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5032 p = mono_array_addr (aname->keyToken, char, 0);
5034 for (i = 0, j = 0; i < 8; i++) {
5035 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5036 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5039 } else if (default_token) {
5040 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5045 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5047 MonoDomain *domain = mono_object_domain (assembly);
5048 MonoAssembly *mass = assembly->assembly;
5052 name = mono_stringify_assembly_name (&mass->aname);
5053 res = mono_string_new (domain, name);
5060 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5063 MonoAssembly *mass = assembly->assembly;
5065 MONO_ARCH_SAVE_REGS;
5067 if (g_path_is_absolute (mass->image->name)) {
5068 fill_reflection_assembly_name (mono_object_domain (assembly),
5069 aname, &mass->aname, mass->image->name, TRUE,
5073 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5075 fill_reflection_assembly_name (mono_object_domain (assembly),
5076 aname, &mass->aname, absolute, TRUE, TRUE,
5083 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5086 MonoImageOpenStatus status = MONO_IMAGE_OK;
5089 MonoAssemblyName name;
5092 MONO_ARCH_SAVE_REGS;
5094 filename = mono_string_to_utf8 (fname);
5096 dirname = g_path_get_dirname (filename);
5097 replace_shadow_path (mono_domain_get (), dirname, &filename);
5100 image = mono_image_open (filename, &status);
5106 if (status == MONO_IMAGE_IMAGE_INVALID)
5107 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5109 exc = mono_get_exception_file_not_found2 (NULL, fname);
5110 mono_raise_exception (exc);
5113 res = mono_assembly_fill_assembly_name (image, &name);
5115 mono_image_close (image);
5117 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5120 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5124 mono_image_close (image);
5128 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5129 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5131 MonoBoolean result = FALSE;
5132 MonoDeclSecurityEntry entry;
5134 /* SecurityAction.RequestMinimum */
5135 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5136 *minimum = entry.blob;
5137 *minLength = entry.size;
5140 /* SecurityAction.RequestOptional */
5141 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5142 *optional = entry.blob;
5143 *optLength = entry.size;
5146 /* SecurityAction.RequestRefuse */
5147 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5148 *refused = entry.blob;
5149 *refLength = entry.size;
5157 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5161 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5163 guint32 attrs, visibility;
5165 /* we start the count from 1 because we skip the special type <Module> */
5168 for (i = 1; i < tdef->rows; ++i) {
5169 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5170 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5171 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5175 count = tdef->rows - 1;
5177 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5178 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5180 for (i = 1; i < tdef->rows; ++i) {
5181 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5182 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5183 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5184 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5186 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5188 MonoLoaderError *error;
5191 error = mono_loader_get_last_error ();
5192 g_assert (error != NULL);
5194 ex = mono_loader_error_prepare_exception (error);
5195 mono_array_setref (*exceptions, count, ex);
5197 if (mono_loader_get_last_error ())
5198 mono_loader_clear_error ();
5207 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5209 MonoArray *res = NULL;
5210 MonoArray *exceptions = NULL;
5211 MonoImage *image = NULL;
5212 MonoTableInfo *table = NULL;
5215 int i, len, ex_count;
5217 MONO_ARCH_SAVE_REGS;
5219 domain = mono_object_domain (assembly);
5221 g_assert (!assembly->assembly->dynamic);
5222 image = assembly->assembly->image;
5223 table = &image->tables [MONO_TABLE_FILE];
5224 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5226 /* Append data from all modules in the assembly */
5227 for (i = 0; i < table->rows; ++i) {
5228 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5229 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5232 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5233 /* Append the new types to the end of the array */
5234 if (mono_array_length (res2) > 0) {
5236 MonoArray *res3, *ex3;
5238 len1 = mono_array_length (res);
5239 len2 = mono_array_length (res2);
5241 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5242 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5243 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5246 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5247 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5248 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5255 /* the ReflectionTypeLoadException must have all the types (Types property),
5256 * NULL replacing types which throws an exception. The LoaderException must
5257 * contain all exceptions for NULL items.
5260 len = mono_array_length (res);
5263 for (i = 0; i < len; i++) {
5264 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5268 klass = mono_type_get_class (t->type);
5269 if ((klass != NULL) && klass->exception_type) {
5270 /* keep the class in the list */
5271 list = g_list_append (list, klass);
5272 /* and replace Type with NULL */
5273 mono_array_setref (res, i, NULL);
5280 if (list || ex_count) {
5282 MonoException *exc = NULL;
5283 MonoArray *exl = NULL;
5284 int j, length = g_list_length (list) + ex_count;
5286 mono_loader_clear_error ();
5288 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5289 /* Types for which mono_class_get () succeeded */
5290 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5291 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5292 mono_array_setref (exl, i, exc);
5294 /* Types for which it don't */
5295 for (j = 0; j < mono_array_length (exceptions); ++j) {
5296 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5298 g_assert (i < length);
5299 mono_array_setref (exl, i, exc);
5306 exc = mono_get_exception_reflection_type_load (res, exl);
5307 mono_loader_clear_error ();
5308 mono_raise_exception (exc);
5315 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5317 MonoAssemblyName aname;
5318 MonoDomain *domain = mono_object_domain (name);
5320 gboolean is_version_defined;
5321 gboolean is_token_defined;
5323 aname.public_key = NULL;
5324 val = mono_string_to_utf8 (assname);
5325 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5326 g_free ((guint8*) aname.public_key);
5331 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5332 FALSE, is_token_defined);
5334 mono_assembly_name_free (&aname);
5335 g_free ((guint8*) aname.public_key);
5341 static MonoReflectionType*
5342 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5344 MonoDomain *domain = mono_object_domain (module);
5347 MONO_ARCH_SAVE_REGS;
5349 g_assert (module->image);
5351 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5352 /* These images do not have a global type */
5355 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5356 return mono_type_get_object (domain, &klass->byval_arg);
5360 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5362 /*if (module->image)
5363 mono_image_close (module->image);*/
5367 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5369 MonoDomain *domain = mono_object_domain (module);
5371 MONO_ARCH_SAVE_REGS;
5373 g_assert (module->image);
5374 return mono_string_new (domain, module->image->guid);
5378 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5381 if (module->image && module->image->is_module_handle)
5382 return module->image->raw_data;
5385 return (gpointer) (-1);
5389 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5391 if (image->dynamic) {
5392 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5393 *pe_kind = dyn->pe_kind;
5394 *machine = dyn->machine;
5397 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5398 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5403 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5405 return (image->md_version_major << 16) | (image->md_version_minor);
5409 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5411 MonoArray *exceptions;
5414 MONO_ARCH_SAVE_REGS;
5417 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5419 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5420 for (i = 0; i < mono_array_length (exceptions); ++i) {
5421 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5423 mono_raise_exception (ex);
5430 mono_memberref_is_method (MonoImage *image, guint32 token)
5432 if (!image->dynamic) {
5433 guint32 cols [MONO_MEMBERREF_SIZE];
5435 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5436 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5437 mono_metadata_decode_blob_size (sig, &sig);
5438 return (*sig != 0x6);
5440 MonoClass *handle_class;
5442 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5445 return mono_defaults.methodhandle_class == handle_class;
5450 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5453 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5454 mono_array_addr (type_args, MonoType*, 0));
5456 context->class_inst = NULL;
5458 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5459 mono_array_addr (method_args, MonoType*, 0));
5461 context->method_inst = NULL;
5465 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5468 int table = mono_metadata_token_table (token);
5469 int index = mono_metadata_token_index (token);
5470 MonoGenericContext context;
5472 *error = ResolveTokenError_Other;
5474 /* Validate token */
5475 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5476 (table != MONO_TABLE_TYPESPEC)) {
5477 *error = ResolveTokenError_BadTable;
5481 if (image->dynamic) {
5482 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5483 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5484 return klass ? &klass->byval_arg : NULL;
5487 init_generic_context_from_args (&context, type_args, method_args);
5488 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5489 return klass ? &klass->byval_arg : NULL;
5492 if ((index <= 0) || (index > image->tables [table].rows)) {
5493 *error = ResolveTokenError_OutOfRange;
5497 init_generic_context_from_args (&context, type_args, method_args);
5498 klass = mono_class_get_full (image, token, &context);
5500 if (mono_loader_get_last_error ())
5501 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5504 return &klass->byval_arg;
5510 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5512 int table = mono_metadata_token_table (token);
5513 int index = mono_metadata_token_index (token);
5514 MonoGenericContext context;
5517 *error = ResolveTokenError_Other;
5519 /* Validate token */
5520 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5521 (table != MONO_TABLE_MEMBERREF)) {
5522 *error = ResolveTokenError_BadTable;
5526 if (image->dynamic) {
5527 if (table == MONO_TABLE_METHOD)
5528 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5530 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5531 *error = ResolveTokenError_BadTable;
5535 init_generic_context_from_args (&context, type_args, method_args);
5536 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5539 if ((index <= 0) || (index > image->tables [table].rows)) {
5540 *error = ResolveTokenError_OutOfRange;
5543 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5544 *error = ResolveTokenError_BadTable;
5548 init_generic_context_from_args (&context, type_args, method_args);
5549 method = mono_get_method_full (image, token, NULL, &context);
5551 if (mono_loader_get_last_error ())
5552 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5558 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5560 int index = mono_metadata_token_index (token);
5562 *error = ResolveTokenError_Other;
5564 /* Validate token */
5565 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5566 *error = ResolveTokenError_BadTable;
5571 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5573 if ((index <= 0) || (index >= image->heap_us.size)) {
5574 *error = ResolveTokenError_OutOfRange;
5578 /* FIXME: What to do if the index points into the middle of a string ? */
5580 return mono_ldstr (mono_domain_get (), image, index);
5583 static MonoClassField*
5584 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5587 int table = mono_metadata_token_table (token);
5588 int index = mono_metadata_token_index (token);
5589 MonoGenericContext context;
5590 MonoClassField *field;
5592 *error = ResolveTokenError_Other;
5594 /* Validate token */
5595 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5596 *error = ResolveTokenError_BadTable;
5600 if (image->dynamic) {
5601 if (table == MONO_TABLE_FIELD)
5602 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5604 if (mono_memberref_is_method (image, token)) {
5605 *error = ResolveTokenError_BadTable;
5609 init_generic_context_from_args (&context, type_args, method_args);
5610 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5613 if ((index <= 0) || (index > image->tables [table].rows)) {
5614 *error = ResolveTokenError_OutOfRange;
5617 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5618 *error = ResolveTokenError_BadTable;
5622 init_generic_context_from_args (&context, type_args, method_args);
5623 field = mono_field_from_token (image, token, &klass, &context);
5625 if (mono_loader_get_last_error ())
5626 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5633 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5635 int table = mono_metadata_token_table (token);
5637 *error = ResolveTokenError_Other;
5640 case MONO_TABLE_TYPEDEF:
5641 case MONO_TABLE_TYPEREF:
5642 case MONO_TABLE_TYPESPEC: {
5643 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5645 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5649 case MONO_TABLE_METHOD:
5650 case MONO_TABLE_METHODSPEC: {
5651 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5653 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5657 case MONO_TABLE_FIELD: {
5658 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5660 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5664 case MONO_TABLE_MEMBERREF:
5665 if (mono_memberref_is_method (image, token)) {
5666 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5668 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5673 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5675 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5682 *error = ResolveTokenError_BadTable;
5689 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5691 int table = mono_metadata_token_table (token);
5692 int idx = mono_metadata_token_index (token);
5693 MonoTableInfo *tables = image->tables;
5698 *error = ResolveTokenError_OutOfRange;
5700 /* FIXME: Support other tables ? */
5701 if (table != MONO_TABLE_STANDALONESIG)
5707 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5710 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5712 ptr = mono_metadata_blob_heap (image, sig);
5713 len = mono_metadata_decode_blob_size (ptr, &ptr);
5715 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5716 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5720 static MonoReflectionType*
5721 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5724 int isbyref = 0, rank;
5725 char *str = mono_string_to_utf8 (smodifiers);
5728 MONO_ARCH_SAVE_REGS;
5730 klass = mono_class_from_mono_type (tb->type.type);
5732 /* logic taken from mono_reflection_parse_type(): keep in sync */
5736 if (isbyref) { /* only one level allowed by the spec */
5743 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5746 klass = mono_ptr_class_get (&klass->byval_arg);
5747 mono_class_init (klass);
5758 else if (*p != '*') { /* '*' means unknown lower bound */
5769 klass = mono_array_class_get (klass, rank);
5770 mono_class_init (klass);
5777 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5781 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5786 MONO_ARCH_SAVE_REGS;
5789 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5795 check_for_invalid_type (MonoClass *klass)
5799 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5802 name = mono_type_get_full_name (klass);
5803 str = mono_string_new (mono_domain_get (), name);
5805 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5808 static MonoReflectionType *
5809 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5811 MonoClass *klass, *aklass;
5813 MONO_ARCH_SAVE_REGS;
5815 klass = mono_class_from_mono_type (type->type);
5816 check_for_invalid_type (klass);
5818 if (rank == 0) //single dimentional array
5819 aklass = mono_array_class_get (klass, 1);
5821 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5823 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5826 static MonoReflectionType *
5827 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5831 MONO_ARCH_SAVE_REGS;
5833 klass = mono_class_from_mono_type (type->type);
5834 mono_class_init_or_throw (klass);
5835 check_for_invalid_type (klass);
5837 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5840 static MonoReflectionType *
5841 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5843 MonoClass *klass, *pklass;
5845 klass = mono_class_from_mono_type (type->type);
5846 mono_class_init_or_throw (klass);
5847 check_for_invalid_type (klass);
5849 pklass = mono_ptr_class_get (type->type);
5851 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5855 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5856 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5858 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5859 MonoObject *delegate;
5861 MonoMethod *method = info->method;
5863 MONO_ARCH_SAVE_REGS;
5865 mono_class_init_or_throw (delegate_class);
5867 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5869 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5870 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5874 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5876 if (method->dynamic) {
5877 /* Creating a trampoline would leak memory */
5878 func = mono_compile_method (method);
5880 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5881 method = mono_object_get_virtual_method (target, method);
5882 func = mono_create_ftnptr (mono_domain_get (),
5883 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5886 mono_delegate_ctor_with_method (delegate, target, func, method);
5892 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5894 /* Reset the invoke impl to the default one */
5895 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5899 * Magic number to convert a time which is relative to
5900 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5902 #define EPOCH_ADJUST ((guint64)62135596800LL)
5905 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5907 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5910 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5912 convert_to_absolute_date(SYSTEMTIME *date)
5914 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5915 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5916 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5917 /* from the calendar FAQ */
5918 int a = (14 - date->wMonth) / 12;
5919 int y = date->wYear - a;
5920 int m = date->wMonth + 12 * a - 2;
5921 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5923 /* d is now the day of the week for the first of the month (0 == Sunday) */
5925 int day_of_week = date->wDayOfWeek;
5927 /* set day_in_month to the first day in the month which falls on day_of_week */
5928 int day_in_month = 1 + (day_of_week - d);
5929 if (day_in_month <= 0)
5932 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5933 date->wDay = day_in_month + (date->wDay - 1) * 7;
5934 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5941 * Return's the offset from GMT of a local time.
5943 * tm is a local time
5944 * t is the same local time as seconds.
5947 gmt_offset(struct tm *tm, time_t t)
5949 #if defined (HAVE_TM_GMTOFF)
5950 return tm->tm_gmtoff;
5955 g.tm_isdst = tm->tm_isdst;
5957 return (int)difftime(t, t2);
5962 * This is heavily based on zdump.c from glibc 2.2.
5964 * * data[0]: start of daylight saving time (in DateTime ticks).
5965 * * data[1]: end of daylight saving time (in DateTime ticks).
5966 * * data[2]: utcoffset (in TimeSpan ticks).
5967 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5968 * * name[0]: name of this timezone when not daylight saving.
5969 * * name[1]: name of this timezone when daylight saving.
5971 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5972 * the class library allows years between 1 and 9999.
5974 * Returns true on success and zero on failure.
5977 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5980 MonoDomain *domain = mono_domain_get ();
5981 struct tm start, tt;
5985 int is_daylight = 0, day;
5988 MONO_ARCH_SAVE_REGS;
5990 MONO_CHECK_ARG_NULL (data);
5991 MONO_CHECK_ARG_NULL (names);
5993 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5994 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5997 * no info is better than crashing: we'll need our own tz data
5998 * to make this work properly, anyway. The range is probably
5999 * reduced to 1970 .. 2037 because that is what mktime is
6000 * guaranteed to support (we get into an infinite loop
6004 memset (&start, 0, sizeof (start));
6007 start.tm_year = year-1900;
6009 t = mktime (&start);
6011 if ((year < 1970) || (year > 2037) || (t == -1)) {
6013 tt = *localtime (&t);
6014 strftime (tzone, sizeof (tzone), "%Z", &tt);
6015 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6016 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6020 gmtoff = gmt_offset (&start, t);
6022 /* For each day of the year, calculate the tm_gmtoff. */
6023 for (day = 0; day < 365; day++) {
6026 tt = *localtime (&t);
6028 /* Daylight saving starts or ends here. */
6029 if (gmt_offset (&tt, t) != gmtoff) {
6033 /* Try to find the exact hour when daylight saving starts/ends. */
6037 tt1 = *localtime (&t1);
6038 } while (gmt_offset (&tt1, t1) != gmtoff);
6040 /* Try to find the exact minute when daylight saving starts/ends. */
6043 tt1 = *localtime (&t1);
6044 } while (gmt_offset (&tt1, t1) == gmtoff);
6046 strftime (tzone, sizeof (tzone), "%Z", &tt);
6048 /* Write data, if we're already in daylight saving, we're done. */
6050 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6051 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6054 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6055 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6059 /* This is only set once when we enter daylight saving. */
6060 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6061 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6063 gmtoff = gmt_offset (&tt, t);
6068 strftime (tzone, sizeof (tzone), "%Z", &tt);
6069 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6070 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6071 mono_array_set ((*data), gint64, 0, 0);
6072 mono_array_set ((*data), gint64, 1, 0);
6073 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6074 mono_array_set ((*data), gint64, 3, 0);
6079 MonoDomain *domain = mono_domain_get ();
6080 TIME_ZONE_INFORMATION tz_info;
6085 tz_id = GetTimeZoneInformation (&tz_info);
6086 if (tz_id == TIME_ZONE_ID_INVALID)
6089 MONO_CHECK_ARG_NULL (data);
6090 MONO_CHECK_ARG_NULL (names);
6092 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6093 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6095 for (i = 0; i < 32; ++i)
6096 if (!tz_info.DaylightName [i])
6098 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6099 for (i = 0; i < 32; ++i)
6100 if (!tz_info.StandardName [i])
6102 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6104 if ((year <= 1601) || (year > 30827)) {
6106 * According to MSDN, the MS time functions can't handle dates outside
6112 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6113 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6114 tz_info.StandardDate.wYear = year;
6115 convert_to_absolute_date(&tz_info.StandardDate);
6116 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6121 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6122 tz_info.DaylightDate.wYear = year;
6123 convert_to_absolute_date(&tz_info.DaylightDate);
6124 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6129 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6131 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6132 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6139 ves_icall_System_Object_obj_address (MonoObject *this)
6141 MONO_ARCH_SAVE_REGS;
6148 static inline gint32
6149 mono_array_get_byte_length (MonoArray *array)
6155 klass = array->obj.vtable->klass;
6157 if (array->bounds == NULL)
6158 length = array->max_length;
6161 for (i = 0; i < klass->rank; ++ i)
6162 length *= array->bounds [i].length;
6165 switch (klass->element_class->byval_arg.type) {
6168 case MONO_TYPE_BOOLEAN:
6172 case MONO_TYPE_CHAR:
6180 return length * sizeof (gpointer);
6191 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6193 MONO_ARCH_SAVE_REGS;
6195 return mono_array_get_byte_length (array);
6199 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6201 MONO_ARCH_SAVE_REGS;
6203 return mono_array_get (array, gint8, idx);
6207 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6209 MONO_ARCH_SAVE_REGS;
6211 mono_array_set (array, gint8, idx, value);
6215 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6217 guint8 *src_buf, *dest_buf;
6219 MONO_ARCH_SAVE_REGS;
6221 /* watch out for integer overflow */
6222 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6225 src_buf = (guint8 *)src->vector + src_offset;
6226 dest_buf = (guint8 *)dest->vector + dest_offset;
6229 memcpy (dest_buf, src_buf, count);
6231 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6237 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6239 MonoDomain *domain = mono_object_domain (this);
6241 MonoRealProxy *rp = ((MonoRealProxy *)this);
6242 MonoTransparentProxy *tp;
6246 MONO_ARCH_SAVE_REGS;
6248 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6249 tp = (MonoTransparentProxy*) res;
6251 MONO_OBJECT_SETREF (tp, rp, rp);
6252 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6253 klass = mono_class_from_mono_type (type);
6255 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6256 tp->remote_class = mono_remote_class (domain, class_name, klass);
6258 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6262 static MonoReflectionType *
6263 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6265 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6268 /* System.Environment */
6271 ves_icall_System_Environment_get_UserName (void)
6273 MONO_ARCH_SAVE_REGS;
6275 /* using glib is more portable */
6276 return mono_string_new (mono_domain_get (), g_get_user_name ());
6281 ves_icall_System_Environment_get_MachineName (void)
6283 #if defined (HOST_WIN32)
6288 len = MAX_COMPUTERNAME_LENGTH + 1;
6289 buf = g_new (gunichar2, len);
6292 if (GetComputerName (buf, (PDWORD) &len))
6293 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6297 #elif !defined(DISABLE_SOCKETS)
6301 if (gethostname (buf, sizeof (buf)) == 0)
6302 result = mono_string_new (mono_domain_get (), buf);
6308 return mono_string_new (mono_domain_get (), "mono");
6313 ves_icall_System_Environment_get_Platform (void)
6315 #if defined (TARGET_WIN32)
6318 #elif defined(__MACH__)
6321 // Notice that the value is hidden from user code, and only exposed
6322 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6323 // define and making assumptions based on Unix/128/4 values before there
6324 // was a MacOS define. Lots of code would assume that not-Unix meant
6325 // Windows, but in this case, it would be OSX.
6335 ves_icall_System_Environment_get_NewLine (void)
6337 MONO_ARCH_SAVE_REGS;
6339 #if defined (HOST_WIN32)
6340 return mono_string_new (mono_domain_get (), "\r\n");
6342 return mono_string_new (mono_domain_get (), "\n");
6347 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6352 MONO_ARCH_SAVE_REGS;
6357 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6358 value = g_getenv (utf8_name);
6365 return mono_string_new (mono_domain_get (), value);
6369 * There is no standard way to get at environ.
6372 #ifndef __MINGW32_VERSION
6373 #if defined(__APPLE__) && !defined (__arm__)
6374 /* Apple defines this in crt_externs.h but doesn't provide that header for
6375 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6376 * in fact exist on all implementations (so far)
6378 gchar ***_NSGetEnviron(void);
6379 #define environ (*_NSGetEnviron())
6388 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6399 env_strings = GetEnvironmentStrings();
6402 env_string = env_strings;
6403 while (*env_string != '\0') {
6404 /* weird case that MS seems to skip */
6405 if (*env_string != '=')
6407 while (*env_string != '\0')
6413 domain = mono_domain_get ();
6414 names = mono_array_new (domain, mono_defaults.string_class, n);
6418 env_string = env_strings;
6419 while (*env_string != '\0') {
6420 /* weird case that MS seems to skip */
6421 if (*env_string != '=') {
6422 equal_str = wcschr(env_string, '=');
6423 g_assert(equal_str);
6424 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6425 mono_array_setref (names, n, str);
6428 while (*env_string != '\0')
6433 FreeEnvironmentStrings (env_strings);
6445 MONO_ARCH_SAVE_REGS;
6448 for (e = environ; *e != 0; ++ e)
6451 domain = mono_domain_get ();
6452 names = mono_array_new (domain, mono_defaults.string_class, n);
6455 for (e = environ; *e != 0; ++ e) {
6456 parts = g_strsplit (*e, "=", 2);
6458 str = mono_string_new (domain, *parts);
6459 mono_array_setref (names, n, str);
6472 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6474 #if !GLIB_CHECK_VERSION(2,4,0)
6475 #define g_setenv(a,b,c) setenv(a,b,c)
6476 #define g_unsetenv(a) unsetenv(a)
6480 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6485 gunichar2 *utf16_name, *utf16_value;
6487 gchar *utf8_name, *utf8_value;
6490 MONO_ARCH_SAVE_REGS;
6493 utf16_name = mono_string_to_utf16 (name);
6494 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6495 SetEnvironmentVariable (utf16_name, NULL);
6496 g_free (utf16_name);
6500 utf16_value = mono_string_to_utf16 (value);
6502 SetEnvironmentVariable (utf16_name, utf16_value);
6504 g_free (utf16_name);
6505 g_free (utf16_value);
6507 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6509 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6510 g_unsetenv (utf8_name);
6515 utf8_value = mono_string_to_utf8_checked (value, &error);
6516 if (!mono_error_ok (&error)) {
6518 mono_error_raise_exception (&error);
6520 g_setenv (utf8_name, utf8_value, TRUE);
6523 g_free (utf8_value);
6528 ves_icall_System_Environment_Exit (int result)
6530 MONO_ARCH_SAVE_REGS;
6532 mono_threads_set_shutting_down ();
6534 mono_runtime_set_shutting_down ();
6536 /* This will kill the tp threads which cannot be suspended */
6537 mono_thread_pool_cleanup ();
6539 /* Suspend all managed threads since the runtime is going away */
6540 mono_thread_suspend_all_other_threads ();
6542 mono_runtime_quit ();
6544 /* we may need to do some cleanup here... */
6549 ves_icall_System_Environment_GetGacPath (void)
6551 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6555 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6557 #if defined (HOST_WIN32)
6558 #ifndef CSIDL_FLAG_CREATE
6559 #define CSIDL_FLAG_CREATE 0x8000
6562 WCHAR path [MAX_PATH];
6563 /* Create directory if no existing */
6564 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6568 return mono_string_new_utf16 (mono_domain_get (), path, len);
6571 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6573 return mono_string_new (mono_domain_get (), "");
6577 ves_icall_System_Environment_GetLogicalDrives (void)
6579 gunichar2 buf [256], *ptr, *dname;
6581 guint initial_size = 127, size = 128;
6584 MonoString *drivestr;
6585 MonoDomain *domain = mono_domain_get ();
6588 MONO_ARCH_SAVE_REGS;
6593 while (size > initial_size) {
6594 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6595 if (size > initial_size) {
6598 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6599 initial_size = size;
6613 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6618 while (*u16) { u16++; len ++; }
6619 drivestr = mono_string_new_utf16 (domain, dname, len);
6620 mono_array_setref (result, ndrives++, drivestr);
6631 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6633 gunichar2 volume_name [MAX_PATH + 1];
6635 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6637 return mono_string_from_utf16 (volume_name);
6641 ves_icall_System_Environment_InternalGetHome (void)
6643 MONO_ARCH_SAVE_REGS;
6645 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6648 static const char *encodings [] = {
6650 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6651 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6652 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6654 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6655 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6656 "x_unicode_2_0_utf_7",
6658 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6659 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6661 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6664 "unicodefffe", "utf_16be",
6671 * Returns the internal codepage, if the value of "int_code_page" is
6672 * 1 at entry, and we can not compute a suitable code page number,
6673 * returns the code page as a string
6676 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6681 char *codepage = NULL;
6683 int want_name = *int_code_page;
6686 *int_code_page = -1;
6687 MONO_ARCH_SAVE_REGS;
6689 g_get_charset (&cset);
6690 c = codepage = strdup (cset);
6691 for (c = codepage; *c; c++){
6692 if (isascii (*c) && isalpha (*c))
6697 /* g_print ("charset: %s\n", cset); */
6699 /* handle some common aliases */
6702 for (i = 0; p != 0; ){
6703 if ((gssize) p < 7){
6705 p = encodings [++i];
6708 if (strcmp (p, codepage) == 0){
6709 *int_code_page = code;
6712 p = encodings [++i];
6715 if (strstr (codepage, "utf_8") != NULL)
6716 *int_code_page |= 0x10000000;
6719 if (want_name && *int_code_page == -1)
6720 return mono_string_new (mono_domain_get (), cset);
6726 ves_icall_System_Environment_get_HasShutdownStarted (void)
6728 if (mono_runtime_is_shutting_down ())
6731 if (mono_domain_is_unloading (mono_domain_get ()))
6738 ves_icall_System_Environment_BroadcastSettingChange (void)
6741 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6746 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6747 MonoReflectionMethod *method,
6748 MonoArray *out_args)
6750 MONO_ARCH_SAVE_REGS;
6752 mono_message_init (mono_object_domain (this), this, method, out_args);
6756 ves_icall_IsTransparentProxy (MonoObject *proxy)
6758 MONO_ARCH_SAVE_REGS;
6763 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6769 static MonoReflectionMethod *
6770 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6771 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6775 MonoMethod **vtable;
6776 MonoMethod *res = NULL;
6778 MONO_CHECK_ARG_NULL (rtype);
6779 MONO_CHECK_ARG_NULL (rmethod);
6781 method = rmethod->method;
6782 klass = mono_class_from_mono_type (rtype->type);
6783 mono_class_init_or_throw (klass);
6785 if (MONO_CLASS_IS_INTERFACE (klass))
6788 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6791 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6792 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6798 mono_class_setup_vtable (klass);
6799 vtable = klass->vtable;
6801 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6802 gboolean variance_used = FALSE;
6803 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6804 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6806 res = vtable [offs + method->slot];
6808 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6811 if (method->slot != -1)
6812 res = vtable [method->slot];
6818 return mono_method_get_object (mono_domain_get (), res, NULL);
6822 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6827 MONO_ARCH_SAVE_REGS;
6829 klass = mono_class_from_mono_type (type->type);
6830 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6832 if (enable) vtable->remote = 1;
6833 else vtable->remote = 0;
6837 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6842 MONO_ARCH_SAVE_REGS;
6844 domain = mono_object_domain (type);
6845 klass = mono_class_from_mono_type (type->type);
6846 mono_class_init_or_throw (klass);
6848 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6849 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6851 if (klass->rank >= 1) {
6852 g_assert (klass->rank == 1);
6853 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6855 /* Bypass remoting object creation check */
6856 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6861 ves_icall_System_IO_get_temp_path (void)
6863 MONO_ARCH_SAVE_REGS;
6865 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6868 #ifndef PLATFORM_NO_DRIVEINFO
6870 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6871 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6875 ULARGE_INTEGER wapi_free_bytes_avail;
6876 ULARGE_INTEGER wapi_total_number_of_bytes;
6877 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6879 MONO_ARCH_SAVE_REGS;
6881 *error = ERROR_SUCCESS;
6882 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6883 &wapi_total_number_of_free_bytes);
6886 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6887 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6888 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6890 *free_bytes_avail = 0;
6891 *total_number_of_bytes = 0;
6892 *total_number_of_free_bytes = 0;
6893 *error = GetLastError ();
6900 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6902 MONO_ARCH_SAVE_REGS;
6904 return GetDriveType (mono_string_chars (root_path_name));
6909 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6911 MONO_ARCH_SAVE_REGS;
6913 return mono_compile_method (method);
6917 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6922 MONO_ARCH_SAVE_REGS;
6924 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6926 #if defined (HOST_WIN32)
6927 /* Avoid mixing '/' and '\\' */
6930 for (i = strlen (path) - 1; i >= 0; i--)
6931 if (path [i] == '/')
6935 mcpath = mono_string_new (mono_domain_get (), path);
6942 get_bundled_app_config (void)
6944 const gchar *app_config;
6947 gchar *config_file_name, *config_file_path;
6951 MONO_ARCH_SAVE_REGS;
6953 domain = mono_domain_get ();
6954 file = domain->setup->configuration_file;
6958 // Retrieve config file and remove the extension
6959 config_file_name = mono_string_to_utf8 (file);
6960 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6961 if (!config_file_path)
6962 config_file_path = config_file_name;
6963 len = strlen (config_file_path) - strlen (".config");
6964 module = g_malloc0 (len + 1);
6965 memcpy (module, config_file_path, len);
6966 // Get the config file from the module name
6967 app_config = mono_config_string_for_assembly_file (module);
6970 if (config_file_name != config_file_path)
6971 g_free (config_file_name);
6972 g_free (config_file_path);
6977 return mono_string_new (mono_domain_get (), app_config);
6981 get_bundled_machine_config (void)
6983 const gchar *machine_config;
6985 MONO_ARCH_SAVE_REGS;
6987 machine_config = mono_get_machine_config ();
6989 if (!machine_config)
6992 return mono_string_new (mono_domain_get (), machine_config);
6996 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7001 MONO_ARCH_SAVE_REGS;
7003 path = g_path_get_dirname (mono_get_config_dir ());
7005 #if defined (HOST_WIN32)
7006 /* Avoid mixing '/' and '\\' */
7009 for (i = strlen (path) - 1; i >= 0; i--)
7010 if (path [i] == '/')
7014 ipath = mono_string_new (mono_domain_get (), path);
7021 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7023 MonoPEResourceDataEntry *entry;
7026 MONO_ARCH_SAVE_REGS;
7028 if (!assembly || !result || !size)
7033 image = assembly->assembly->image;
7034 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7038 *result = mono_image_rva_map (image, entry->rde_data_offset);
7043 *size = entry->rde_size;
7049 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7051 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7055 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7057 #if defined (HOST_WIN32)
7058 OutputDebugString (mono_string_chars (message));
7060 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7064 /* Only used for value types */
7066 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7071 MONO_ARCH_SAVE_REGS;
7073 domain = mono_object_domain (type);
7074 klass = mono_class_from_mono_type (type->type);
7075 mono_class_init_or_throw (klass);
7077 if (mono_class_is_nullable (klass))
7078 /* No arguments -> null */
7081 return mono_object_new (domain, klass);
7084 static MonoReflectionMethod *
7085 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7087 MonoClass *klass, *parent;
7088 MonoMethod *method = m->method;
7089 MonoMethod *result = NULL;
7092 MONO_ARCH_SAVE_REGS;
7094 if (method->klass == NULL)
7097 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7098 MONO_CLASS_IS_INTERFACE (method->klass) ||
7099 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7102 slot = mono_method_get_vtable_slot (method);
7106 klass = method->klass;
7107 if (klass->generic_class)
7108 klass = klass->generic_class->container_class;
7111 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7112 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7113 mono_class_setup_vtable (parent);
7114 if (parent->vtable_size <= slot)
7119 klass = klass->parent;
7124 if (klass == method->klass)
7127 /*This is possible if definition == FALSE.
7128 * Do it here to be really sure we don't read invalid memory.
7130 if (slot >= klass->vtable_size)
7133 mono_class_setup_vtable (klass);
7135 result = klass->vtable [slot];
7136 if (result == NULL) {
7137 /* It is an abstract method */
7138 gpointer iter = NULL;
7139 while ((result = mono_class_get_methods (klass, &iter)))
7140 if (result->slot == slot)
7147 return mono_method_get_object (mono_domain_get (), result, NULL);
7151 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7153 MonoMethod *method = m->method;
7155 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7160 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7162 MONO_ARCH_SAVE_REGS;
7164 iter->sig = *(MonoMethodSignature**)argsp;
7166 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7167 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7170 /* FIXME: it's not documented what start is exactly... */
7174 iter->args = argsp + sizeof (gpointer);
7176 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7178 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7182 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7184 guint32 i, arg_size;
7187 MONO_ARCH_SAVE_REGS;
7189 i = iter->sig->sentinelpos + iter->next_arg;
7191 g_assert (i < iter->sig->param_count);
7193 res.type = iter->sig->params [i];
7194 res.klass = mono_class_from_mono_type (res.type);
7195 arg_size = mono_type_stack_size (res.type, &align);
7196 #if defined(__arm__)
7197 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7199 res.value = iter->args;
7200 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7201 if (arg_size <= sizeof (gpointer)) {
7203 int padding = arg_size - mono_type_size (res.type, &dummy);
7204 res.value = (guint8*)res.value + padding;
7207 iter->args = (char*)iter->args + arg_size;
7210 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7216 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7218 guint32 i, arg_size;
7221 MONO_ARCH_SAVE_REGS;
7223 i = iter->sig->sentinelpos + iter->next_arg;
7225 g_assert (i < iter->sig->param_count);
7227 while (i < iter->sig->param_count) {
7228 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7230 res.type = iter->sig->params [i];
7231 res.klass = mono_class_from_mono_type (res.type);
7232 /* FIXME: endianess issue... */
7233 arg_size = mono_type_stack_size (res.type, &align);
7234 #if defined(__arm__)
7235 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7237 res.value = iter->args;
7238 iter->args = (char*)iter->args + arg_size;
7240 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7243 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7252 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7255 MONO_ARCH_SAVE_REGS;
7257 i = iter->sig->sentinelpos + iter->next_arg;
7259 g_assert (i < iter->sig->param_count);
7261 return iter->sig->params [i];
7265 mono_TypedReference_ToObject (MonoTypedRef tref)
7267 MONO_ARCH_SAVE_REGS;
7269 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7270 MonoObject** objp = tref.value;
7274 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7278 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7280 MONO_ARCH_SAVE_REGS;
7282 if (MONO_TYPE_IS_REFERENCE (type)) {
7283 MonoObject** objp = value;
7287 return mono_value_box (mono_domain_get (), klass, value);
7291 prelink_method (MonoMethod *method)
7293 const char *exc_class, *exc_arg;
7294 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7296 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7298 mono_raise_exception(
7299 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7301 /* create the wrapper, too? */
7305 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7307 MONO_ARCH_SAVE_REGS;
7308 prelink_method (method->method);
7312 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7314 MonoClass *klass = mono_class_from_mono_type (type->type);
7316 gpointer iter = NULL;
7317 MONO_ARCH_SAVE_REGS;
7319 mono_class_init_or_throw (klass);
7321 while ((m = mono_class_get_methods (klass, &iter)))
7325 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7327 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7328 gint32 const **exponents,
7329 gunichar2 const **digitLowerTable,
7330 gunichar2 const **digitUpperTable,
7331 gint64 const **tenPowersList,
7332 gint32 const **decHexDigits)
7334 *mantissas = Formatter_MantissaBitsTable;
7335 *exponents = Formatter_TensExponentTable;
7336 *digitLowerTable = Formatter_DigitLowerTable;
7337 *digitUpperTable = Formatter_DigitUpperTable;
7338 *tenPowersList = Formatter_TenPowersList;
7339 *decHexDigits = Formatter_DecHexDigits;
7342 /* These parameters are "readonly" in corlib/System/Char.cs */
7344 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7345 guint8 const **numeric_data,
7346 gdouble const **numeric_data_values,
7347 guint16 const **to_lower_data_low,
7348 guint16 const **to_lower_data_high,
7349 guint16 const **to_upper_data_low,
7350 guint16 const **to_upper_data_high)
7352 *category_data = CategoryData;
7353 *numeric_data = NumericData;
7354 *numeric_data_values = NumericDataValues;
7355 *to_lower_data_low = ToLowerDataLow;
7356 *to_lower_data_high = ToLowerDataHigh;
7357 *to_upper_data_low = ToUpperDataLow;
7358 *to_upper_data_high = ToUpperDataHigh;
7362 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7364 return method->method->token;
7368 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7369 * and avoid useless allocations.
7372 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7376 for (i = 0; i < type->num_mods; ++i) {
7377 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7382 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7384 for (i = 0; i < type->num_mods; ++i) {
7385 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7386 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7387 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7395 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7397 MonoType *type = param->ClassImpl->type;
7398 MonoClass *member_class = mono_object_class (param->MemberImpl);
7399 MonoMethod *method = NULL;
7402 MonoMethodSignature *sig;
7404 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7405 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7406 method = rmethod->method;
7407 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7408 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7409 if (!(method = prop->property->get))
7410 method = prop->property->set;
7413 char *type_name = mono_type_get_full_name (member_class);
7414 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7415 MonoException *ex = mono_get_exception_not_supported (msg);
7418 mono_raise_exception (ex);
7421 image = method->klass->image;
7422 pos = param->PositionImpl;
7423 sig = mono_method_signature (method);
7427 type = sig->params [pos];
7429 return type_array_from_modifiers (image, type, optional);
7433 get_property_type (MonoProperty *prop)
7435 MonoMethodSignature *sig;
7437 sig = mono_method_signature (prop->get);
7439 } else if (prop->set) {
7440 sig = mono_method_signature (prop->set);
7441 return sig->params [sig->param_count - 1];
7447 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7449 MonoType *type = get_property_type (property->property);
7450 MonoImage *image = property->klass->image;
7454 return type_array_from_modifiers (image, type, optional);
7458 *Construct a MonoType suited to be used to decode a constant blob object.
7460 * @type is the target type which will be constructed
7461 * @blob_type is the blob type, for example, that comes from the constant table
7462 * @real_type is the expected constructed type.
7465 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7467 type->type = blob_type;
7468 type->data.klass = NULL;
7469 if (blob_type == MONO_TYPE_CLASS)
7470 type->data.klass = mono_defaults.object_class;
7471 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7472 /* For enums, we need to use the base type */
7473 type->type = MONO_TYPE_VALUETYPE;
7474 type->data.klass = mono_class_from_mono_type (real_type);
7476 type->data.klass = mono_class_from_mono_type (real_type);
7480 property_info_get_default_value (MonoReflectionProperty *property)
7483 MonoProperty *prop = property->property;
7484 MonoType *type = get_property_type (prop);
7485 MonoDomain *domain = mono_object_domain (property);
7486 MonoTypeEnum def_type;
7487 const char *def_value;
7490 mono_class_init (prop->parent);
7492 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7493 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7495 def_value = mono_class_get_property_default_value (prop, &def_type);
7497 mono_type_from_blob_type (&blob_type, def_type, type);
7498 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7504 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7506 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7507 MonoCustomAttrInfo *cinfo;
7510 mono_class_init_or_throw (attr_class);
7512 cinfo = mono_reflection_get_custom_attrs_info (obj);
7515 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7517 mono_custom_attrs_free (cinfo);
7522 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7524 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7529 mono_class_init_or_throw (attr_class);
7531 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7532 if (!mono_error_ok (&error))
7533 mono_error_raise_exception (&error);
7534 if (mono_loader_get_last_error ()) {
7535 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7536 g_assert_not_reached ();
7545 ves_icall_Mono_Runtime_GetDisplayName (void)
7548 MonoString *display_name;
7550 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7551 display_name = mono_string_new (mono_domain_get (), info);
7553 return display_name;
7557 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7559 MonoString *message;
7563 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7564 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7567 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7569 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7577 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7578 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7579 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7580 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7581 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7582 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7583 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7584 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7588 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7593 gunichar2 last, prev_last, prev2_last;
7601 last = prev_last = 0, prev2_last = 0;
7602 for (i = 0; i < ilength; i++) {
7604 if (c >= sizeof (dbase64)) {
7605 exc = mono_exception_from_name_msg (mono_get_corlib (),
7606 "System", "FormatException",
7607 "Invalid character found.");
7608 mono_raise_exception (exc);
7609 } else if (isspace (c)) {
7612 prev2_last = prev_last;
7618 olength = ilength - ignored;
7620 if (allowWhitespaceOnly && olength == 0) {
7621 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7624 if ((olength & 3) != 0 || olength <= 0) {
7625 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7626 "FormatException", "Invalid length.");
7627 mono_raise_exception (exc);
7630 if (prev2_last == '=') {
7631 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7632 mono_raise_exception (exc);
7635 olength = (olength * 3) / 4;
7639 if (prev_last == '=')
7642 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7643 res_ptr = mono_array_addr (result, guchar, 0);
7644 for (i = 0; i < ilength; ) {
7647 for (k = 0; k < 4 && i < ilength;) {
7653 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7654 exc = mono_exception_from_name_msg (mono_get_corlib (),
7655 "System", "FormatException",
7656 "Invalid character found.");
7657 mono_raise_exception (exc);
7662 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7664 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7666 *res_ptr++ = (b [2] << 6) | b [3];
7668 while (i < ilength && isspace (start [i]))
7676 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7678 MONO_ARCH_SAVE_REGS;
7680 return base64_to_byte_array (mono_string_chars (str),
7681 mono_string_length (str), allowWhitespaceOnly);
7685 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7687 MONO_ARCH_SAVE_REGS;
7689 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7693 #define ICALL_TYPE(id,name,first)
7694 #define ICALL(id,name,func) Icall_ ## id,
7697 #include "metadata/icall-def.h"
7703 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7704 #define ICALL(id,name,func)
7706 #include "metadata/icall-def.h"
7712 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7713 #define ICALL(id,name,func)
7715 guint16 first_icall;
7718 static const IcallTypeDesc
7719 icall_type_descs [] = {
7720 #include "metadata/icall-def.h"
7724 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7727 #define ICALL_TYPE(id,name,first)
7730 #ifdef HAVE_ARRAY_ELEM_INIT
7731 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7732 #define MSGSTRFIELD1(line) str##line
7734 static const struct msgstrtn_t {
7735 #define ICALL(id,name,func)
7737 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7738 #include "metadata/icall-def.h"
7740 } icall_type_names_str = {
7741 #define ICALL_TYPE(id,name,first) (name),
7742 #include "metadata/icall-def.h"
7745 static const guint16 icall_type_names_idx [] = {
7746 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7747 #include "metadata/icall-def.h"
7750 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7752 static const struct msgstr_t {
7754 #define ICALL_TYPE(id,name,first)
7755 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7756 #include "metadata/icall-def.h"
7758 } icall_names_str = {
7759 #define ICALL(id,name,func) (name),
7760 #include "metadata/icall-def.h"
7763 static const guint16 icall_names_idx [] = {
7764 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7765 #include "metadata/icall-def.h"
7768 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7774 #define ICALL_TYPE(id,name,first) name,
7775 #define ICALL(id,name,func)
7776 static const char* const
7777 icall_type_names [] = {
7778 #include "metadata/icall-def.h"
7782 #define icall_type_name_get(id) (icall_type_names [(id)])
7786 #define ICALL_TYPE(id,name,first)
7787 #define ICALL(id,name,func) name,
7788 static const char* const
7790 #include "metadata/icall-def.h"
7793 #define icall_name_get(id) icall_names [(id)]
7795 #endif /* !HAVE_ARRAY_ELEM_INIT */
7799 #define ICALL_TYPE(id,name,first)
7800 #define ICALL(id,name,func) func,
7801 static const gconstpointer
7802 icall_functions [] = {
7803 #include "metadata/icall-def.h"
7807 static GHashTable *icall_hash = NULL;
7808 static GHashTable *jit_icall_hash_name = NULL;
7809 static GHashTable *jit_icall_hash_addr = NULL;
7812 mono_icall_init (void)
7816 /* check that tables are sorted: disable in release */
7819 const char *prev_class = NULL;
7820 const char *prev_method;
7822 for (i = 0; i < Icall_type_num; ++i) {
7823 const IcallTypeDesc *desc;
7826 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7827 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7828 prev_class = icall_type_name_get (i);
7829 desc = &icall_type_descs [i];
7830 num_icalls = icall_desc_num_icalls (desc);
7831 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7832 for (j = 0; j < num_icalls; ++j) {
7833 const char *methodn = icall_name_get (desc->first_icall + j);
7834 if (prev_method && strcmp (prev_method, methodn) >= 0)
7835 g_print ("method %s should come before method %s\n", methodn, prev_method);
7836 prev_method = methodn;
7841 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7845 mono_icall_cleanup (void)
7847 g_hash_table_destroy (icall_hash);
7848 g_hash_table_destroy (jit_icall_hash_name);
7849 g_hash_table_destroy (jit_icall_hash_addr);
7853 mono_add_internal_call (const char *name, gconstpointer method)
7855 mono_loader_lock ();
7857 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7859 mono_loader_unlock ();
7862 #ifdef HAVE_ARRAY_ELEM_INIT
7864 compare_method_imap (const void *key, const void *elem)
7866 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7867 return strcmp (key, method_name);
7871 find_method_icall (const IcallTypeDesc *imap, const char *name)
7873 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7876 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7880 compare_class_imap (const void *key, const void *elem)
7882 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7883 return strcmp (key, class_name);
7886 static const IcallTypeDesc*
7887 find_class_icalls (const char *name)
7889 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7892 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7897 compare_method_imap (const void *key, const void *elem)
7899 const char** method_name = (const char**)elem;
7900 return strcmp (key, *method_name);
7904 find_method_icall (const IcallTypeDesc *imap, const char *name)
7906 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7909 return (gpointer)icall_functions [(nameslot - icall_names)];
7913 compare_class_imap (const void *key, const void *elem)
7915 const char** class_name = (const char**)elem;
7916 return strcmp (key, *class_name);
7919 static const IcallTypeDesc*
7920 find_class_icalls (const char *name)
7922 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7925 return &icall_type_descs [nameslot - icall_type_names];
7931 * we should probably export this as an helper (handle nested types).
7932 * Returns the number of chars written in buf.
7935 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7937 int nspacelen, cnamelen;
7938 nspacelen = strlen (klass->name_space);
7939 cnamelen = strlen (klass->name);
7940 if (nspacelen + cnamelen + 2 > bufsize)
7943 memcpy (buf, klass->name_space, nspacelen);
7944 buf [nspacelen ++] = '.';
7946 memcpy (buf + nspacelen, klass->name, cnamelen);
7947 buf [nspacelen + cnamelen] = 0;
7948 return nspacelen + cnamelen;
7952 mono_lookup_internal_call (MonoMethod *method)
7957 int typelen = 0, mlen, siglen;
7959 const IcallTypeDesc *imap;
7961 g_assert (method != NULL);
7963 if (method->is_inflated)
7964 method = ((MonoMethodInflated *) method)->declaring;
7966 if (method->klass->nested_in) {
7967 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7971 mname [pos++] = '/';
7974 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7980 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7985 imap = find_class_icalls (mname);
7987 mname [typelen] = ':';
7988 mname [typelen + 1] = ':';
7990 mlen = strlen (method->name);
7991 memcpy (mname + typelen + 2, method->name, mlen);
7992 sigstart = mname + typelen + 2 + mlen;
7995 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7996 siglen = strlen (tmpsig);
7997 if (typelen + mlen + siglen + 6 > sizeof (mname))
8000 memcpy (sigstart + 1, tmpsig, siglen);
8001 sigstart [siglen + 1] = ')';
8002 sigstart [siglen + 2] = 0;
8005 mono_loader_lock ();
8007 res = g_hash_table_lookup (icall_hash, mname);
8009 mono_loader_unlock ();
8012 /* try without signature */
8014 res = g_hash_table_lookup (icall_hash, mname);
8016 mono_loader_unlock ();
8020 /* it wasn't found in the static call tables */
8022 mono_loader_unlock ();
8025 res = find_method_icall (imap, sigstart - mlen);
8027 mono_loader_unlock ();
8030 /* try _with_ signature */
8032 res = find_method_icall (imap, sigstart - mlen);
8034 mono_loader_unlock ();
8038 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8039 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8040 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8041 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8042 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");
8043 g_print ("If you see other errors or faults after this message they are probably related\n");
8044 g_print ("and you need to fix your mono install first.\n");
8046 mono_loader_unlock ();
8052 type_from_typename (char *typename)
8054 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8056 if (!strcmp (typename, "int"))
8057 klass = mono_defaults.int_class;
8058 else if (!strcmp (typename, "ptr"))
8059 klass = mono_defaults.int_class;
8060 else if (!strcmp (typename, "void"))
8061 klass = mono_defaults.void_class;
8062 else if (!strcmp (typename, "int32"))
8063 klass = mono_defaults.int32_class;
8064 else if (!strcmp (typename, "uint32"))
8065 klass = mono_defaults.uint32_class;
8066 else if (!strcmp (typename, "int8"))
8067 klass = mono_defaults.sbyte_class;
8068 else if (!strcmp (typename, "uint8"))
8069 klass = mono_defaults.byte_class;
8070 else if (!strcmp (typename, "int16"))
8071 klass = mono_defaults.int16_class;
8072 else if (!strcmp (typename, "uint16"))
8073 klass = mono_defaults.uint16_class;
8074 else if (!strcmp (typename, "long"))
8075 klass = mono_defaults.int64_class;
8076 else if (!strcmp (typename, "ulong"))
8077 klass = mono_defaults.uint64_class;
8078 else if (!strcmp (typename, "float"))
8079 klass = mono_defaults.single_class;
8080 else if (!strcmp (typename, "double"))
8081 klass = mono_defaults.double_class;
8082 else if (!strcmp (typename, "object"))
8083 klass = mono_defaults.object_class;
8084 else if (!strcmp (typename, "obj"))
8085 klass = mono_defaults.object_class;
8086 else if (!strcmp (typename, "string"))
8087 klass = mono_defaults.string_class;
8088 else if (!strcmp (typename, "bool"))
8089 klass = mono_defaults.boolean_class;
8090 else if (!strcmp (typename, "boolean"))
8091 klass = mono_defaults.boolean_class;
8093 g_error ("%s", typename);
8094 g_assert_not_reached ();
8096 return &klass->byval_arg;
8099 MonoMethodSignature*
8100 mono_create_icall_signature (const char *sigstr)
8105 MonoMethodSignature *res;
8107 mono_loader_lock ();
8108 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8110 mono_loader_unlock ();
8114 parts = g_strsplit (sigstr, " ", 256);
8123 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8128 * Under windows, the default pinvoke calling convention is STDCALL but
8131 res->call_convention = MONO_CALL_C;
8134 res->ret = type_from_typename (parts [0]);
8135 for (i = 1; i < len; ++i) {
8136 res->params [i - 1] = type_from_typename (parts [i]);
8141 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8143 mono_loader_unlock ();
8149 mono_find_jit_icall_by_name (const char *name)
8151 MonoJitICallInfo *info;
8152 g_assert (jit_icall_hash_name);
8154 mono_loader_lock ();
8155 info = g_hash_table_lookup (jit_icall_hash_name, name);
8156 mono_loader_unlock ();
8161 mono_find_jit_icall_by_addr (gconstpointer addr)
8163 MonoJitICallInfo *info;
8164 g_assert (jit_icall_hash_addr);
8166 mono_loader_lock ();
8167 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8168 mono_loader_unlock ();
8174 * mono_get_jit_icall_info:
8176 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8177 * caller should access it while holding the loader lock.
8180 mono_get_jit_icall_info (void)
8182 return jit_icall_hash_name;
8186 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8188 mono_loader_lock ();
8189 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8190 mono_loader_unlock ();
8194 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8196 MonoJitICallInfo *info;
8201 mono_loader_lock ();
8203 if (!jit_icall_hash_name) {
8204 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8205 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8208 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8209 g_warning ("jit icall already defined \"%s\"\n", name);
8210 g_assert_not_reached ();
8213 info = g_new0 (MonoJitICallInfo, 1);
8220 info->wrapper = func;
8222 info->wrapper = NULL;
8225 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8226 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8228 mono_loader_unlock ();