5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
9 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
10 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
21 #ifdef HAVE_SYS_TIME_H
27 #if defined (HOST_WIN32)
31 #include "mono/utils/mono-membar.h"
32 #include <mono/metadata/object.h>
33 #include <mono/metadata/threads.h>
34 #include <mono/metadata/threads-types.h>
35 #include <mono/metadata/threadpool.h>
36 #include <mono/metadata/monitor.h>
37 #include <mono/metadata/reflection.h>
38 #include <mono/metadata/assembly.h>
39 #include <mono/metadata/tabledefs.h>
40 #include <mono/metadata/exception.h>
41 #include <mono/metadata/file-io.h>
42 #include <mono/metadata/console-io.h>
43 #include <mono/metadata/socket-io.h>
44 #include <mono/metadata/mono-endian.h>
45 #include <mono/metadata/tokentype.h>
46 #include <mono/metadata/domain-internals.h>
47 #include <mono/metadata/metadata-internals.h>
48 #include <mono/metadata/class-internals.h>
49 #include <mono/metadata/marshal.h>
50 #include <mono/metadata/gc-internal.h>
51 #include <mono/metadata/mono-gc.h>
52 #include <mono/metadata/rand.h>
53 #include <mono/metadata/sysmath.h>
54 #include <mono/metadata/string-icalls.h>
55 #include <mono/metadata/debug-helpers.h>
56 #include <mono/metadata/process.h>
57 #include <mono/metadata/environment.h>
58 #include <mono/metadata/profiler-private.h>
59 #include <mono/metadata/locales.h>
60 #include <mono/metadata/filewatcher.h>
61 #include <mono/metadata/char-conversions.h>
62 #include <mono/metadata/security.h>
63 #include <mono/metadata/mono-config.h>
64 #include <mono/metadata/cil-coff.h>
65 #include <mono/metadata/number-formatter.h>
66 #include <mono/metadata/security-manager.h>
67 #include <mono/metadata/security-core-clr.h>
68 #include <mono/metadata/mono-perfcounters.h>
69 #include <mono/metadata/mono-debug.h>
70 #include <mono/metadata/mono-ptr-array.h>
71 #include <mono/io-layer/io-layer.h>
72 #include <mono/utils/strtod.h>
73 #include <mono/utils/monobitset.h>
74 #include <mono/utils/mono-time.h>
75 #include <mono/utils/mono-proclib.h>
76 #include <mono/utils/mono-string.h>
77 #include <mono/utils/mono-error-internals.h>
78 #include <mono/utils/mono-mmap.h>
80 #if defined (HOST_WIN32)
86 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
88 static MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
91 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
93 static inline MonoBoolean
94 is_generic_parameter (MonoType *type)
96 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
100 mono_class_init_or_throw (MonoClass *klass)
102 if (!mono_class_init (klass))
103 mono_raise_exception (mono_class_get_exception_for_failure (klass));
107 * We expect a pointer to a char, not a string
110 mono_double_ParseImpl (char *ptr, double *result)
112 gchar *endptr = NULL;
119 *result = strtod (ptr, &endptr);
123 /* Need to lock here because EGLIB (#464316) has locking defined as no-ops, and that breaks mono_strtod */
124 EnterCriticalSection (&mono_strtod_mutex);
125 *result = mono_strtod (ptr, &endptr);
126 LeaveCriticalSection (&mono_strtod_mutex);
128 *result = mono_strtod (ptr, &endptr);
133 if (!*ptr || (endptr && *endptr))
140 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
149 ao = (MonoArray *)this;
150 ac = (MonoClass *)ao->obj.vtable->klass;
152 esize = mono_array_element_size (ac);
153 ea = (gpointer*)((char*)ao->vector + (pos * esize));
155 if (ac->element_class->valuetype)
156 return mono_value_box (this->vtable->domain, ac->element_class, ea);
162 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
170 MONO_CHECK_ARG_NULL (idxs);
172 io = (MonoArray *)idxs;
173 ic = (MonoClass *)io->obj.vtable->klass;
175 ao = (MonoArray *)this;
176 ac = (MonoClass *)ao->obj.vtable->klass;
178 g_assert (ic->rank == 1);
179 if (io->bounds != NULL || io->max_length != ac->rank)
180 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
182 ind = (gint32 *)io->vector;
184 if (ao->bounds == NULL) {
185 if (*ind < 0 || *ind >= ao->max_length)
186 mono_raise_exception (mono_get_exception_index_out_of_range ());
188 return ves_icall_System_Array_GetValueImpl (this, *ind);
191 for (i = 0; i < ac->rank; i++)
192 if ((ind [i] < ao->bounds [i].lower_bound) ||
193 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
194 mono_raise_exception (mono_get_exception_index_out_of_range ());
196 pos = ind [0] - ao->bounds [0].lower_bound;
197 for (i = 1; i < ac->rank; i++)
198 pos = pos*ao->bounds [i].length + ind [i] -
199 ao->bounds [i].lower_bound;
201 return ves_icall_System_Array_GetValueImpl (this, pos);
205 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
207 MonoClass *ac, *vc, *ec;
219 vc = value->vtable->klass;
223 ac = this->obj.vtable->klass;
224 ec = ac->element_class;
226 esize = mono_array_element_size (ac);
227 ea = (gpointer*)((char*)this->vector + (pos * esize));
228 va = (gpointer*)((char*)value + sizeof (MonoObject));
230 if (mono_class_is_nullable (ec)) {
231 mono_nullable_init ((guint8*)ea, value, ec);
236 memset (ea, 0, esize);
240 #define NO_WIDENING_CONVERSION G_STMT_START{\
241 mono_raise_exception (mono_get_exception_argument ( \
242 "value", "not a widening conversion")); \
245 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
246 if (esize < vsize + (extra)) \
247 mono_raise_exception (mono_get_exception_argument ( \
248 "value", "not a widening conversion")); \
251 #define INVALID_CAST G_STMT_START{\
252 mono_raise_exception (mono_get_exception_invalid_cast ()); \
255 /* Check element (destination) type. */
256 switch (ec->byval_arg.type) {
257 case MONO_TYPE_STRING:
258 switch (vc->byval_arg.type) {
259 case MONO_TYPE_STRING:
265 case MONO_TYPE_BOOLEAN:
266 switch (vc->byval_arg.type) {
267 case MONO_TYPE_BOOLEAN:
280 NO_WIDENING_CONVERSION;
287 if (!ec->valuetype) {
288 if (!mono_object_isinst (value, ec))
290 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
294 if (mono_object_isinst (value, ec)) {
295 if (ec->has_references)
296 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
298 memcpy (ea, (char *)value + sizeof (MonoObject), esize);
305 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
307 et = ec->byval_arg.type;
308 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
309 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
311 vt = vc->byval_arg.type;
312 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
313 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
315 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
321 case MONO_TYPE_CHAR: \
322 CHECK_WIDENING_CONVERSION(0); \
323 *(etype *) ea = (etype) u64; \
325 /* You can't assign a signed value to an unsigned array. */ \
330 /* You can't assign a floating point number to an integer array. */ \
333 NO_WIDENING_CONVERSION; \
337 #define ASSIGN_SIGNED(etype) G_STMT_START{\
343 CHECK_WIDENING_CONVERSION(0); \
344 *(etype *) ea = (etype) i64; \
346 /* You can assign an unsigned value to a signed array if the array's */ \
347 /* element size is larger than the value size. */ \
352 case MONO_TYPE_CHAR: \
353 CHECK_WIDENING_CONVERSION(1); \
354 *(etype *) ea = (etype) u64; \
356 /* You can't assign a floating point number to an integer array. */ \
359 NO_WIDENING_CONVERSION; \
363 #define ASSIGN_REAL(etype) G_STMT_START{\
367 CHECK_WIDENING_CONVERSION(0); \
368 *(etype *) ea = (etype) r64; \
370 /* All integer values fit into a floating point array, so we don't */ \
371 /* need to CHECK_WIDENING_CONVERSION here. */ \
376 *(etype *) ea = (etype) i64; \
382 case MONO_TYPE_CHAR: \
383 *(etype *) ea = (etype) u64; \
390 u64 = *(guint8 *) va;
393 u64 = *(guint16 *) va;
396 u64 = *(guint32 *) va;
399 u64 = *(guint64 *) va;
405 i64 = *(gint16 *) va;
408 i64 = *(gint32 *) va;
411 i64 = *(gint64 *) va;
414 r64 = *(gfloat *) va;
417 r64 = *(gdouble *) va;
420 u64 = *(guint16 *) va;
422 case MONO_TYPE_BOOLEAN:
423 /* Boolean is only compatible with itself. */
436 NO_WIDENING_CONVERSION;
443 /* If we can't do a direct copy, let's try a widening conversion. */
446 ASSIGN_UNSIGNED (guint16);
448 ASSIGN_UNSIGNED (guint8);
450 ASSIGN_UNSIGNED (guint16);
452 ASSIGN_UNSIGNED (guint32);
454 ASSIGN_UNSIGNED (guint64);
456 ASSIGN_SIGNED (gint8);
458 ASSIGN_SIGNED (gint16);
460 ASSIGN_SIGNED (gint32);
462 ASSIGN_SIGNED (gint64);
464 ASSIGN_REAL (gfloat);
466 ASSIGN_REAL (gdouble);
470 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
474 #undef NO_WIDENING_CONVERSION
475 #undef CHECK_WIDENING_CONVERSION
476 #undef ASSIGN_UNSIGNED
482 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
490 MONO_CHECK_ARG_NULL (idxs);
492 ic = idxs->obj.vtable->klass;
493 ac = this->obj.vtable->klass;
495 g_assert (ic->rank == 1);
496 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
497 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
499 ind = (gint32 *)idxs->vector;
501 if (this->bounds == NULL) {
502 if (*ind < 0 || *ind >= this->max_length)
503 mono_raise_exception (mono_get_exception_index_out_of_range ());
505 ves_icall_System_Array_SetValueImpl (this, value, *ind);
509 for (i = 0; i < ac->rank; i++)
510 if ((ind [i] < this->bounds [i].lower_bound) ||
511 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
512 mono_raise_exception (mono_get_exception_index_out_of_range ());
514 pos = ind [0] - this->bounds [0].lower_bound;
515 for (i = 1; i < ac->rank; i++)
516 pos = pos * this->bounds [i].length + ind [i] -
517 this->bounds [i].lower_bound;
519 ves_icall_System_Array_SetValueImpl (this, value, pos);
523 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
525 MonoClass *aklass, *klass;
528 gboolean bounded = FALSE;
532 MONO_CHECK_ARG_NULL (type);
533 MONO_CHECK_ARG_NULL (lengths);
535 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
537 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
539 for (i = 0; i < mono_array_length (lengths); i++)
540 if (mono_array_get (lengths, gint32, i) < 0)
541 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
543 klass = mono_class_from_mono_type (type->type);
544 mono_class_init_or_throw (klass);
546 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
547 /* vectors are not the same as one dimensional arrays with no-zero bounds */
552 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
554 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
555 for (i = 0; i < aklass->rank; ++i) {
556 sizes [i] = mono_array_get (lengths, guint32, i);
558 sizes [i + aklass->rank] = mono_array_get (bounds, guint32, i);
560 sizes [i + aklass->rank] = 0;
563 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
569 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
571 MonoClass *aklass, *klass;
574 gboolean bounded = FALSE;
578 MONO_CHECK_ARG_NULL (type);
579 MONO_CHECK_ARG_NULL (lengths);
581 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
583 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
585 for (i = 0; i < mono_array_length (lengths); i++)
586 if ((mono_array_get (lengths, gint64, i) < 0) ||
587 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
588 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
590 klass = mono_class_from_mono_type (type->type);
591 mono_class_init_or_throw (klass);
593 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
594 /* vectors are not the same as one dimensional arrays with no-zero bounds */
599 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
601 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
602 for (i = 0; i < aklass->rank; ++i) {
603 sizes [i] = mono_array_get (lengths, guint64, i);
605 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
607 sizes [i + aklass->rank] = 0;
610 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
616 ves_icall_System_Array_GetRank (MonoObject *this)
620 return this->vtable->klass->rank;
624 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
626 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
631 if ((dimension < 0) || (dimension >= rank))
632 mono_raise_exception (mono_get_exception_index_out_of_range ());
634 if (this->bounds == NULL)
635 length = this->max_length;
637 length = this->bounds [dimension].length;
639 #ifdef MONO_BIG_ARRAYS
640 if (length > G_MAXINT32)
641 mono_raise_exception (mono_get_exception_overflow ());
647 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
649 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
653 if ((dimension < 0) || (dimension >= rank))
654 mono_raise_exception (mono_get_exception_index_out_of_range ());
656 if (this->bounds == NULL)
657 return this->max_length;
659 return this->bounds [dimension].length;
663 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
665 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
669 if ((dimension < 0) || (dimension >= rank))
670 mono_raise_exception (mono_get_exception_index_out_of_range ());
672 if (this->bounds == NULL)
675 return this->bounds [dimension].lower_bound;
679 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
681 int sz = mono_array_element_size (mono_object_class (arr));
682 memset (mono_array_addr_with_size (arr, sz, idx), 0, length * sz);
686 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
691 MonoClass *src_class;
692 MonoClass *dest_class;
697 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
700 if (source->bounds || dest->bounds)
703 /* there's no integer overflow since mono_array_length returns an unsigned integer */
704 if ((dest_idx + length > mono_array_length (dest)) ||
705 (source_idx + length > mono_array_length (source)))
708 src_class = source->obj.vtable->klass->element_class;
709 dest_class = dest->obj.vtable->klass->element_class;
712 * Handle common cases.
715 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
716 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
717 int has_refs = dest_class->has_references;
718 for (i = source_idx; i < source_idx + length; ++i) {
719 MonoObject *elem = mono_array_get (source, MonoObject*, i);
720 if (elem && !mono_object_isinst (elem, dest_class))
724 element_size = mono_array_element_size (dest->obj.vtable->klass);
725 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
726 for (i = 0; i < length; ++i) {
727 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
728 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
732 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
734 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
739 /* Check if we're copying a char[] <==> (u)short[] */
740 if (src_class != dest_class) {
741 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
744 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
746 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
747 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE))
748 for (i = source_idx; i < source_idx + length; ++i) {
749 MonoObject *elem = mono_array_get (source, MonoObject*, i);
750 if (elem && !mono_object_isinst (elem, dest_class))
757 if (dest_class->valuetype) {
758 element_size = mono_array_element_size (source->obj.vtable->klass);
759 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
760 if (dest_class->has_references) {
761 mono_value_copy_array (dest, dest_idx, source_addr, length);
763 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
764 memmove (dest_addr, source_addr, element_size * length);
767 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
774 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
783 ao = (MonoArray *)this;
784 ac = (MonoClass *)ao->obj.vtable->klass;
786 esize = mono_array_element_size (ac);
787 ea = (gpointer*)((char*)ao->vector + (pos * esize));
789 memcpy (value, ea, esize);
793 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
802 ao = (MonoArray *)this;
803 ac = (MonoClass *)ao->obj.vtable->klass;
804 ec = ac->element_class;
806 esize = mono_array_element_size (ac);
807 ea = (gpointer*)((char*)ao->vector + (pos * esize));
809 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
810 g_assert (esize == sizeof (gpointer));
811 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
813 g_assert (ec->inited);
814 g_assert (esize == mono_class_value_size (ec, NULL));
815 if (ec->has_references)
816 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
818 memcpy (ea, value, esize);
823 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
825 MonoClass *klass = array->obj.vtable->klass;
826 guint32 size = mono_array_element_size (klass);
827 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
829 const char *field_data;
831 if (MONO_TYPE_IS_REFERENCE (type) ||
832 (type->type == MONO_TYPE_VALUETYPE &&
833 (!mono_type_get_class (type) ||
834 mono_type_get_class (type)->has_references))) {
835 MonoException *exc = mono_get_exception_argument("array",
836 "Cannot initialize array containing references");
837 mono_raise_exception (exc);
840 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
841 MonoException *exc = mono_get_exception_argument("field_handle",
842 "Field doesn't have an RVA");
843 mono_raise_exception (exc);
846 size *= array->max_length;
847 field_data = mono_field_get_data (field_handle);
849 if (size > mono_type_size (field_handle->type, &align)) {
850 MonoException *exc = mono_get_exception_argument("field_handle",
851 "Field not large enough to fill array");
852 mono_raise_exception (exc);
855 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
857 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
858 guint ## n *src = (guint ## n *) field_data; \
859 guint ## n *end = (guint ## n *)((char*)src + size); \
861 for (; src < end; data++, src++) { \
862 *data = read ## n (src); \
866 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
868 switch (type->type) {
885 memcpy (mono_array_addr (array, char, 0), field_data, size);
889 memcpy (mono_array_addr (array, char, 0), field_data, size);
891 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
894 double *data = (double*)mono_array_addr (array, double, 0);
896 for (i = 0; i < size; i++, data++) {
906 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
910 return offsetof (MonoString, chars);
914 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
918 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
921 return mono_object_clone (obj);
925 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
930 MONO_CHECK_ARG_NULL (handle);
932 klass = mono_class_from_mono_type (handle);
933 MONO_CHECK_ARG (handle, klass);
935 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
937 /* This will call the type constructor */
938 mono_runtime_class_init (vtable);
942 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
946 mono_image_check_for_module_cctor (image);
947 if (image->has_module_cctor) {
948 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
949 /*It's fine to raise the exception here*/
950 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
955 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
960 /* later make this configurable and per-arch */
961 int min_size = 4096 * 4 * sizeof (void*);
962 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
963 /* if we have no info we are optimistic and assume there is enough room */
966 current = (guint8 *)&stack_addr;
967 if (current > stack_addr) {
968 if ((current - stack_addr) < min_size)
971 if (current - (stack_addr - stack_size) < min_size)
978 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
982 return mono_object_clone (this);
986 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
989 MonoObject **values = NULL;
993 MonoClassField* field;
998 klass = mono_object_class (this);
1000 if (mono_class_num_fields (klass) == 0)
1001 return mono_object_hash (this);
1004 * Compute the starting value of the hashcode for fields of primitive
1005 * types, and return the remaining fields in an array to the managed side.
1006 * This way, we can avoid costly reflection operations in managed code.
1009 while ((field = mono_class_get_fields (klass, &iter))) {
1010 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1012 if (mono_field_is_deleted (field))
1014 /* FIXME: Add more types */
1015 switch (field->type->type) {
1017 result ^= *(gint32*)((guint8*)this + field->offset);
1019 case MONO_TYPE_STRING: {
1021 s = *(MonoString**)((guint8*)this + field->offset);
1023 result ^= mono_string_hash (s);
1028 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1029 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1030 values [count++] = o;
1036 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1037 for (i = 0; i < count; ++i)
1038 mono_array_setref (*fields, i, values [i]);
1046 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1049 MonoObject **values = NULL;
1051 MonoClassField* field;
1055 MONO_ARCH_SAVE_REGS;
1057 MONO_CHECK_ARG_NULL (that);
1059 if (this->vtable != that->vtable)
1062 klass = mono_object_class (this);
1064 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1065 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1068 * Do the comparison for fields of primitive type and return a result if
1069 * possible. Otherwise, return the remaining fields in an array to the
1070 * managed side. This way, we can avoid costly reflection operations in
1075 while ((field = mono_class_get_fields (klass, &iter))) {
1076 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1078 if (mono_field_is_deleted (field))
1080 /* FIXME: Add more types */
1081 switch (field->type->type) {
1084 case MONO_TYPE_BOOLEAN:
1085 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1090 case MONO_TYPE_CHAR:
1091 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1096 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1101 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1105 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1109 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1114 case MONO_TYPE_STRING: {
1115 MonoString *s1, *s2;
1116 guint32 s1len, s2len;
1117 s1 = *(MonoString**)((guint8*)this + field->offset);
1118 s2 = *(MonoString**)((guint8*)that + field->offset);
1121 if ((s1 == NULL) || (s2 == NULL))
1123 s1len = mono_string_length (s1);
1124 s2len = mono_string_length (s2);
1128 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1134 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1135 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1136 values [count++] = o;
1137 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1138 values [count++] = o;
1141 if (klass->enumtype)
1142 /* enums only have one non-static field */
1148 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1149 for (i = 0; i < count; ++i)
1150 mono_array_setref (*fields, i, values [i]);
1157 static MonoReflectionType *
1158 ves_icall_System_Object_GetType (MonoObject *obj)
1160 MONO_ARCH_SAVE_REGS;
1162 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1163 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1165 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1169 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1171 MONO_ARCH_SAVE_REGS;
1173 mtype->type = &obj->vtable->klass->byval_arg;
1174 g_assert (mtype->type->type);
1178 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj)
1180 MONO_ARCH_SAVE_REGS;
1182 MONO_CHECK_ARG_NULL (obj);
1184 return mono_image_create_token (mb->dynamic_image, obj, TRUE, TRUE);
1188 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1189 MonoReflectionMethod *method,
1190 MonoArray *opt_param_types)
1192 MONO_ARCH_SAVE_REGS;
1194 MONO_CHECK_ARG_NULL (method);
1196 return mono_image_create_method_token (
1197 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1201 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1203 MONO_ARCH_SAVE_REGS;
1205 mono_image_create_pefile (mb, file);
1209 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1211 MONO_ARCH_SAVE_REGS;
1213 mono_image_build_metadata (mb);
1217 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1219 MONO_ARCH_SAVE_REGS;
1221 mono_image_register_token (mb->dynamic_image, token, obj);
1225 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1227 MonoMethod **dest = data;
1229 /* skip unmanaged frames */
1245 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1247 MonoMethod **dest = data;
1249 /* skip unmanaged frames */
1254 if (!strcmp (m->klass->name_space, "System.Reflection"))
1263 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1265 MonoMethod **dest = data;
1267 /* skip unmanaged frames */
1271 if (m->wrapper_type != MONO_WRAPPER_NONE)
1274 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1288 static MonoReflectionType *
1289 type_from_name (const char *str, MonoBoolean ignoreCase)
1291 MonoType *type = NULL;
1292 MonoAssembly *assembly = NULL;
1293 MonoTypeNameParse info;
1294 char *temp_str = g_strdup (str);
1295 gboolean type_resolve = FALSE;
1297 MONO_ARCH_SAVE_REGS;
1299 /* mono_reflection_parse_type() mangles the string */
1300 if (!mono_reflection_parse_type (temp_str, &info)) {
1301 mono_reflection_free_type_info (&info);
1306 if (info.assembly.name) {
1307 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1309 MonoMethod *m = mono_method_get_last_managed ();
1310 MonoMethod *dest = m;
1312 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1317 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1318 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1319 * to crash. This only seems to happen in some strange remoting
1320 * scenarios and I was unable to figure out what's happening there.
1321 * Dec 10, 2005 - Martin.
1325 assembly = dest->klass->image->assembly;
1326 type_resolve = TRUE;
1328 g_warning (G_STRLOC);
1333 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1334 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1337 if (!info.assembly.name && !type) /* try mscorlib */
1338 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1340 if (assembly && !type && type_resolve) {
1341 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1342 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1345 mono_reflection_free_type_info (&info);
1351 return mono_type_get_object (mono_domain_get (), type);
1355 MonoReflectionType *
1356 mono_type_get (const char *str)
1358 char *copy = g_strdup (str);
1359 MonoReflectionType *type = type_from_name (copy, FALSE);
1366 static MonoReflectionType*
1367 ves_icall_type_from_name (MonoString *name,
1368 MonoBoolean throwOnError,
1369 MonoBoolean ignoreCase)
1371 char *str = mono_string_to_utf8 (name);
1372 MonoReflectionType *type;
1374 type = type_from_name (str, ignoreCase);
1377 MonoException *e = NULL;
1380 e = mono_get_exception_type_load (name, NULL);
1382 mono_loader_clear_error ();
1384 mono_raise_exception (e);
1391 static MonoReflectionType*
1392 ves_icall_type_from_handle (MonoType *handle)
1394 MonoDomain *domain = mono_domain_get ();
1396 MONO_ARCH_SAVE_REGS;
1398 return mono_type_get_object (domain, handle);
1402 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1404 MONO_ARCH_SAVE_REGS;
1406 if (c && type->type && c->type)
1407 return mono_metadata_type_equal (type->type, c->type);
1409 return (type == c) ? TRUE : FALSE;
1412 /* System.TypeCode */
1431 TYPECODE_STRING = 18
1435 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1437 int t = type->type->type;
1439 MONO_ARCH_SAVE_REGS;
1441 if (type->type->byref)
1442 return TYPECODE_OBJECT;
1446 case MONO_TYPE_VOID:
1447 return TYPECODE_OBJECT;
1448 case MONO_TYPE_BOOLEAN:
1449 return TYPECODE_BOOLEAN;
1451 return TYPECODE_BYTE;
1453 return TYPECODE_SBYTE;
1455 return TYPECODE_UINT16;
1457 return TYPECODE_INT16;
1458 case MONO_TYPE_CHAR:
1459 return TYPECODE_CHAR;
1463 return TYPECODE_OBJECT;
1465 return TYPECODE_UINT32;
1467 return TYPECODE_INT32;
1469 return TYPECODE_UINT64;
1471 return TYPECODE_INT64;
1473 return TYPECODE_SINGLE;
1475 return TYPECODE_DOUBLE;
1476 case MONO_TYPE_VALUETYPE: {
1477 MonoClass *klass = type->type->data.klass;
1479 if (klass->enumtype) {
1480 t = mono_class_enum_basetype (klass)->type;
1482 } else if (mono_is_corlib_image (klass->image)) {
1483 if (strcmp (klass->name_space, "System") == 0) {
1484 if (strcmp (klass->name, "Decimal") == 0)
1485 return TYPECODE_DECIMAL;
1486 else if (strcmp (klass->name, "DateTime") == 0)
1487 return TYPECODE_DATETIME;
1490 return TYPECODE_OBJECT;
1492 case MONO_TYPE_STRING:
1493 return TYPECODE_STRING;
1494 case MONO_TYPE_SZARRAY:
1495 case MONO_TYPE_ARRAY:
1496 case MONO_TYPE_OBJECT:
1498 case MONO_TYPE_MVAR:
1499 case MONO_TYPE_TYPEDBYREF:
1500 return TYPECODE_OBJECT;
1501 case MONO_TYPE_CLASS:
1503 MonoClass *klass = type->type->data.klass;
1504 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1505 if (strcmp (klass->name, "DBNull") == 0)
1506 return TYPECODE_DBNULL;
1509 return TYPECODE_OBJECT;
1510 case MONO_TYPE_GENERICINST:
1511 return TYPECODE_OBJECT;
1513 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1519 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1525 MONO_ARCH_SAVE_REGS;
1527 g_assert (type != NULL);
1529 domain = ((MonoObject *)type)->vtable->domain;
1531 if (!c) /* FIXME: dont know what do do here */
1534 klass = mono_class_from_mono_type (type->type);
1535 klassc = mono_class_from_mono_type (c->type);
1537 /* Interface check requires a more complex setup so we
1538 * only do for them. Otherwise we simply avoid mono_class_init.
1540 if (check_interfaces) {
1541 mono_class_init_or_throw (klass);
1542 mono_class_init_or_throw (klassc);
1543 } else if (!klass->supertypes || !klassc->supertypes) {
1544 mono_loader_lock ();
1545 mono_class_setup_supertypes (klass);
1546 mono_class_setup_supertypes (klassc);
1547 mono_loader_unlock ();
1550 if (type->type->byref)
1551 return klassc == mono_defaults.object_class;
1553 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1557 mono_type_is_primitive (MonoType *type)
1559 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1560 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1564 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1566 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1567 return mono_class_enum_basetype (type->data.klass);
1568 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1569 return mono_class_enum_basetype (type->data.generic_class->container_class);
1574 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1580 MONO_ARCH_SAVE_REGS;
1582 g_assert (type != NULL);
1584 domain = ((MonoObject *)type)->vtable->domain;
1586 klass = mono_class_from_mono_type (type->type);
1587 klassc = mono_class_from_mono_type (c->type);
1589 mono_class_init_or_throw (klass);
1590 mono_class_init_or_throw (klassc);
1592 if (type->type->byref ^ c->type->byref)
1595 if (type->type->byref) {
1596 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1597 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1599 klass = mono_class_from_mono_type (t);
1600 klassc = mono_class_from_mono_type (ot);
1602 if (mono_type_is_primitive (t)) {
1603 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1604 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1605 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1606 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1607 return t->type == ot->type;
1609 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1612 if (klass->valuetype)
1613 return klass == klassc;
1614 return klass->valuetype == klassc->valuetype;
1617 return mono_class_is_assignable_from (klass, klassc);
1621 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1623 MonoClass *klass = mono_class_from_mono_type (type->type);
1624 mono_class_init_or_throw (klass);
1625 return mono_object_isinst (obj, klass) != NULL;
1629 ves_icall_get_attributes (MonoReflectionType *type)
1631 MonoClass *klass = mono_class_from_mono_type (type->type);
1632 return klass->flags;
1635 static MonoReflectionMarshal*
1636 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1638 MonoClass *klass = field->field->parent;
1639 MonoMarshalType *info;
1642 if (klass->generic_container ||
1643 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1646 info = mono_marshal_load_type_info (klass);
1648 for (i = 0; i < info->num_fields; ++i) {
1649 if (info->fields [i].field == field->field) {
1650 if (!info->fields [i].mspec)
1653 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1660 static MonoReflectionField*
1661 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1663 gboolean found = FALSE;
1670 klass = handle->parent;
1672 klass = mono_class_from_mono_type (type);
1674 /* Check that the field belongs to the class */
1675 for (k = klass; k; k = k->parent) {
1676 if (k == handle->parent) {
1683 /* The managed code will throw the exception */
1687 return mono_field_get_object (mono_domain_get (), klass, handle);
1691 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1693 MonoType *type = field->field->type;
1695 return type_array_from_modifiers (field->field->parent->image, type, optional);
1699 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1701 MonoDomain *domain = mono_domain_get ();
1702 MonoMethodSignature* sig;
1703 MONO_ARCH_SAVE_REGS;
1705 sig = mono_method_signature (method);
1707 g_assert (mono_loader_get_last_error ());
1708 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1711 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1712 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1713 info->attrs = method->flags;
1714 info->implattrs = method->iflags;
1715 if (sig->call_convention == MONO_CALL_DEFAULT)
1716 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1718 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1723 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1727 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1729 MonoDomain *domain = mono_domain_get ();
1731 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1734 static MonoReflectionMarshal*
1735 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1737 MonoDomain *domain = mono_domain_get ();
1738 MonoReflectionMarshal* res = NULL;
1739 MonoMarshalSpec **mspecs;
1742 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1743 mono_method_get_marshal_info (method, mspecs);
1746 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1748 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1750 mono_metadata_free_marshal_spec (mspecs [i]);
1757 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1759 return field->field->offset - sizeof (MonoObject);
1762 static MonoReflectionType*
1763 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1766 MONO_ARCH_SAVE_REGS;
1768 parent = declaring? field->field->parent: field->klass;
1770 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1774 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1776 MonoClass *fklass = field->klass;
1777 MonoClassField *cf = field->field;
1778 MonoDomain *domain = mono_object_domain (field);
1780 if (fklass->image->assembly->ref_only)
1781 mono_raise_exception (mono_get_exception_invalid_operation (
1782 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1784 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1785 mono_security_core_clr_ensure_reflection_access_field (cf);
1787 return mono_field_get_value_object (domain, cf, obj);
1791 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1793 MonoClassField *cf = field->field;
1796 MONO_ARCH_SAVE_REGS;
1798 if (field->klass->image->assembly->ref_only)
1799 mono_raise_exception (mono_get_exception_invalid_operation (
1800 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1802 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1803 mono_security_core_clr_ensure_reflection_access_field (cf);
1805 v = (gchar *) value;
1806 if (!cf->type->byref) {
1807 switch (cf->type->type) {
1810 case MONO_TYPE_BOOLEAN:
1813 case MONO_TYPE_CHAR:
1822 case MONO_TYPE_VALUETYPE:
1824 v += sizeof (MonoObject);
1826 case MONO_TYPE_STRING:
1827 case MONO_TYPE_OBJECT:
1828 case MONO_TYPE_CLASS:
1829 case MONO_TYPE_ARRAY:
1830 case MONO_TYPE_SZARRAY:
1833 case MONO_TYPE_GENERICINST: {
1834 MonoGenericClass *gclass = cf->type->data.generic_class;
1835 g_assert (!gclass->context.class_inst->is_open);
1837 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1838 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1839 MonoObject *nullable;
1842 * Convert the boxed vtype into a Nullable structure.
1843 * This is complicated by the fact that Nullables have
1844 * a variable structure.
1846 nullable = mono_object_new (mono_domain_get (), nklass);
1848 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1850 v = mono_object_unbox (nullable);
1853 if (gclass->container_class->valuetype && (v != NULL))
1854 v += sizeof (MonoObject);
1858 g_error ("type 0x%x not handled in "
1859 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1864 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1865 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1866 if (!vtable->initialized)
1867 mono_runtime_class_init (vtable);
1868 mono_field_static_set_value (vtable, cf, v);
1870 mono_field_set_value (obj, cf, v);
1875 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1877 MonoObject *o = NULL;
1878 MonoClassField *field = this->field;
1880 MonoDomain *domain = mono_object_domain (this);
1882 MonoTypeEnum def_type;
1883 const char *def_value;
1885 MONO_ARCH_SAVE_REGS;
1887 mono_class_init (field->parent);
1889 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1890 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1892 if (field->parent->image->dynamic) {
1894 g_assert_not_reached ();
1897 def_value = mono_class_get_field_default_value (field, &def_type);
1899 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1903 case MONO_TYPE_BOOLEAN:
1906 case MONO_TYPE_CHAR:
1914 case MONO_TYPE_R8: {
1917 /* boxed value type */
1918 t = g_new0 (MonoType, 1);
1920 klass = mono_class_from_mono_type (t);
1922 o = mono_object_new (domain, klass);
1923 v = ((gchar *) o) + sizeof (MonoObject);
1924 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1927 case MONO_TYPE_STRING:
1928 case MONO_TYPE_CLASS:
1929 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1932 g_assert_not_reached ();
1938 static MonoReflectionType*
1939 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1942 MonoClassField *field = ref_field->field;
1943 MonoType *type = mono_field_get_type_checked (field, &error);
1944 if (!mono_error_ok (&error))
1945 mono_error_raise_exception (&error);
1946 return mono_type_get_object (mono_object_domain (ref_field), type);
1949 static MonoReflectionType*
1950 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1952 MonoMethod *method = rmethod->method.method;
1954 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1957 /* From MonoProperty.cs */
1959 PInfo_Attributes = 1,
1960 PInfo_GetMethod = 1 << 1,
1961 PInfo_SetMethod = 1 << 2,
1962 PInfo_ReflectedType = 1 << 3,
1963 PInfo_DeclaringType = 1 << 4,
1968 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1970 MonoDomain *domain = mono_object_domain (property);
1972 MONO_ARCH_SAVE_REGS;
1974 if ((req_info & PInfo_ReflectedType) != 0)
1975 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1976 else if ((req_info & PInfo_DeclaringType) != 0)
1977 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1979 if ((req_info & PInfo_Name) != 0)
1980 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1982 if ((req_info & PInfo_Attributes) != 0)
1983 info->attrs = property->property->attrs;
1985 if ((req_info & PInfo_GetMethod) != 0)
1986 MONO_STRUCT_SETREF (info, get, property->property->get ?
1987 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1989 if ((req_info & PInfo_SetMethod) != 0)
1990 MONO_STRUCT_SETREF (info, set, property->property->set ?
1991 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1993 * There may be other methods defined for properties, though, it seems they are not exposed
1994 * in the reflection API
1999 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2001 MonoDomain *domain = mono_object_domain (event);
2003 MONO_ARCH_SAVE_REGS;
2005 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2006 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2008 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2009 info->attrs = event->event->attrs;
2010 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2011 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2012 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2014 #ifndef MONO_SMALL_CONFIG
2015 if (event->event->other) {
2017 while (event->event->other [n])
2019 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2021 for (i = 0; i < n; i++)
2022 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2028 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2033 mono_class_setup_interfaces (klass, error);
2034 if (!mono_error_ok (error))
2037 for (i = 0; i < klass->interface_count; i++) {
2038 ic = klass->interfaces [i];
2039 g_hash_table_insert (ifaces, ic, ic);
2041 collect_interfaces (ic, ifaces, error);
2042 if (!mono_error_ok (error))
2048 MonoArray *iface_array;
2049 MonoGenericContext *context;
2053 } FillIfaceArrayData;
2056 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2058 FillIfaceArrayData *data = user_data;
2059 MonoClass *ic = key;
2060 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2062 if (!mono_error_ok (data->error))
2065 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2066 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2067 if (!mono_error_ok (data->error))
2071 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2074 mono_metadata_free_type (inflated);
2078 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2081 MonoClass *class = mono_class_from_mono_type (type->type);
2083 FillIfaceArrayData data = { 0 };
2086 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2088 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2089 data.context = mono_class_get_context (class);
2090 class = class->generic_class->container_class;
2093 for (parent = class; parent; parent = parent->parent) {
2094 mono_class_setup_interfaces (parent, &error);
2095 if (!mono_error_ok (&error))
2097 collect_interfaces (parent, iface_hash, &error);
2098 if (!mono_error_ok (&error))
2102 data.error = &error;
2103 data.domain = mono_object_domain (type);
2105 len = g_hash_table_size (iface_hash);
2107 return mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2109 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2110 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2111 if (!mono_error_ok (&error))
2114 g_hash_table_destroy (iface_hash);
2115 return data.iface_array;
2118 g_hash_table_destroy (iface_hash);
2119 mono_error_raise_exception (&error);
2124 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2126 gboolean variance_used;
2127 MonoClass *class = mono_class_from_mono_type (type->type);
2128 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2129 MonoReflectionMethod *member;
2132 int i = 0, len, ioffset;
2135 MONO_ARCH_SAVE_REGS;
2136 mono_class_init_or_throw (class);
2137 mono_class_init_or_throw (iclass);
2139 mono_class_setup_vtable (class);
2141 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2145 len = mono_class_num_methods (iclass);
2146 domain = mono_object_domain (type);
2147 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2148 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2150 while ((method = mono_class_get_methods (iclass, &iter))) {
2151 member = mono_method_get_object (domain, method, iclass);
2152 mono_array_setref (*methods, i, member);
2153 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2154 mono_array_setref (*targets, i, member);
2161 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2163 MonoClass *klass = mono_class_from_mono_type (type->type);
2164 mono_class_init_or_throw (klass);
2166 if (klass->image->dynamic) {
2167 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2168 *packing = tb->packing_size;
2169 *size = tb->class_size;
2171 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2175 static MonoReflectionType*
2176 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2180 MONO_ARCH_SAVE_REGS;
2182 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2183 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2185 class = mono_class_from_mono_type (type->type);
2186 mono_class_init_or_throw (class);
2188 // GetElementType should only return a type for:
2189 // Array Pointer PassedByRef
2190 if (type->type->byref)
2191 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2192 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2193 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2194 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2195 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2200 static MonoReflectionType*
2201 ves_icall_get_type_parent (MonoReflectionType *type)
2203 MonoClass *class = mono_class_from_mono_type (type->type);
2204 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2208 ves_icall_type_ispointer (MonoReflectionType *type)
2210 MONO_ARCH_SAVE_REGS;
2212 return type->type->type == MONO_TYPE_PTR;
2216 ves_icall_type_isprimitive (MonoReflectionType *type)
2218 MONO_ARCH_SAVE_REGS;
2220 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)));
2224 ves_icall_type_isbyref (MonoReflectionType *type)
2226 MONO_ARCH_SAVE_REGS;
2228 return type->type->byref;
2232 ves_icall_type_iscomobject (MonoReflectionType *type)
2234 MonoClass *klass = mono_class_from_mono_type (type->type);
2235 mono_class_init_or_throw (klass);
2237 return (klass && klass->is_com_object);
2240 static MonoReflectionModule*
2241 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2243 MonoClass *class = mono_class_from_mono_type (type->type);
2244 return mono_module_get_object (mono_object_domain (type), class->image);
2247 static MonoReflectionAssembly*
2248 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2250 MonoDomain *domain = mono_domain_get ();
2251 MonoClass *class = mono_class_from_mono_type (type->type);
2252 return mono_assembly_get_object (domain, class->image->assembly);
2255 static MonoReflectionType*
2256 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2258 MonoDomain *domain = mono_domain_get ();
2261 MONO_ARCH_SAVE_REGS;
2263 if (type->type->byref)
2265 if (type->type->type == MONO_TYPE_VAR)
2266 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2267 else if (type->type->type == MONO_TYPE_MVAR)
2268 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2270 class = mono_class_from_mono_type (type->type)->nested_in;
2272 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2276 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2278 MonoDomain *domain = mono_domain_get ();
2279 MonoClass *class = mono_class_from_mono_type (type->type);
2281 if (type->type->byref) {
2282 char *n = g_strdup_printf ("%s&", class->name);
2283 MonoString *res = mono_string_new (domain, n);
2289 return mono_string_new (domain, class->name);
2294 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2296 MonoDomain *domain = mono_domain_get ();
2297 MonoClass *class = mono_class_from_mono_type (type->type);
2299 while (class->nested_in)
2300 class = class->nested_in;
2302 if (class->name_space [0] == '\0')
2305 return mono_string_new (domain, class->name_space);
2309 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2313 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2314 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2316 class = mono_class_from_mono_type (type->type);
2317 mono_class_init_or_throw (class);
2323 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2326 MonoClass *klass, *pklass;
2327 MonoDomain *domain = mono_object_domain (type);
2328 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2330 MONO_ARCH_SAVE_REGS;
2332 klass = mono_class_from_mono_type (type->type);
2333 mono_class_init_or_throw (klass);
2335 if (klass->generic_container) {
2336 MonoGenericContainer *container = klass->generic_container;
2337 res = mono_array_new_specific (array_vtable, container->type_argc);
2338 for (i = 0; i < container->type_argc; ++i) {
2339 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2340 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2342 } else if (klass->generic_class) {
2343 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2344 res = mono_array_new_specific (array_vtable, inst->type_argc);
2345 for (i = 0; i < inst->type_argc; ++i)
2346 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2348 res = mono_array_new_specific (array_vtable, 0);
2354 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2357 MONO_ARCH_SAVE_REGS;
2359 if (!IS_MONOTYPE (type))
2362 if (type->type->byref)
2365 klass = mono_class_from_mono_type (type->type);
2366 return klass->generic_container != NULL;
2369 static MonoReflectionType*
2370 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2373 MONO_ARCH_SAVE_REGS;
2375 if (type->type->byref)
2378 klass = mono_class_from_mono_type (type->type);
2379 mono_class_init_or_throw (klass);
2381 if (klass->generic_container) {
2382 return type; /* check this one */
2384 if (klass->generic_class) {
2385 MonoClass *generic_class = klass->generic_class->container_class;
2388 tb = mono_class_get_ref_info (generic_class);
2390 if (generic_class->wastypebuilder && tb)
2393 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2398 static MonoReflectionType*
2399 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2401 MonoType *geninst, **types;
2404 g_assert (IS_MONOTYPE (type));
2405 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2407 count = mono_array_length (type_array);
2408 types = g_new0 (MonoType *, count);
2410 for (i = 0; i < count; i++) {
2411 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2412 types [i] = t->type;
2415 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2420 return mono_type_get_object (mono_object_domain (type), geninst);
2424 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2427 MONO_ARCH_SAVE_REGS;
2429 if (type->type->byref)
2432 klass = mono_class_from_mono_type (type->type);
2434 return klass->generic_class != NULL;
2438 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2441 MONO_ARCH_SAVE_REGS;
2443 if (!IS_MONOTYPE (type))
2446 if (type->type->byref)
2449 klass = mono_class_from_mono_type (type->type);
2450 return klass->generic_class != NULL || klass->generic_container != NULL;
2454 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2456 MONO_ARCH_SAVE_REGS;
2458 if (!IS_MONOTYPE (type))
2461 if (is_generic_parameter (type->type))
2462 return mono_type_get_generic_param_num (type->type);
2466 static GenericParameterAttributes
2467 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2469 MONO_ARCH_SAVE_REGS;
2471 g_assert (IS_MONOTYPE (type));
2472 g_assert (is_generic_parameter (type->type));
2473 return mono_generic_param_info (type->type->data.generic_param)->flags;
2477 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2479 MonoGenericParamInfo *param_info;
2485 MONO_ARCH_SAVE_REGS;
2487 g_assert (IS_MONOTYPE (type));
2489 domain = mono_object_domain (type);
2490 param_info = mono_generic_param_info (type->type->data.generic_param);
2491 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2494 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2495 for (i = 0; i < count; i++)
2496 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2503 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2505 MONO_ARCH_SAVE_REGS;
2506 return is_generic_parameter (type->type);
2510 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2512 MONO_ARCH_SAVE_REGS;
2513 return is_generic_parameter (tb->type.type);
2517 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2518 MonoReflectionType *t)
2520 enumtype->type = t->type;
2523 static MonoReflectionMethod*
2524 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2525 MonoReflectionMethod* generic)
2532 MONO_ARCH_SAVE_REGS;
2534 domain = ((MonoObject *)type)->vtable->domain;
2536 klass = mono_class_from_mono_type (type->type);
2537 mono_class_init_or_throw (klass);
2540 while ((method = mono_class_get_methods (klass, &iter))) {
2541 if (method->token == generic->method->token)
2542 return mono_method_get_object (domain, method, klass);
2550 static MonoReflectionMethod *
2551 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2554 MonoType *type = ref_type->type;
2556 MONO_ARCH_SAVE_REGS;
2558 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2559 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2560 if (type->type == MONO_TYPE_VAR)
2563 method = mono_type_get_generic_param_owner (type)->owner.method;
2565 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2568 static MonoReflectionDllImportAttribute*
2569 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2571 static MonoClass *DllImportAttributeClass = NULL;
2572 MonoDomain *domain = mono_domain_get ();
2573 MonoReflectionDllImportAttribute *attr;
2574 MonoImage *image = method->klass->image;
2575 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2576 MonoTableInfo *tables = image->tables;
2577 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2578 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2579 guint32 im_cols [MONO_IMPLMAP_SIZE];
2580 guint32 scope_token;
2581 const char *import = NULL;
2582 const char *scope = NULL;
2585 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2588 if (!DllImportAttributeClass) {
2589 DllImportAttributeClass =
2590 mono_class_from_name (mono_defaults.corlib,
2591 "System.Runtime.InteropServices", "DllImportAttribute");
2592 g_assert (DllImportAttributeClass);
2595 if (method->klass->image->dynamic) {
2596 MonoReflectionMethodAux *method_aux =
2597 g_hash_table_lookup (
2598 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2600 import = method_aux->dllentry;
2601 scope = method_aux->dll;
2604 if (!import || !scope) {
2605 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2610 if (piinfo->implmap_idx) {
2611 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2613 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2614 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2615 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2616 scope = mono_metadata_string_heap (image, scope_token);
2619 flags = piinfo->piflags;
2621 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2623 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2624 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2625 attr->call_conv = (flags & 0x700) >> 8;
2626 attr->charset = ((flags & 0x6) >> 1) + 1;
2627 if (attr->charset == 1)
2629 attr->exact_spelling = (flags & 0x1) != 0;
2630 attr->set_last_error = (flags & 0x40) != 0;
2631 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2632 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2633 attr->preserve_sig = FALSE;
2638 static MonoReflectionMethod *
2639 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2641 MonoMethodInflated *imethod;
2644 MONO_ARCH_SAVE_REGS;
2646 if (method->method->is_generic)
2649 if (!method->method->is_inflated)
2652 imethod = (MonoMethodInflated *) method->method;
2654 result = imethod->declaring;
2655 /* Not a generic method. */
2656 if (!result->is_generic)
2659 if (method->method->klass->image->dynamic) {
2660 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2661 MonoReflectionMethod *res;
2664 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2665 * the dynamic case as well ?
2667 mono_loader_lock ();
2668 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2669 mono_loader_unlock ();
2675 if (imethod->context.class_inst) {
2676 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2677 /*Generic methods gets the context of the GTD.*/
2678 if (mono_class_get_context (klass))
2679 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2682 return mono_method_get_object (mono_object_domain (method), result, NULL);
2686 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2688 MONO_ARCH_SAVE_REGS;
2690 return mono_method_signature (method->method)->generic_param_count != 0;
2694 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2696 MONO_ARCH_SAVE_REGS;
2698 return method->method->is_generic;
2702 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2707 MONO_ARCH_SAVE_REGS;
2709 domain = mono_object_domain (method);
2711 if (method->method->is_inflated) {
2712 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2715 count = inst->type_argc;
2716 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2718 for (i = 0; i < count; i++)
2719 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2725 count = mono_method_signature (method->method)->generic_param_count;
2726 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2728 for (i = 0; i < count; i++) {
2729 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2730 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2731 MonoClass *pklass = mono_class_from_generic_parameter (
2732 param, method->method->klass->image, TRUE);
2733 mono_array_setref (res, i,
2734 mono_type_get_object (domain, &pklass->byval_arg));
2741 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2744 * Invoke from reflection is supposed to always be a virtual call (the API
2745 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2746 * greater flexibility.
2748 MonoMethod *m = method->method;
2752 MONO_ARCH_SAVE_REGS;
2756 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2757 mono_security_core_clr_ensure_reflection_access_method (m);
2759 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2760 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2761 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2766 if (!mono_object_isinst (this, m->klass)) {
2767 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2770 m = mono_object_get_virtual_method (this, m);
2771 /* must pass the pointer to the value for valuetype methods */
2772 if (m->klass->valuetype)
2773 obj = mono_object_unbox (this);
2774 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2775 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2780 pcount = params? mono_array_length (params): 0;
2781 if (pcount != mono_method_signature (m)->param_count) {
2782 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2786 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2787 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."));
2791 if (m->klass->image->assembly->ref_only) {
2792 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."));
2796 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2799 intptr_t *lower_bounds;
2800 pcount = mono_array_length (params);
2801 lengths = alloca (sizeof (uintptr_t) * pcount);
2802 /* Note: the synthetized array .ctors have int32 as argument type */
2803 for (i = 0; i < pcount; ++i)
2804 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2806 if (m->klass->rank == pcount) {
2807 /* Only lengths provided. */
2808 lower_bounds = NULL;
2810 g_assert (pcount == (m->klass->rank * 2));
2811 /* lower bounds are first. */
2812 lower_bounds = (intptr_t*)lengths;
2813 lengths += m->klass->rank;
2816 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2818 return mono_runtime_invoke_array (m, obj, params, NULL);
2822 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2824 MonoDomain *domain = mono_object_domain (method);
2825 MonoMethod *m = method->method;
2826 MonoMethodSignature *sig = mono_method_signature (m);
2827 MonoArray *out_args;
2829 int i, j, outarg_count = 0;
2831 MONO_ARCH_SAVE_REGS;
2833 if (m->klass == mono_defaults.object_class) {
2835 if (!strcmp (m->name, "FieldGetter")) {
2836 MonoClass *k = this->vtable->klass;
2840 /* If this is a proxy, then it must be a CBO */
2841 if (k == mono_defaults.transparent_proxy_class) {
2842 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2843 this = tp->rp->unwrapped_server;
2845 k = this->vtable->klass;
2848 name = mono_array_get (params, MonoString *, 1);
2849 str = mono_string_to_utf8 (name);
2852 MonoClassField* field = mono_class_get_field_from_name (k, str);
2854 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2855 if (field_klass->valuetype)
2856 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2858 result = *((gpointer *)((char *)this + field->offset));
2860 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2861 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2862 mono_array_setref (out_args, 0, result);
2870 g_assert_not_reached ();
2872 } else if (!strcmp (m->name, "FieldSetter")) {
2873 MonoClass *k = this->vtable->klass;
2879 /* If this is a proxy, then it must be a CBO */
2880 if (k == mono_defaults.transparent_proxy_class) {
2881 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2882 this = tp->rp->unwrapped_server;
2884 k = this->vtable->klass;
2887 name = mono_array_get (params, MonoString *, 1);
2888 str = mono_string_to_utf8 (name);
2891 MonoClassField* field = mono_class_get_field_from_name (k, str);
2893 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2894 MonoObject *val = mono_array_get (params, gpointer, 2);
2896 if (field_klass->valuetype) {
2897 size = mono_type_size (field->type, &align);
2898 g_assert (size == mono_class_value_size (field_klass, NULL));
2899 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2901 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2904 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2905 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2915 g_assert_not_reached ();
2920 for (i = 0; i < mono_array_length (params); i++) {
2921 if (sig->params [i]->byref)
2925 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2927 /* handle constructors only for objects already allocated */
2928 if (!strcmp (method->method->name, ".ctor"))
2931 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2932 g_assert (!method->method->klass->valuetype);
2933 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2935 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2936 if (sig->params [i]->byref) {
2938 arg = mono_array_get (params, gpointer, i);
2939 mono_array_setref (out_args, j, arg);
2944 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2950 read_enum_value (char *mem, int type)
2954 return *(guint8*)mem;
2956 return *(gint8*)mem;
2958 return *(guint16*)mem;
2960 return *(gint16*)mem;
2962 return *(guint32*)mem;
2964 return *(gint32*)mem;
2966 return *(guint64*)mem;
2968 return *(gint64*)mem;
2970 g_assert_not_reached ();
2976 write_enum_value (char *mem, int type, guint64 value)
2980 case MONO_TYPE_I1: {
2981 guint8 *p = (guint8*)mem;
2986 case MONO_TYPE_I2: {
2987 guint16 *p = (void*)mem;
2992 case MONO_TYPE_I4: {
2993 guint32 *p = (void*)mem;
2998 case MONO_TYPE_I8: {
2999 guint64 *p = (void*)mem;
3004 g_assert_not_reached ();
3010 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3013 MonoClass *enumc, *objc;
3018 MONO_ARCH_SAVE_REGS;
3020 MONO_CHECK_ARG_NULL (enumType);
3021 MONO_CHECK_ARG_NULL (value);
3023 domain = mono_object_domain (enumType);
3024 enumc = mono_class_from_mono_type (enumType->type);
3026 mono_class_init_or_throw (enumc);
3028 objc = value->vtable->klass;
3030 if (!enumc->enumtype)
3031 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3032 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3033 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."));
3035 etype = mono_class_enum_basetype (enumc);
3037 /* MS throws this for typebuilders */
3038 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3040 res = mono_object_new (domain, enumc);
3041 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3042 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3048 ves_icall_System_Enum_get_value (MonoObject *this)
3056 MONO_ARCH_SAVE_REGS;
3061 g_assert (this->vtable->klass->enumtype);
3063 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3064 res = mono_object_new (mono_object_domain (this), enumc);
3065 dst = (char *)res + sizeof (MonoObject);
3066 src = (char *)this + sizeof (MonoObject);
3067 size = mono_class_value_size (enumc, NULL);
3069 memcpy (dst, src, size);
3074 static MonoReflectionType *
3075 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3080 MONO_ARCH_SAVE_REGS;
3082 klass = mono_class_from_mono_type (type->type);
3083 mono_class_init_or_throw (klass);
3085 etype = mono_class_enum_basetype (klass);
3087 /* MS throws this for typebuilders */
3088 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3090 return mono_type_get_object (mono_object_domain (type), etype);
3094 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3096 gpointer tdata = (char *)this + sizeof (MonoObject);
3097 gpointer odata = (char *)other + sizeof (MonoObject);
3098 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3099 g_assert (basetype);
3101 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3102 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3103 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3106 return me > other ? 1 : -1; \
3109 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3110 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3111 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3114 return me - other; \
3117 switch (basetype->type) {
3119 COMPARE_ENUM_VALUES (guint8);
3121 COMPARE_ENUM_VALUES (gint8);
3122 case MONO_TYPE_CHAR:
3124 COMPARE_ENUM_VALUES_RANGE (guint16);
3126 COMPARE_ENUM_VALUES (gint16);
3128 COMPARE_ENUM_VALUES (guint32);
3130 COMPARE_ENUM_VALUES (gint32);
3132 COMPARE_ENUM_VALUES (guint64);
3134 COMPARE_ENUM_VALUES (gint64);
3136 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3138 #undef COMPARE_ENUM_VALUES_RANGE
3139 #undef COMPARE_ENUM_VALUES
3144 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3146 gpointer data = (char *)this + sizeof (MonoObject);
3147 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3148 g_assert (basetype);
3150 switch (basetype->type) {
3152 return *((gint8*)data);
3154 return *((guint8*)data);
3155 case MONO_TYPE_CHAR:
3157 return *((guint16*)data);
3160 return *((gint16*)data);
3162 return *((guint32*)data);
3164 return *((gint32*)data);
3166 case MONO_TYPE_I8: {
3167 gint64 value = *((gint64*)data);
3168 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3171 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3177 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3179 MonoDomain *domain = mono_object_domain (type);
3180 MonoClass *enumc = mono_class_from_mono_type (type->type);
3181 guint j = 0, nvalues, crow;
3183 MonoClassField *field;
3185 MONO_ARCH_SAVE_REGS;
3187 mono_class_init_or_throw (enumc);
3189 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3190 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3191 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3192 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3196 while ((field = mono_class_get_fields (enumc, &iter))) {
3199 MonoTypeEnum def_type;
3201 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3203 if (mono_field_is_deleted (field))
3205 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3207 p = mono_class_get_field_default_value (field, &def_type);
3208 len = mono_metadata_decode_blob_size (p, &p);
3209 switch (mono_class_enum_basetype (enumc)->type) {
3212 mono_array_set (info->values, gchar, j, *p);
3214 case MONO_TYPE_CHAR:
3217 mono_array_set (info->values, gint16, j, read16 (p));
3221 mono_array_set (info->values, gint32, j, read32 (p));
3225 mono_array_set (info->values, gint64, j, read64 (p));
3228 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3235 BFLAGS_IgnoreCase = 1,
3236 BFLAGS_DeclaredOnly = 2,
3237 BFLAGS_Instance = 4,
3239 BFLAGS_Public = 0x10,
3240 BFLAGS_NonPublic = 0x20,
3241 BFLAGS_FlattenHierarchy = 0x40,
3242 BFLAGS_InvokeMethod = 0x100,
3243 BFLAGS_CreateInstance = 0x200,
3244 BFLAGS_GetField = 0x400,
3245 BFLAGS_SetField = 0x800,
3246 BFLAGS_GetProperty = 0x1000,
3247 BFLAGS_SetProperty = 0x2000,
3248 BFLAGS_ExactBinding = 0x10000,
3249 BFLAGS_SuppressChangeType = 0x20000,
3250 BFLAGS_OptionalParamBinding = 0x40000
3253 static MonoReflectionField *
3254 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3257 MonoClass *startklass, *klass;
3259 MonoClassField *field;
3262 int (*compare_func) (const char *s1, const char *s2) = NULL;
3263 domain = ((MonoObject *)type)->vtable->domain;
3264 klass = startklass = mono_class_from_mono_type (type->type);
3265 mono_class_init_or_throw (klass);
3268 mono_raise_exception (mono_get_exception_argument_null ("name"));
3269 if (type->type->byref)
3272 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3275 if (klass->exception_type != MONO_EXCEPTION_NONE)
3276 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3279 while ((field = mono_class_get_fields (klass, &iter))) {
3282 if (field->type == NULL)
3284 if (mono_field_is_deleted (field))
3286 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3287 if (bflags & BFLAGS_Public)
3289 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3290 if (bflags & BFLAGS_NonPublic) {
3297 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3298 if (bflags & BFLAGS_Static)
3299 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3302 if (bflags & BFLAGS_Instance)
3309 utf8_name = mono_string_to_utf8 (name);
3311 if (compare_func (mono_field_get_name (field), utf8_name)) {
3317 return mono_field_get_object (domain, klass, field);
3319 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3326 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3329 MonoClass *startklass, *klass, *refklass;
3334 MonoClassField *field;
3335 MonoPtrArray tmp_array;
3337 MONO_ARCH_SAVE_REGS;
3339 domain = ((MonoObject *)type)->vtable->domain;
3340 if (type->type->byref)
3341 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3342 klass = startklass = mono_class_from_mono_type (type->type);
3343 refklass = mono_class_from_mono_type (reftype->type);
3345 mono_ptr_array_init (tmp_array, 2);
3348 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3349 mono_ptr_array_destroy (tmp_array);
3350 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3354 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3355 guint32 flags = mono_field_get_flags (field);
3357 if (mono_field_is_deleted_with_flags (field, flags))
3359 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3360 if (bflags & BFLAGS_Public)
3362 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3363 if (bflags & BFLAGS_NonPublic) {
3370 if (flags & FIELD_ATTRIBUTE_STATIC) {
3371 if (bflags & BFLAGS_Static)
3372 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3375 if (bflags & BFLAGS_Instance)
3381 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3382 mono_ptr_array_append (tmp_array, member);
3384 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3387 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3389 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3390 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3392 mono_ptr_array_destroy (tmp_array);
3398 method_nonpublic (MonoMethod* method, gboolean start_klass)
3400 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3401 case METHOD_ATTRIBUTE_ASSEM:
3402 return (start_klass || mono_defaults.generic_ilist_class);
3403 case METHOD_ATTRIBUTE_PRIVATE:
3405 case METHOD_ATTRIBUTE_PUBLIC:
3413 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3415 static MonoClass *MethodInfo_array;
3417 MonoClass *startklass, *klass, *refklass;
3422 int i, len, match, nslots;
3423 /*FIXME, use MonoBitSet*/
3424 guint32 method_slots_default [8];
3425 guint32 *method_slots = NULL;
3426 gchar *mname = NULL;
3427 int (*compare_func) (const char *s1, const char *s2) = NULL;
3428 MonoVTable *array_vtable;
3430 MonoPtrArray tmp_array;
3432 mono_ptr_array_init (tmp_array, 4);
3434 if (!MethodInfo_array) {
3435 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3436 mono_memory_barrier ();
3437 MethodInfo_array = klass;
3440 domain = ((MonoObject *)type)->vtable->domain;
3441 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3442 if (type->type->byref)
3443 return mono_array_new_specific (array_vtable, 0);
3444 klass = startklass = mono_class_from_mono_type (type->type);
3445 refklass = mono_class_from_mono_type (reftype->type);
3449 mname = mono_string_to_utf8 (name);
3450 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3453 /* An optimization for calls made from Delegate:CreateDelegate () */
3454 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3455 method = mono_get_delegate_invoke (klass);
3456 if (mono_loader_get_last_error ())
3459 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3461 res = mono_array_new_specific (array_vtable, 1);
3462 mono_array_setref (res, 0, member);
3467 mono_class_setup_vtable (klass);
3468 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3471 if (is_generic_parameter (type->type))
3472 nslots = mono_class_get_vtable_size (klass->parent);
3474 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3475 if (nslots >= sizeof (method_slots_default) * 8) {
3476 method_slots = g_new0 (guint32, nslots / 32 + 1);
3478 method_slots = method_slots_default;
3479 memset (method_slots, 0, sizeof (method_slots_default));
3482 mono_class_setup_vtable (klass);
3483 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3487 while ((method = mono_class_get_methods (klass, &iter))) {
3489 if (method->slot != -1) {
3490 g_assert (method->slot < nslots);
3491 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3493 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3494 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3497 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3499 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3500 if (bflags & BFLAGS_Public)
3502 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3508 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3509 if (bflags & BFLAGS_Static)
3510 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3513 if (bflags & BFLAGS_Instance)
3521 if (compare_func (mname, method->name))
3527 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3529 mono_ptr_array_append (tmp_array, member);
3531 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3535 if (method_slots != method_slots_default)
3536 g_free (method_slots);
3538 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3540 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3541 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3543 mono_ptr_array_destroy (tmp_array);
3548 if (method_slots != method_slots_default)
3549 g_free (method_slots);
3550 mono_ptr_array_destroy (tmp_array);
3551 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3552 ex = mono_class_get_exception_for_failure (klass);
3554 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3555 mono_loader_clear_error ();
3557 mono_raise_exception (ex);
3562 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3565 static MonoClass *System_Reflection_ConstructorInfo;
3566 MonoClass *startklass, *klass, *refklass;
3571 gpointer iter = NULL;
3572 MonoPtrArray tmp_array;
3574 MONO_ARCH_SAVE_REGS;
3576 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3578 domain = ((MonoObject *)type)->vtable->domain;
3579 if (type->type->byref)
3580 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3581 klass = startklass = mono_class_from_mono_type (type->type);
3582 refklass = mono_class_from_mono_type (reftype->type);
3584 if (!System_Reflection_ConstructorInfo)
3585 System_Reflection_ConstructorInfo = mono_class_from_name (
3586 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3589 while ((method = mono_class_get_methods (klass, &iter))) {
3591 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3593 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3594 if (bflags & BFLAGS_Public)
3597 if (bflags & BFLAGS_NonPublic)
3603 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3604 if (bflags & BFLAGS_Static)
3605 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3608 if (bflags & BFLAGS_Instance)
3614 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3616 mono_ptr_array_append (tmp_array, member);
3619 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3621 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3622 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3624 mono_ptr_array_destroy (tmp_array);
3630 property_hash (gconstpointer data)
3632 MonoProperty *prop = (MonoProperty*)data;
3634 return g_str_hash (prop->name);
3638 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3640 // Properties are hide-by-name-and-signature
3641 if (!g_str_equal (prop1->name, prop2->name))
3644 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3646 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3652 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3657 return method_nonpublic (accessor, start_klass);
3661 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3665 static MonoClass *System_Reflection_PropertyInfo;
3666 MonoClass *startklass, *klass;
3672 gchar *propname = NULL;
3673 int (*compare_func) (const char *s1, const char *s2) = NULL;
3675 GHashTable *properties = NULL;
3676 MonoPtrArray tmp_array;
3678 MONO_ARCH_SAVE_REGS;
3680 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3682 if (!System_Reflection_PropertyInfo)
3683 System_Reflection_PropertyInfo = mono_class_from_name (
3684 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3686 domain = ((MonoObject *)type)->vtable->domain;
3687 if (type->type->byref)
3688 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3689 klass = startklass = mono_class_from_mono_type (type->type);
3692 propname = mono_string_to_utf8 (name);
3693 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3696 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3698 mono_class_setup_vtable (klass);
3699 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3703 while ((prop = mono_class_get_properties (klass, &iter))) {
3709 flags = method->flags;
3712 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3713 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3714 if (bflags & BFLAGS_Public)
3716 } else if (bflags & BFLAGS_NonPublic) {
3717 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3718 property_accessor_nonpublic(prop->set, startklass == klass)) {
3725 if (flags & METHOD_ATTRIBUTE_STATIC) {
3726 if (bflags & BFLAGS_Static)
3727 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3730 if (bflags & BFLAGS_Instance)
3739 if (compare_func (propname, prop->name))
3743 if (g_hash_table_lookup (properties, prop))
3746 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3748 g_hash_table_insert (properties, prop, prop);
3750 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3753 g_hash_table_destroy (properties);
3756 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3757 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3758 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3760 mono_ptr_array_destroy (tmp_array);
3766 g_hash_table_destroy (properties);
3769 mono_ptr_array_destroy (tmp_array);
3771 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3772 ex = mono_class_get_exception_for_failure (klass);
3774 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3775 mono_loader_clear_error ();
3777 mono_raise_exception (ex);
3781 static MonoReflectionEvent *
3782 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3785 MonoClass *klass, *startklass;
3790 int (*compare_func) (const char *s1, const char *s2);
3792 MONO_ARCH_SAVE_REGS;
3794 event_name = mono_string_to_utf8 (name);
3795 if (type->type->byref)
3797 klass = startklass = mono_class_from_mono_type (type->type);
3798 domain = mono_object_domain (type);
3800 mono_class_init_or_throw (klass);
3802 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3804 if (klass->exception_type != MONO_EXCEPTION_NONE)
3805 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3808 while ((event = mono_class_get_events (klass, &iter))) {
3809 if (compare_func (event->name, event_name))
3812 method = event->add;
3814 method = event->remove;
3816 method = event->raise;
3818 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3819 if (!(bflags & BFLAGS_Public))
3822 if (!(bflags & BFLAGS_NonPublic))
3824 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3828 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3829 if (!(bflags & BFLAGS_Static))
3831 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3834 if (!(bflags & BFLAGS_Instance))
3838 if (!(bflags & BFLAGS_NonPublic))
3841 g_free (event_name);
3842 return mono_event_get_object (domain, startklass, event);
3845 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3848 g_free (event_name);
3853 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3857 static MonoClass *System_Reflection_EventInfo;
3858 MonoClass *startklass, *klass;
3865 MonoPtrArray tmp_array;
3867 MONO_ARCH_SAVE_REGS;
3869 mono_ptr_array_init (tmp_array, 4);
3871 if (!System_Reflection_EventInfo)
3872 System_Reflection_EventInfo = mono_class_from_name (
3873 mono_defaults.corlib, "System.Reflection", "EventInfo");
3875 domain = mono_object_domain (type);
3876 if (type->type->byref)
3877 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3878 klass = startklass = mono_class_from_mono_type (type->type);
3881 mono_class_setup_vtable (klass);
3882 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3886 while ((event = mono_class_get_events (klass, &iter))) {
3888 method = event->add;
3890 method = event->remove;
3892 method = event->raise;
3894 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3895 if (bflags & BFLAGS_Public)
3897 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3898 if (bflags & BFLAGS_NonPublic)
3903 if (bflags & BFLAGS_NonPublic)
3909 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3910 if (bflags & BFLAGS_Static)
3911 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3914 if (bflags & BFLAGS_Instance)
3919 if (bflags & BFLAGS_Instance)
3923 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3925 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3928 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3930 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3931 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3933 mono_ptr_array_destroy (tmp_array);
3938 mono_ptr_array_destroy (tmp_array);
3939 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3940 ex = mono_class_get_exception_for_failure (klass);
3942 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3943 mono_loader_clear_error ();
3945 mono_raise_exception (ex);
3949 static MonoReflectionType *
3950 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3958 MONO_ARCH_SAVE_REGS;
3961 mono_raise_exception (mono_get_exception_argument_null ("name"));
3963 domain = ((MonoObject *)type)->vtable->domain;
3964 if (type->type->byref)
3966 klass = mono_class_from_mono_type (type->type);
3968 str = mono_string_to_utf8 (name);
3971 if (klass->exception_type != MONO_EXCEPTION_NONE)
3972 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3975 * If a nested type is generic, return its generic type definition.
3976 * Note that this means that the return value is essentially a
3977 * nested type of the generic type definition of @klass.
3979 * A note in MSDN claims that a generic type definition can have
3980 * nested types that aren't generic. In any case, the container of that
3981 * nested type would be the generic type definition.
3983 if (klass->generic_class)
3984 klass = klass->generic_class->container_class;
3987 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3989 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3990 if (bflags & BFLAGS_Public)
3993 if (bflags & BFLAGS_NonPublic)
3998 if (strcmp (nested->name, str) == 0){
4000 return mono_type_get_object (domain, &nested->byval_arg);
4003 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4010 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4019 MonoPtrArray tmp_array;
4021 MONO_ARCH_SAVE_REGS;
4023 domain = ((MonoObject *)type)->vtable->domain;
4024 if (type->type->byref)
4025 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4026 klass = mono_class_from_mono_type (type->type);
4029 * If a nested type is generic, return its generic type definition.
4030 * Note that this means that the return value is essentially the set
4031 * of nested types of the generic type definition of @klass.
4033 * A note in MSDN claims that a generic type definition can have
4034 * nested types that aren't generic. In any case, the container of that
4035 * nested type would be the generic type definition.
4037 if (klass->generic_class)
4038 klass = klass->generic_class->container_class;
4040 mono_ptr_array_init (tmp_array, 1);
4042 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4044 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4045 if (bflags & BFLAGS_Public)
4048 if (bflags & BFLAGS_NonPublic)
4053 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4054 mono_ptr_array_append (tmp_array, member);
4057 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4059 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4060 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4062 mono_ptr_array_destroy (tmp_array);
4067 static MonoReflectionType*
4068 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4071 MonoType *type = NULL;
4072 MonoTypeNameParse info;
4073 gboolean type_resolve;
4075 MONO_ARCH_SAVE_REGS;
4077 /* On MS.NET, this does not fire a TypeResolve event */
4078 type_resolve = TRUE;
4079 str = mono_string_to_utf8 (name);
4080 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4081 if (!mono_reflection_parse_type (str, &info)) {
4083 mono_reflection_free_type_info (&info);
4084 if (throwOnError) /* uhm: this is a parse error, though... */
4085 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4086 /*g_print ("failed parse\n");*/
4090 if (info.assembly.name) {
4092 mono_reflection_free_type_info (&info);
4094 /* 1.0 and 2.0 throw different exceptions */
4095 if (mono_defaults.generic_ilist_class)
4096 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4098 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4103 if (module != NULL) {
4105 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4110 if (assembly->assembly->dynamic) {
4111 /* Enumerate all modules */
4112 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4116 if (abuilder->modules) {
4117 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4118 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4119 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4125 if (!type && abuilder->loaded_modules) {
4126 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4127 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4128 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4135 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4137 mono_reflection_free_type_info (&info);
4139 MonoException *e = NULL;
4142 e = mono_get_exception_type_load (name, NULL);
4144 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4145 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4147 mono_loader_clear_error ();
4150 mono_raise_exception (e);
4153 } else if (mono_loader_get_last_error ()) {
4155 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4156 mono_loader_clear_error ();
4159 if (type->type == MONO_TYPE_CLASS) {
4160 MonoClass *klass = mono_type_get_class (type);
4162 if (mono_is_security_manager_active () && !klass->exception_type)
4163 /* Some security problems are detected during generic vtable construction */
4164 mono_class_setup_vtable (klass);
4165 /* need to report exceptions ? */
4166 if (throwOnError && klass->exception_type) {
4167 /* report SecurityException (or others) that occured when loading the assembly */
4168 MonoException *exc = mono_class_get_exception_for_failure (klass);
4169 mono_loader_clear_error ();
4170 mono_raise_exception (exc);
4171 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4176 /* g_print ("got it\n"); */
4177 return mono_type_get_object (mono_object_domain (assembly), type);
4181 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4184 gchar *shadow_ini_file;
4187 /* Check for shadow-copied assembly */
4188 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4189 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4191 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4192 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4198 g_free (shadow_ini_file);
4199 if (content != NULL) {
4202 *filename = content;
4210 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4212 MonoDomain *domain = mono_object_domain (assembly);
4213 MonoAssembly *mass = assembly->assembly;
4214 MonoString *res = NULL;
4219 MONO_ARCH_SAVE_REGS;
4221 if (g_path_is_absolute (mass->image->name)) {
4222 absolute = g_strdup (mass->image->name);
4223 dirname = g_path_get_dirname (absolute);
4225 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4226 dirname = g_strdup (mass->basedir);
4229 replace_shadow_path (domain, dirname, &absolute);
4234 for (i = strlen (absolute) - 1; i >= 0; i--)
4235 if (absolute [i] == '\\')
4240 uri = g_filename_to_uri (absolute, NULL, NULL);
4242 const char *prepend = "file://";
4244 if (*absolute == '/' && *(absolute + 1) == '/') {
4247 prepend = "file:///";
4250 uri = g_strconcat (prepend, absolute, NULL);
4254 res = mono_string_new (domain, uri);
4262 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4264 MonoAssembly *mass = assembly->assembly;
4266 MONO_ARCH_SAVE_REGS;
4268 return mass->in_gac;
4271 static MonoReflectionAssembly*
4272 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4276 MonoImageOpenStatus status;
4278 MONO_ARCH_SAVE_REGS;
4280 name = mono_string_to_utf8 (mname);
4281 res = mono_assembly_load_with_partial_name (name, &status);
4287 return mono_assembly_get_object (mono_domain_get (), res);
4291 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4293 MonoDomain *domain = mono_object_domain (assembly);
4296 MONO_ARCH_SAVE_REGS;
4298 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4304 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4306 MONO_ARCH_SAVE_REGS;
4308 return assembly->assembly->ref_only;
4312 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4314 MonoDomain *domain = mono_object_domain (assembly);
4316 MONO_ARCH_SAVE_REGS;
4318 return mono_string_new (domain, assembly->assembly->image->version);
4321 static MonoReflectionMethod*
4322 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4324 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4326 MONO_ARCH_SAVE_REGS;
4330 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4333 static MonoReflectionModule*
4334 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4336 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4340 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4342 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4343 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4347 MONO_ARCH_SAVE_REGS;
4349 for (i = 0; i < table->rows; ++i) {
4350 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4351 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4357 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4359 static MonoClass *System_Version = NULL;
4360 static MonoMethod *create_version = NULL;
4364 if (!System_Version) {
4365 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4366 g_assert (System_Version);
4369 if (!create_version) {
4370 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4371 create_version = mono_method_desc_search_in_class (desc, System_Version);
4372 g_assert (create_version);
4373 mono_method_desc_free (desc);
4379 args [3] = &revision;
4380 result = mono_object_new (domain, System_Version);
4381 mono_runtime_invoke (create_version, result, args, NULL);
4387 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4389 static MonoClass *System_Reflection_AssemblyName;
4391 MonoDomain *domain = mono_object_domain (assembly);
4393 static MonoMethod *create_culture = NULL;
4394 MonoImage *image = assembly->assembly->image;
4397 MONO_ARCH_SAVE_REGS;
4399 if (!System_Reflection_AssemblyName)
4400 System_Reflection_AssemblyName = mono_class_from_name (
4401 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4403 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4406 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4408 if (count > 0 && !create_culture) {
4409 MonoMethodDesc *desc = mono_method_desc_new (
4410 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4411 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4412 g_assert (create_culture);
4413 mono_method_desc_free (desc);
4416 for (i = 0; i < count; i++) {
4417 MonoReflectionAssemblyName *aname;
4418 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4420 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4422 aname = (MonoReflectionAssemblyName *) mono_object_new (
4423 domain, System_Reflection_AssemblyName);
4425 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4427 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4428 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4429 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4430 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4431 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4432 aname->versioncompat = 1; /* SameMachine (default) */
4433 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4434 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4436 if (create_culture) {
4438 MonoBoolean assembly_ref = 1;
4439 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4440 args [1] = &assembly_ref;
4441 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4444 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4445 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4446 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4448 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4449 /* public key token isn't copied - the class library will
4450 automatically generate it from the public key if required */
4451 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4452 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4454 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4455 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4458 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4461 /* note: this function doesn't return the codebase on purpose (i.e. it can
4462 be used under partial trust as path information isn't present). */
4464 mono_array_setref (result, i, aname);
4475 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4477 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4479 mono_array_setref (info->res, info->idx, name);
4484 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4486 MonoImage *img = assembly->assembly->image;
4491 MONO_ARCH_SAVE_REGS;
4493 mono_image_lock (img);
4494 mono_image_init_name_cache (img);
4497 len = g_hash_table_size (img->name_cache);
4498 mono_image_unlock (img);
4500 /*we can't create objects holding the image lock */
4501 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4503 mono_image_lock (img);
4504 /*len might have changed, create a new array*/
4505 if (len != g_hash_table_size (img->name_cache))
4510 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4511 mono_image_unlock (img);
4516 /* move this in some file in mono/util/ */
4518 g_concat_dir_and_file (const char *dir, const char *file)
4520 g_return_val_if_fail (dir != NULL, NULL);
4521 g_return_val_if_fail (file != NULL, NULL);
4524 * If the directory name doesn't have a / on the end, we need
4525 * to add one so we get a proper path to the file
4527 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4528 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4530 return g_strconcat (dir, file, NULL);
4534 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4536 char *n = mono_string_to_utf8 (name);
4537 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4539 guint32 cols [MONO_MANIFEST_SIZE];
4540 guint32 impl, file_idx;
4544 MONO_ARCH_SAVE_REGS;
4546 for (i = 0; i < table->rows; ++i) {
4547 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4548 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4549 if (strcmp (val, n) == 0)
4553 if (i == table->rows)
4556 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4559 * this code should only be called after obtaining the
4560 * ResourceInfo and handling the other cases.
4562 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4563 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4565 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4570 module = assembly->assembly->image;
4572 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4574 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4578 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4580 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4582 guint32 cols [MONO_MANIFEST_SIZE];
4583 guint32 file_cols [MONO_FILE_SIZE];
4587 MONO_ARCH_SAVE_REGS;
4589 n = mono_string_to_utf8 (name);
4590 for (i = 0; i < table->rows; ++i) {
4591 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4592 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4593 if (strcmp (val, n) == 0)
4597 if (i == table->rows)
4600 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4601 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4604 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4605 case MONO_IMPLEMENTATION_FILE:
4606 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4607 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4608 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4609 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4610 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4611 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4614 info->location = RESOURCE_LOCATION_EMBEDDED;
4617 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4618 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4619 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4620 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4621 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4622 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4624 mono_raise_exception (ex);
4626 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4628 /* Obtain info recursively */
4629 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4630 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4633 case MONO_IMPLEMENTATION_EXP_TYPE:
4634 g_assert_not_reached ();
4643 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4645 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4646 MonoArray *result = NULL;
4651 MONO_ARCH_SAVE_REGS;
4653 /* check hash if needed */
4655 n = mono_string_to_utf8 (name);
4656 for (i = 0; i < table->rows; ++i) {
4657 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4658 if (strcmp (val, n) == 0) {
4661 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4662 fn = mono_string_new (mono_object_domain (assembly), n);
4664 return (MonoObject*)fn;
4672 for (i = 0; i < table->rows; ++i) {
4673 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4677 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4680 for (i = 0; i < table->rows; ++i) {
4681 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4682 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4683 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4684 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4689 return (MonoObject*)result;
4693 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4695 MonoDomain *domain = mono_domain_get();
4698 int i, j, file_count = 0;
4699 MonoImage **modules;
4700 guint32 module_count, real_module_count;
4701 MonoTableInfo *table;
4702 guint32 cols [MONO_FILE_SIZE];
4703 MonoImage *image = assembly->assembly->image;
4705 g_assert (image != NULL);
4706 g_assert (!assembly->assembly->dynamic);
4708 table = &image->tables [MONO_TABLE_FILE];
4709 file_count = table->rows;
4711 modules = image->modules;
4712 module_count = image->module_count;
4714 real_module_count = 0;
4715 for (i = 0; i < module_count; ++i)
4717 real_module_count ++;
4719 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4720 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4722 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4724 for (i = 0; i < module_count; ++i)
4726 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4730 for (i = 0; i < file_count; ++i, ++j) {
4731 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4732 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4733 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4735 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4737 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4738 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4740 mono_array_setref (res, j, mono_module_get_object (domain, m));
4747 static MonoReflectionMethod*
4748 ves_icall_GetCurrentMethod (void)
4750 MonoMethod *m = mono_method_get_last_managed ();
4752 while (m->is_inflated)
4753 m = ((MonoMethodInflated*)m)->declaring;
4755 return mono_method_get_object (mono_domain_get (), m, NULL);
4760 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4763 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4764 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4765 //method is inflated, we should inflate it on the other class
4766 MonoGenericContext ctx;
4767 ctx.method_inst = inflated->context.method_inst;
4768 ctx.class_inst = inflated->context.class_inst;
4769 if (klass->generic_class)
4770 ctx.class_inst = klass->generic_class->context.class_inst;
4771 else if (klass->generic_container)
4772 ctx.class_inst = klass->generic_container->context.class_inst;
4773 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4776 mono_class_setup_methods (method->klass);
4777 if (method->klass->exception_type)
4779 for (i = 0; i < method->klass->method.count; ++i) {
4780 if (method->klass->methods [i] == method) {
4785 mono_class_setup_methods (klass);
4786 if (klass->exception_type)
4788 g_assert (offset >= 0 && offset < klass->method.count);
4789 return klass->methods [offset];
4792 static MonoReflectionMethod*
4793 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4797 klass = mono_class_from_mono_type (type);
4798 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4800 if (method->klass != klass) {
4801 method = mono_method_get_equivalent_method (method, klass);
4806 klass = method->klass;
4807 return mono_method_get_object (mono_domain_get (), method, klass);
4810 static MonoReflectionMethod*
4811 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4813 return mono_method_get_object (mono_domain_get (), method, NULL);
4816 static MonoReflectionMethodBody*
4817 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4819 return mono_method_body_get_object (mono_domain_get (), method);
4822 static MonoReflectionAssembly*
4823 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4825 MonoMethod *dest = NULL;
4827 MONO_ARCH_SAVE_REGS;
4829 mono_stack_walk_no_il (get_executing, &dest);
4830 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4834 static MonoReflectionAssembly*
4835 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4837 MonoDomain* domain = mono_domain_get ();
4839 MONO_ARCH_SAVE_REGS;
4841 if (!domain->entry_assembly)
4844 return mono_assembly_get_object (domain, domain->entry_assembly);
4847 static MonoReflectionAssembly*
4848 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4853 MONO_ARCH_SAVE_REGS;
4856 mono_stack_walk_no_il (get_executing, &dest);
4858 mono_stack_walk_no_il (get_caller, &dest);
4861 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4865 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4866 gboolean assembly_qualified)
4868 MonoDomain *domain = mono_object_domain (object);
4869 MonoTypeNameFormat format;
4874 format = assembly_qualified ?
4875 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4876 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4878 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4880 name = mono_type_get_name_full (object->type, format);
4884 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4889 res = mono_string_new (domain, name);
4896 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4898 MonoClass *klass = mono_class_from_mono_type (this->type);
4899 mono_class_init_or_throw (klass);
4900 return mono_security_core_clr_class_level (klass);
4904 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4906 static MonoMethod *create_culture = NULL;
4909 const char *pkey_ptr;
4911 MonoBoolean assembly_ref = 0;
4913 MONO_ARCH_SAVE_REGS;
4915 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4916 aname->major = name->major;
4917 aname->minor = name->minor;
4918 aname->build = name->build;
4919 aname->flags = name->flags;
4920 aname->revision = name->revision;
4921 aname->hashalg = name->hash_alg;
4922 aname->versioncompat = 1; /* SameMachine (default) */
4924 if (by_default_version)
4925 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4928 if (absolute != NULL && *absolute != '\0') {
4929 const gchar *prepend = "file://";
4932 codebase = g_strdup (absolute);
4937 for (i = strlen (codebase) - 1; i >= 0; i--)
4938 if (codebase [i] == '\\')
4941 if (*codebase == '/' && *(codebase + 1) == '/') {
4944 prepend = "file:///";
4948 result = g_strconcat (prepend, codebase, NULL);
4954 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4958 if (!create_culture) {
4959 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4960 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4961 g_assert (create_culture);
4962 mono_method_desc_free (desc);
4965 if (name->culture) {
4966 args [0] = mono_string_new (domain, name->culture);
4967 args [1] = &assembly_ref;
4968 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4971 if (name->public_key) {
4972 pkey_ptr = (char*)name->public_key;
4973 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4975 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4976 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4977 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4978 } else if (default_publickey) {
4979 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4980 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4983 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4984 if (name->public_key_token [0]) {
4988 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4989 p = mono_array_addr (aname->keyToken, char, 0);
4991 for (i = 0, j = 0; i < 8; i++) {
4992 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4993 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4996 } else if (default_token) {
4997 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5002 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5004 MonoDomain *domain = mono_object_domain (assembly);
5005 MonoAssembly *mass = assembly->assembly;
5009 name = g_strdup_printf (
5010 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
5012 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
5013 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
5014 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
5015 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
5017 res = mono_string_new (domain, name);
5024 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5027 MonoAssembly *mass = assembly->assembly;
5029 MONO_ARCH_SAVE_REGS;
5031 if (g_path_is_absolute (mass->image->name)) {
5032 fill_reflection_assembly_name (mono_object_domain (assembly),
5033 aname, &mass->aname, mass->image->name, TRUE,
5037 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5039 fill_reflection_assembly_name (mono_object_domain (assembly),
5040 aname, &mass->aname, absolute, TRUE, TRUE,
5047 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5050 MonoImageOpenStatus status = MONO_IMAGE_OK;
5053 MonoAssemblyName name;
5056 MONO_ARCH_SAVE_REGS;
5058 filename = mono_string_to_utf8 (fname);
5060 dirname = g_path_get_dirname (filename);
5061 replace_shadow_path (mono_domain_get (), dirname, &filename);
5064 image = mono_image_open (filename, &status);
5070 if (status == MONO_IMAGE_IMAGE_INVALID)
5071 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5073 exc = mono_get_exception_file_not_found2 (NULL, fname);
5074 mono_raise_exception (exc);
5077 res = mono_assembly_fill_assembly_name (image, &name);
5079 mono_image_close (image);
5081 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5084 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5088 mono_image_close (image);
5092 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5093 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5095 MonoBoolean result = FALSE;
5096 MonoDeclSecurityEntry entry;
5098 /* SecurityAction.RequestMinimum */
5099 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5100 *minimum = entry.blob;
5101 *minLength = entry.size;
5104 /* SecurityAction.RequestOptional */
5105 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5106 *optional = entry.blob;
5107 *optLength = entry.size;
5110 /* SecurityAction.RequestRefuse */
5111 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5112 *refused = entry.blob;
5113 *refLength = entry.size;
5121 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5125 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5127 guint32 attrs, visibility;
5129 /* we start the count from 1 because we skip the special type <Module> */
5132 for (i = 1; i < tdef->rows; ++i) {
5133 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5134 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5135 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5139 count = tdef->rows - 1;
5141 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5142 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5144 for (i = 1; i < tdef->rows; ++i) {
5145 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5146 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5147 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5148 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5150 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5152 MonoLoaderError *error;
5155 error = mono_loader_get_last_error ();
5156 g_assert (error != NULL);
5158 ex = mono_loader_error_prepare_exception (error);
5159 mono_array_setref (*exceptions, count, ex);
5161 if (mono_loader_get_last_error ())
5162 mono_loader_clear_error ();
5171 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5173 MonoArray *res = NULL;
5174 MonoArray *exceptions = NULL;
5175 MonoImage *image = NULL;
5176 MonoTableInfo *table = NULL;
5179 int i, len, ex_count;
5181 MONO_ARCH_SAVE_REGS;
5183 domain = mono_object_domain (assembly);
5185 g_assert (!assembly->assembly->dynamic);
5186 image = assembly->assembly->image;
5187 table = &image->tables [MONO_TABLE_FILE];
5188 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5190 /* Append data from all modules in the assembly */
5191 for (i = 0; i < table->rows; ++i) {
5192 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5193 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5196 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5197 /* Append the new types to the end of the array */
5198 if (mono_array_length (res2) > 0) {
5200 MonoArray *res3, *ex3;
5202 len1 = mono_array_length (res);
5203 len2 = mono_array_length (res2);
5205 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5206 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5207 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5210 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5211 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5212 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5219 /* the ReflectionTypeLoadException must have all the types (Types property),
5220 * NULL replacing types which throws an exception. The LoaderException must
5221 * contain all exceptions for NULL items.
5224 len = mono_array_length (res);
5227 for (i = 0; i < len; i++) {
5228 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5232 klass = mono_type_get_class (t->type);
5233 if ((klass != NULL) && klass->exception_type) {
5234 /* keep the class in the list */
5235 list = g_list_append (list, klass);
5236 /* and replace Type with NULL */
5237 mono_array_setref (res, i, NULL);
5244 if (list || ex_count) {
5246 MonoException *exc = NULL;
5247 MonoArray *exl = NULL;
5248 int j, length = g_list_length (list) + ex_count;
5250 mono_loader_clear_error ();
5252 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5253 /* Types for which mono_class_get () succeeded */
5254 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5255 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5256 mono_array_setref (exl, i, exc);
5258 /* Types for which it don't */
5259 for (j = 0; j < mono_array_length (exceptions); ++j) {
5260 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5262 g_assert (i < length);
5263 mono_array_setref (exl, i, exc);
5270 exc = mono_get_exception_reflection_type_load (res, exl);
5271 mono_loader_clear_error ();
5272 mono_raise_exception (exc);
5279 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5281 MonoAssemblyName aname;
5282 MonoDomain *domain = mono_object_domain (name);
5284 gboolean is_version_defined;
5285 gboolean is_token_defined;
5287 aname.public_key = NULL;
5288 val = mono_string_to_utf8 (assname);
5289 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5290 g_free ((guint8*) aname.public_key);
5295 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5296 FALSE, is_token_defined);
5298 mono_assembly_name_free (&aname);
5299 g_free ((guint8*) aname.public_key);
5305 static MonoReflectionType*
5306 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5308 MonoDomain *domain = mono_object_domain (module);
5311 MONO_ARCH_SAVE_REGS;
5313 g_assert (module->image);
5315 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5316 /* These images do not have a global type */
5319 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5320 return mono_type_get_object (domain, &klass->byval_arg);
5324 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5326 /*if (module->image)
5327 mono_image_close (module->image);*/
5331 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5333 MonoDomain *domain = mono_object_domain (module);
5335 MONO_ARCH_SAVE_REGS;
5337 g_assert (module->image);
5338 return mono_string_new (domain, module->image->guid);
5342 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5345 if (module->image && module->image->is_module_handle)
5346 return module->image->raw_data;
5349 return (gpointer) (-1);
5353 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5355 if (image->dynamic) {
5356 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5357 *pe_kind = dyn->pe_kind;
5358 *machine = dyn->machine;
5361 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5362 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5367 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5369 return (image->md_version_major << 16) | (image->md_version_minor);
5373 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5375 MonoArray *exceptions;
5378 MONO_ARCH_SAVE_REGS;
5381 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5383 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5384 for (i = 0; i < mono_array_length (exceptions); ++i) {
5385 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5387 mono_raise_exception (ex);
5394 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5396 guint32 cols [MONO_MEMBERREF_SIZE];
5398 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5399 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5400 mono_metadata_decode_blob_size (sig, &sig);
5401 return (*sig != 0x6);
5405 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5408 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5409 mono_array_addr (type_args, MonoType*, 0));
5411 context->class_inst = NULL;
5413 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5414 mono_array_addr (method_args, MonoType*, 0));
5416 context->method_inst = NULL;
5420 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5423 int table = mono_metadata_token_table (token);
5424 int index = mono_metadata_token_index (token);
5425 MonoGenericContext context;
5427 *error = ResolveTokenError_Other;
5429 /* Validate token */
5430 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5431 (table != MONO_TABLE_TYPESPEC)) {
5432 *error = ResolveTokenError_BadTable;
5436 if (image->dynamic) {
5437 if (type_args || method_args)
5438 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5439 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5442 return &klass->byval_arg;
5445 if ((index <= 0) || (index > image->tables [table].rows)) {
5446 *error = ResolveTokenError_OutOfRange;
5450 init_generic_context_from_args (&context, type_args, method_args);
5451 klass = mono_class_get_full (image, token, &context);
5453 if (mono_loader_get_last_error ())
5454 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5457 return &klass->byval_arg;
5463 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5465 int table = mono_metadata_token_table (token);
5466 int index = mono_metadata_token_index (token);
5467 MonoGenericContext context;
5470 *error = ResolveTokenError_Other;
5472 /* Validate token */
5473 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5474 (table != MONO_TABLE_MEMBERREF)) {
5475 *error = ResolveTokenError_BadTable;
5479 if (image->dynamic) {
5480 if (type_args || method_args)
5481 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5482 /* FIXME: validate memberref token type */
5483 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5486 if ((index <= 0) || (index > image->tables [table].rows)) {
5487 *error = ResolveTokenError_OutOfRange;
5490 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5491 *error = ResolveTokenError_BadTable;
5495 init_generic_context_from_args (&context, type_args, method_args);
5496 method = mono_get_method_full (image, token, NULL, &context);
5498 if (mono_loader_get_last_error ())
5499 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5505 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5507 int index = mono_metadata_token_index (token);
5509 *error = ResolveTokenError_Other;
5511 /* Validate token */
5512 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5513 *error = ResolveTokenError_BadTable;
5518 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5520 if ((index <= 0) || (index >= image->heap_us.size)) {
5521 *error = ResolveTokenError_OutOfRange;
5525 /* FIXME: What to do if the index points into the middle of a string ? */
5527 return mono_ldstr (mono_domain_get (), image, index);
5530 static MonoClassField*
5531 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5534 int table = mono_metadata_token_table (token);
5535 int index = mono_metadata_token_index (token);
5536 MonoGenericContext context;
5537 MonoClassField *field;
5539 *error = ResolveTokenError_Other;
5541 /* Validate token */
5542 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5543 *error = ResolveTokenError_BadTable;
5547 if (image->dynamic) {
5548 if (type_args || method_args)
5549 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5550 /* FIXME: validate memberref token type */
5551 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5554 if ((index <= 0) || (index > image->tables [table].rows)) {
5555 *error = ResolveTokenError_OutOfRange;
5558 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5559 *error = ResolveTokenError_BadTable;
5563 init_generic_context_from_args (&context, type_args, method_args);
5564 field = mono_field_from_token (image, token, &klass, &context);
5566 if (mono_loader_get_last_error ())
5567 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5574 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5576 int table = mono_metadata_token_table (token);
5578 *error = ResolveTokenError_Other;
5581 case MONO_TABLE_TYPEDEF:
5582 case MONO_TABLE_TYPEREF:
5583 case MONO_TABLE_TYPESPEC: {
5584 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5586 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5590 case MONO_TABLE_METHOD:
5591 case MONO_TABLE_METHODSPEC: {
5592 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5594 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5598 case MONO_TABLE_FIELD: {
5599 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5601 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5605 case MONO_TABLE_MEMBERREF:
5606 if (mono_metadata_memberref_is_method (image, token)) {
5607 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5609 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5614 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5616 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5623 *error = ResolveTokenError_BadTable;
5630 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5632 int table = mono_metadata_token_table (token);
5633 int idx = mono_metadata_token_index (token);
5634 MonoTableInfo *tables = image->tables;
5639 *error = ResolveTokenError_OutOfRange;
5641 /* FIXME: Support other tables ? */
5642 if (table != MONO_TABLE_STANDALONESIG)
5648 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5651 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5653 ptr = mono_metadata_blob_heap (image, sig);
5654 len = mono_metadata_decode_blob_size (ptr, &ptr);
5656 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5657 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5661 static MonoReflectionType*
5662 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5665 int isbyref = 0, rank;
5666 char *str = mono_string_to_utf8 (smodifiers);
5669 MONO_ARCH_SAVE_REGS;
5671 klass = mono_class_from_mono_type (tb->type.type);
5673 /* logic taken from mono_reflection_parse_type(): keep in sync */
5677 if (isbyref) { /* only one level allowed by the spec */
5684 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5687 klass = mono_ptr_class_get (&klass->byval_arg);
5688 mono_class_init (klass);
5699 else if (*p != '*') { /* '*' means unknown lower bound */
5710 klass = mono_array_class_get (klass, rank);
5711 mono_class_init (klass);
5718 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5722 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5727 MONO_ARCH_SAVE_REGS;
5730 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5736 check_for_invalid_type (MonoClass *klass)
5740 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5743 name = mono_type_get_full_name (klass);
5744 str = mono_string_new (mono_domain_get (), name);
5746 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5749 static MonoReflectionType *
5750 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5752 MonoClass *klass, *aklass;
5754 MONO_ARCH_SAVE_REGS;
5756 klass = mono_class_from_mono_type (type->type);
5757 mono_class_init_or_throw (klass);
5758 check_for_invalid_type (klass);
5760 if (rank == 0) //single dimentional array
5761 aklass = mono_array_class_get (klass, 1);
5763 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5765 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5768 static MonoReflectionType *
5769 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5773 MONO_ARCH_SAVE_REGS;
5775 klass = mono_class_from_mono_type (type->type);
5776 mono_class_init_or_throw (klass);
5777 check_for_invalid_type (klass);
5779 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5782 static MonoReflectionType *
5783 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5785 MonoClass *klass, *pklass;
5787 klass = mono_class_from_mono_type (type->type);
5788 mono_class_init_or_throw (klass);
5789 check_for_invalid_type (klass);
5791 pklass = mono_ptr_class_get (type->type);
5793 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5797 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5798 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5800 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5801 MonoObject *delegate;
5803 MonoMethod *method = info->method;
5805 MONO_ARCH_SAVE_REGS;
5807 mono_class_init_or_throw (delegate_class);
5809 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5811 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5812 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5816 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5818 if (method->dynamic) {
5819 /* Creating a trampoline would leak memory */
5820 func = mono_compile_method (method);
5822 func = mono_create_ftnptr (mono_domain_get (),
5823 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5826 mono_delegate_ctor_with_method (delegate, target, func, method);
5832 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5834 /* Reset the invoke impl to the default one */
5835 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5839 * Magic number to convert a time which is relative to
5840 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5842 #define EPOCH_ADJUST ((guint64)62135596800LL)
5845 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5847 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5850 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5852 convert_to_absolute_date(SYSTEMTIME *date)
5854 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5855 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5856 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5857 /* from the calendar FAQ */
5858 int a = (14 - date->wMonth) / 12;
5859 int y = date->wYear - a;
5860 int m = date->wMonth + 12 * a - 2;
5861 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5863 /* d is now the day of the week for the first of the month (0 == Sunday) */
5865 int day_of_week = date->wDayOfWeek;
5867 /* set day_in_month to the first day in the month which falls on day_of_week */
5868 int day_in_month = 1 + (day_of_week - d);
5869 if (day_in_month <= 0)
5872 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5873 date->wDay = day_in_month + (date->wDay - 1) * 7;
5874 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5881 * Return's the offset from GMT of a local time.
5883 * tm is a local time
5884 * t is the same local time as seconds.
5887 gmt_offset(struct tm *tm, time_t t)
5889 #if defined (HAVE_TM_GMTOFF)
5890 return tm->tm_gmtoff;
5895 g.tm_isdst = tm->tm_isdst;
5897 return (int)difftime(t, t2);
5902 * This is heavily based on zdump.c from glibc 2.2.
5904 * * data[0]: start of daylight saving time (in DateTime ticks).
5905 * * data[1]: end of daylight saving time (in DateTime ticks).
5906 * * data[2]: utcoffset (in TimeSpan ticks).
5907 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5908 * * name[0]: name of this timezone when not daylight saving.
5909 * * name[1]: name of this timezone when daylight saving.
5911 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5912 * the class library allows years between 1 and 9999.
5914 * Returns true on success and zero on failure.
5917 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5920 MonoDomain *domain = mono_domain_get ();
5921 struct tm start, tt;
5925 int is_daylight = 0, day;
5928 MONO_ARCH_SAVE_REGS;
5930 MONO_CHECK_ARG_NULL (data);
5931 MONO_CHECK_ARG_NULL (names);
5933 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5934 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5937 * no info is better than crashing: we'll need our own tz data
5938 * to make this work properly, anyway. The range is probably
5939 * reduced to 1970 .. 2037 because that is what mktime is
5940 * guaranteed to support (we get into an infinite loop
5944 memset (&start, 0, sizeof (start));
5947 start.tm_year = year-1900;
5949 t = mktime (&start);
5951 if ((year < 1970) || (year > 2037) || (t == -1)) {
5953 tt = *localtime (&t);
5954 strftime (tzone, sizeof (tzone), "%Z", &tt);
5955 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5956 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5960 gmtoff = gmt_offset (&start, t);
5962 /* For each day of the year, calculate the tm_gmtoff. */
5963 for (day = 0; day < 365; day++) {
5966 tt = *localtime (&t);
5968 /* Daylight saving starts or ends here. */
5969 if (gmt_offset (&tt, t) != gmtoff) {
5973 /* Try to find the exact hour when daylight saving starts/ends. */
5977 tt1 = *localtime (&t1);
5978 } while (gmt_offset (&tt1, t1) != gmtoff);
5980 /* Try to find the exact minute when daylight saving starts/ends. */
5983 tt1 = *localtime (&t1);
5984 } while (gmt_offset (&tt1, t1) == gmtoff);
5986 strftime (tzone, sizeof (tzone), "%Z", &tt);
5988 /* Write data, if we're already in daylight saving, we're done. */
5990 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5991 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5994 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5995 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5999 /* This is only set once when we enter daylight saving. */
6000 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6001 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6003 gmtoff = gmt_offset (&tt, t);
6008 strftime (tzone, sizeof (tzone), "%Z", &tt);
6009 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6010 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6011 mono_array_set ((*data), gint64, 0, 0);
6012 mono_array_set ((*data), gint64, 1, 0);
6013 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6014 mono_array_set ((*data), gint64, 3, 0);
6019 MonoDomain *domain = mono_domain_get ();
6020 TIME_ZONE_INFORMATION tz_info;
6025 tz_id = GetTimeZoneInformation (&tz_info);
6026 if (tz_id == TIME_ZONE_ID_INVALID)
6029 MONO_CHECK_ARG_NULL (data);
6030 MONO_CHECK_ARG_NULL (names);
6032 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6033 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6035 for (i = 0; i < 32; ++i)
6036 if (!tz_info.DaylightName [i])
6038 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6039 for (i = 0; i < 32; ++i)
6040 if (!tz_info.StandardName [i])
6042 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6044 if ((year <= 1601) || (year > 30827)) {
6046 * According to MSDN, the MS time functions can't handle dates outside
6052 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6053 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6054 tz_info.StandardDate.wYear = year;
6055 convert_to_absolute_date(&tz_info.StandardDate);
6056 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6061 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6062 tz_info.DaylightDate.wYear = year;
6063 convert_to_absolute_date(&tz_info.DaylightDate);
6064 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6069 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6071 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6072 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6079 ves_icall_System_Object_obj_address (MonoObject *this)
6081 MONO_ARCH_SAVE_REGS;
6088 static inline gint32
6089 mono_array_get_byte_length (MonoArray *array)
6095 klass = array->obj.vtable->klass;
6097 if (array->bounds == NULL)
6098 length = array->max_length;
6101 for (i = 0; i < klass->rank; ++ i)
6102 length *= array->bounds [i].length;
6105 switch (klass->element_class->byval_arg.type) {
6108 case MONO_TYPE_BOOLEAN:
6112 case MONO_TYPE_CHAR:
6120 return length * sizeof (gpointer);
6131 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6133 MONO_ARCH_SAVE_REGS;
6135 return mono_array_get_byte_length (array);
6139 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6141 MONO_ARCH_SAVE_REGS;
6143 return mono_array_get (array, gint8, idx);
6147 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6149 MONO_ARCH_SAVE_REGS;
6151 mono_array_set (array, gint8, idx, value);
6155 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6157 guint8 *src_buf, *dest_buf;
6159 MONO_ARCH_SAVE_REGS;
6161 /* watch out for integer overflow */
6162 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6165 src_buf = (guint8 *)src->vector + src_offset;
6166 dest_buf = (guint8 *)dest->vector + dest_offset;
6169 memcpy (dest_buf, src_buf, count);
6171 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6177 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6179 MonoDomain *domain = mono_object_domain (this);
6181 MonoRealProxy *rp = ((MonoRealProxy *)this);
6182 MonoTransparentProxy *tp;
6186 MONO_ARCH_SAVE_REGS;
6188 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6189 tp = (MonoTransparentProxy*) res;
6191 MONO_OBJECT_SETREF (tp, rp, rp);
6192 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6193 klass = mono_class_from_mono_type (type);
6195 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6196 tp->remote_class = mono_remote_class (domain, class_name, klass);
6198 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6202 static MonoReflectionType *
6203 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6205 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6208 /* System.Environment */
6211 ves_icall_System_Environment_get_UserName (void)
6213 MONO_ARCH_SAVE_REGS;
6215 /* using glib is more portable */
6216 return mono_string_new (mono_domain_get (), g_get_user_name ());
6221 ves_icall_System_Environment_get_MachineName (void)
6223 #if defined (HOST_WIN32)
6228 len = MAX_COMPUTERNAME_LENGTH + 1;
6229 buf = g_new (gunichar2, len);
6232 if (GetComputerName (buf, (PDWORD) &len))
6233 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6237 #elif !defined(DISABLE_SOCKETS)
6241 if (gethostname (buf, sizeof (buf)) == 0)
6242 result = mono_string_new (mono_domain_get (), buf);
6248 return mono_string_new (mono_domain_get (), "mono");
6253 ves_icall_System_Environment_get_Platform (void)
6255 #if defined (TARGET_WIN32)
6258 #elif defined(__MACH__)
6261 // For compatibility with our client code, this will be 4 for a while.
6262 // We will eventually move to 6 to match .NET, but it requires all client
6263 // code to be updated and the documentation everywhere to be updated
6274 ves_icall_System_Environment_get_NewLine (void)
6276 MONO_ARCH_SAVE_REGS;
6278 #if defined (HOST_WIN32)
6279 return mono_string_new (mono_domain_get (), "\r\n");
6281 return mono_string_new (mono_domain_get (), "\n");
6286 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6291 MONO_ARCH_SAVE_REGS;
6296 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6297 value = g_getenv (utf8_name);
6304 return mono_string_new (mono_domain_get (), value);
6308 * There is no standard way to get at environ.
6311 #ifndef __MINGW32_VERSION
6312 #if defined(__APPLE__) && !defined (__arm__)
6313 /* Apple defines this in crt_externs.h but doesn't provide that header for
6314 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6315 * in fact exist on all implementations (so far)
6317 gchar ***_NSGetEnviron(void);
6318 #define environ (*_NSGetEnviron())
6327 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6338 env_strings = GetEnvironmentStrings();
6341 env_string = env_strings;
6342 while (*env_string != '\0') {
6343 /* weird case that MS seems to skip */
6344 if (*env_string != '=')
6346 while (*env_string != '\0')
6352 domain = mono_domain_get ();
6353 names = mono_array_new (domain, mono_defaults.string_class, n);
6357 env_string = env_strings;
6358 while (*env_string != '\0') {
6359 /* weird case that MS seems to skip */
6360 if (*env_string != '=') {
6361 equal_str = wcschr(env_string, '=');
6362 g_assert(equal_str);
6363 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6364 mono_array_setref (names, n, str);
6367 while (*env_string != '\0')
6372 FreeEnvironmentStrings (env_strings);
6384 MONO_ARCH_SAVE_REGS;
6387 for (e = environ; *e != 0; ++ e)
6390 domain = mono_domain_get ();
6391 names = mono_array_new (domain, mono_defaults.string_class, n);
6394 for (e = environ; *e != 0; ++ e) {
6395 parts = g_strsplit (*e, "=", 2);
6397 str = mono_string_new (domain, *parts);
6398 mono_array_setref (names, n, str);
6411 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6413 #if !GLIB_CHECK_VERSION(2,4,0)
6414 #define g_setenv(a,b,c) setenv(a,b,c)
6415 #define g_unsetenv(a) unsetenv(a)
6419 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6424 gunichar2 *utf16_name, *utf16_value;
6426 gchar *utf8_name, *utf8_value;
6429 MONO_ARCH_SAVE_REGS;
6432 utf16_name = mono_string_to_utf16 (name);
6433 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6434 SetEnvironmentVariable (utf16_name, NULL);
6435 g_free (utf16_name);
6439 utf16_value = mono_string_to_utf16 (value);
6441 SetEnvironmentVariable (utf16_name, utf16_value);
6443 g_free (utf16_name);
6444 g_free (utf16_value);
6446 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6448 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6449 g_unsetenv (utf8_name);
6454 utf8_value = mono_string_to_utf8_checked (value, &error);
6455 if (!mono_error_ok (&error)) {
6457 mono_error_raise_exception (&error);
6459 g_setenv (utf8_name, utf8_value, TRUE);
6462 g_free (utf8_value);
6467 ves_icall_System_Environment_Exit (int result)
6469 MONO_ARCH_SAVE_REGS;
6471 mono_threads_set_shutting_down ();
6473 mono_runtime_set_shutting_down ();
6475 /* This will kill the tp threads which cannot be suspended */
6476 mono_thread_pool_cleanup ();
6478 /* Suspend all managed threads since the runtime is going away */
6479 mono_thread_suspend_all_other_threads ();
6481 mono_runtime_quit ();
6483 /* we may need to do some cleanup here... */
6488 ves_icall_System_Environment_GetGacPath (void)
6490 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6494 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6496 #if defined (HOST_WIN32)
6497 #ifndef CSIDL_FLAG_CREATE
6498 #define CSIDL_FLAG_CREATE 0x8000
6501 WCHAR path [MAX_PATH];
6502 /* Create directory if no existing */
6503 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6507 return mono_string_new_utf16 (mono_domain_get (), path, len);
6510 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6512 return mono_string_new (mono_domain_get (), "");
6516 ves_icall_System_Environment_GetLogicalDrives (void)
6518 gunichar2 buf [128], *ptr, *dname;
6520 guint initial_size = 127, size = 128;
6523 MonoString *drivestr;
6524 MonoDomain *domain = mono_domain_get ();
6527 MONO_ARCH_SAVE_REGS;
6532 while (size > initial_size) {
6533 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6534 if (size > initial_size) {
6537 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6538 initial_size = size;
6552 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6557 while (*u16) { u16++; len ++; }
6558 drivestr = mono_string_new_utf16 (domain, dname, len);
6559 mono_array_setref (result, ndrives++, drivestr);
6570 ves_icall_System_Environment_InternalGetHome (void)
6572 MONO_ARCH_SAVE_REGS;
6574 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6577 static const char *encodings [] = {
6579 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6580 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6581 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6583 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6584 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6585 "x_unicode_2_0_utf_7",
6587 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6588 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6590 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6593 "unicodefffe", "utf_16be",
6600 * Returns the internal codepage, if the value of "int_code_page" is
6601 * 1 at entry, and we can not compute a suitable code page number,
6602 * returns the code page as a string
6605 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6610 char *codepage = NULL;
6612 int want_name = *int_code_page;
6615 *int_code_page = -1;
6616 MONO_ARCH_SAVE_REGS;
6618 g_get_charset (&cset);
6619 c = codepage = strdup (cset);
6620 for (c = codepage; *c; c++){
6621 if (isascii (*c) && isalpha (*c))
6626 /* g_print ("charset: %s\n", cset); */
6628 /* handle some common aliases */
6631 for (i = 0; p != 0; ){
6632 if ((gssize) p < 7){
6634 p = encodings [++i];
6637 if (strcmp (p, codepage) == 0){
6638 *int_code_page = code;
6641 p = encodings [++i];
6644 if (strstr (codepage, "utf_8") != NULL)
6645 *int_code_page |= 0x10000000;
6648 if (want_name && *int_code_page == -1)
6649 return mono_string_new (mono_domain_get (), cset);
6655 ves_icall_System_Environment_get_HasShutdownStarted (void)
6657 if (mono_runtime_is_shutting_down ())
6660 if (mono_domain_is_unloading (mono_domain_get ()))
6667 ves_icall_System_Environment_BroadcastSettingChange (void)
6670 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6675 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6676 MonoReflectionMethod *method,
6677 MonoArray *out_args)
6679 MONO_ARCH_SAVE_REGS;
6681 mono_message_init (mono_object_domain (this), this, method, out_args);
6685 ves_icall_IsTransparentProxy (MonoObject *proxy)
6687 MONO_ARCH_SAVE_REGS;
6692 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6698 static MonoReflectionMethod *
6699 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6700 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6704 MonoMethod **vtable;
6705 MonoMethod *res = NULL;
6707 MONO_CHECK_ARG_NULL (rtype);
6708 MONO_CHECK_ARG_NULL (rmethod);
6710 method = rmethod->method;
6711 klass = mono_class_from_mono_type (rtype->type);
6712 mono_class_init_or_throw (klass);
6714 if (MONO_CLASS_IS_INTERFACE (klass))
6717 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6720 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6721 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6727 mono_class_setup_vtable (klass);
6728 vtable = klass->vtable;
6730 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6731 gboolean variance_used = FALSE;
6732 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6733 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6735 res = vtable [offs + method->slot];
6737 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6740 if (method->slot != -1)
6741 res = vtable [method->slot];
6747 return mono_method_get_object (mono_domain_get (), res, NULL);
6751 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6756 MONO_ARCH_SAVE_REGS;
6758 klass = mono_class_from_mono_type (type->type);
6759 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6761 if (enable) vtable->remote = 1;
6762 else vtable->remote = 0;
6766 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6771 MONO_ARCH_SAVE_REGS;
6773 domain = mono_object_domain (type);
6774 klass = mono_class_from_mono_type (type->type);
6775 mono_class_init_or_throw (klass);
6777 if (klass->rank >= 1) {
6778 g_assert (klass->rank == 1);
6779 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6781 /* Bypass remoting object creation check */
6782 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6787 ves_icall_System_IO_get_temp_path (void)
6789 MONO_ARCH_SAVE_REGS;
6791 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6794 #ifndef PLATFORM_NO_DRIVEINFO
6796 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6797 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6801 ULARGE_INTEGER wapi_free_bytes_avail;
6802 ULARGE_INTEGER wapi_total_number_of_bytes;
6803 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6805 MONO_ARCH_SAVE_REGS;
6807 *error = ERROR_SUCCESS;
6808 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6809 &wapi_total_number_of_free_bytes);
6812 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6813 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6814 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6816 *free_bytes_avail = 0;
6817 *total_number_of_bytes = 0;
6818 *total_number_of_free_bytes = 0;
6819 *error = GetLastError ();
6826 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6828 MONO_ARCH_SAVE_REGS;
6830 return GetDriveType (mono_string_chars (root_path_name));
6835 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6837 MONO_ARCH_SAVE_REGS;
6839 return mono_compile_method (method);
6843 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6848 MONO_ARCH_SAVE_REGS;
6850 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6852 #if defined (HOST_WIN32)
6853 /* Avoid mixing '/' and '\\' */
6856 for (i = strlen (path) - 1; i >= 0; i--)
6857 if (path [i] == '/')
6861 mcpath = mono_string_new (mono_domain_get (), path);
6868 get_bundled_app_config (void)
6870 const gchar *app_config;
6877 MONO_ARCH_SAVE_REGS;
6879 domain = mono_domain_get ();
6880 file = domain->setup->configuration_file;
6884 // Retrieve config file and remove the extension
6885 config_file = mono_string_to_utf8 (file);
6886 len = strlen (config_file) - strlen (".config");
6887 module = g_malloc0 (len + 1);
6888 memcpy (module, config_file, len);
6889 // Get the config file from the module name
6890 app_config = mono_config_string_for_assembly_file (module);
6893 g_free (config_file);
6898 return mono_string_new (mono_domain_get (), app_config);
6902 get_bundled_machine_config (void)
6904 const gchar *machine_config;
6906 MONO_ARCH_SAVE_REGS;
6908 machine_config = mono_get_machine_config ();
6910 if (!machine_config)
6913 return mono_string_new (mono_domain_get (), machine_config);
6917 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6922 MONO_ARCH_SAVE_REGS;
6924 path = g_path_get_dirname (mono_get_config_dir ());
6926 #if defined (HOST_WIN32)
6927 /* Avoid mixing '/' and '\\' */
6930 for (i = strlen (path) - 1; i >= 0; i--)
6931 if (path [i] == '/')
6935 ipath = mono_string_new (mono_domain_get (), path);
6942 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6944 MonoPEResourceDataEntry *entry;
6947 MONO_ARCH_SAVE_REGS;
6949 if (!assembly || !result || !size)
6954 image = assembly->assembly->image;
6955 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6959 *result = mono_image_rva_map (image, entry->rde_data_offset);
6964 *size = entry->rde_size;
6970 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6972 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6976 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6978 #if defined (HOST_WIN32)
6979 OutputDebugString (mono_string_chars (message));
6981 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6985 /* Only used for value types */
6987 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6992 MONO_ARCH_SAVE_REGS;
6994 domain = mono_object_domain (type);
6995 klass = mono_class_from_mono_type (type->type);
6996 mono_class_init_or_throw (klass);
6998 if (mono_class_is_nullable (klass))
6999 /* No arguments -> null */
7002 return mono_object_new (domain, klass);
7005 static MonoReflectionMethod *
7006 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7008 MonoClass *klass, *parent;
7009 MonoMethod *method = m->method;
7010 MonoMethod *result = NULL;
7012 MONO_ARCH_SAVE_REGS;
7014 if (method->klass == NULL)
7017 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7018 MONO_CLASS_IS_INTERFACE (method->klass) ||
7019 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7022 klass = method->klass;
7023 if (klass->generic_class)
7024 klass = klass->generic_class->container_class;
7027 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7028 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7029 mono_class_setup_vtable (parent);
7030 if (parent->vtable_size <= method->slot)
7035 klass = klass->parent;
7040 if (klass == method->klass)
7043 /*This is possible if definition == FALSE.
7044 * Do it here to be really sure we don't read invalid memory.
7046 if (method->slot >= klass->vtable_size)
7049 result = klass->vtable [method->slot];
7050 if (result == NULL) {
7051 /* It is an abstract method */
7052 gpointer iter = NULL;
7053 while ((result = mono_class_get_methods (klass, &iter)))
7054 if (result->slot == method->slot)
7061 return mono_method_get_object (mono_domain_get (), result, NULL);
7065 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7067 MonoMethod *method = m->method;
7069 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7074 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7076 MONO_ARCH_SAVE_REGS;
7078 iter->sig = *(MonoMethodSignature**)argsp;
7080 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7081 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7084 /* FIXME: it's not documented what start is exactly... */
7088 iter->args = argsp + sizeof (gpointer);
7090 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7092 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7096 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7098 guint32 i, arg_size;
7101 MONO_ARCH_SAVE_REGS;
7103 i = iter->sig->sentinelpos + iter->next_arg;
7105 g_assert (i < iter->sig->param_count);
7107 res.type = iter->sig->params [i];
7108 res.klass = mono_class_from_mono_type (res.type);
7109 res.value = iter->args;
7110 arg_size = mono_type_stack_size (res.type, &align);
7111 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7112 if (arg_size <= sizeof (gpointer)) {
7114 int padding = arg_size - mono_type_size (res.type, &dummy);
7115 res.value = (guint8*)res.value + padding;
7118 iter->args = (char*)iter->args + arg_size;
7121 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7127 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7129 guint32 i, arg_size;
7132 MONO_ARCH_SAVE_REGS;
7134 i = iter->sig->sentinelpos + iter->next_arg;
7136 g_assert (i < iter->sig->param_count);
7138 while (i < iter->sig->param_count) {
7139 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7141 res.type = iter->sig->params [i];
7142 res.klass = mono_class_from_mono_type (res.type);
7143 /* FIXME: endianess issue... */
7144 res.value = iter->args;
7145 arg_size = mono_type_stack_size (res.type, &align);
7146 iter->args = (char*)iter->args + arg_size;
7148 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7151 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7160 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7163 MONO_ARCH_SAVE_REGS;
7165 i = iter->sig->sentinelpos + iter->next_arg;
7167 g_assert (i < iter->sig->param_count);
7169 return iter->sig->params [i];
7173 mono_TypedReference_ToObject (MonoTypedRef tref)
7175 MONO_ARCH_SAVE_REGS;
7177 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7178 MonoObject** objp = tref.value;
7182 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7186 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7188 MONO_ARCH_SAVE_REGS;
7190 if (MONO_TYPE_IS_REFERENCE (type)) {
7191 MonoObject** objp = value;
7195 return mono_value_box (mono_domain_get (), klass, value);
7199 prelink_method (MonoMethod *method)
7201 const char *exc_class, *exc_arg;
7202 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7204 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7206 mono_raise_exception(
7207 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7209 /* create the wrapper, too? */
7213 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7215 MONO_ARCH_SAVE_REGS;
7216 prelink_method (method->method);
7220 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7222 MonoClass *klass = mono_class_from_mono_type (type->type);
7224 gpointer iter = NULL;
7225 MONO_ARCH_SAVE_REGS;
7227 mono_class_init_or_throw (klass);
7229 while ((m = mono_class_get_methods (klass, &iter)))
7233 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7235 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7236 gint32 const **exponents,
7237 gunichar2 const **digitLowerTable,
7238 gunichar2 const **digitUpperTable,
7239 gint64 const **tenPowersList,
7240 gint32 const **decHexDigits)
7242 *mantissas = Formatter_MantissaBitsTable;
7243 *exponents = Formatter_TensExponentTable;
7244 *digitLowerTable = Formatter_DigitLowerTable;
7245 *digitUpperTable = Formatter_DigitUpperTable;
7246 *tenPowersList = Formatter_TenPowersList;
7247 *decHexDigits = Formatter_DecHexDigits;
7250 /* These parameters are "readonly" in corlib/System/Char.cs */
7252 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7253 guint8 const **numeric_data,
7254 gdouble const **numeric_data_values,
7255 guint16 const **to_lower_data_low,
7256 guint16 const **to_lower_data_high,
7257 guint16 const **to_upper_data_low,
7258 guint16 const **to_upper_data_high)
7260 *category_data = CategoryData;
7261 *numeric_data = NumericData;
7262 *numeric_data_values = NumericDataValues;
7263 *to_lower_data_low = ToLowerDataLow;
7264 *to_lower_data_high = ToLowerDataHigh;
7265 *to_upper_data_low = ToUpperDataLow;
7266 *to_upper_data_high = ToUpperDataHigh;
7270 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7272 return method->method->token;
7276 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7277 * and avoid useless allocations.
7280 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7284 for (i = 0; i < type->num_mods; ++i) {
7285 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7290 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7292 for (i = 0; i < type->num_mods; ++i) {
7293 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7294 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7295 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7303 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7305 MonoType *type = param->ClassImpl->type;
7306 MonoClass *member_class = mono_object_class (param->MemberImpl);
7307 MonoMethod *method = NULL;
7310 MonoMethodSignature *sig;
7312 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7313 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7314 method = rmethod->method;
7315 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7316 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7317 if (!(method = prop->property->get))
7318 method = prop->property->set;
7321 char *type_name = mono_type_get_full_name (member_class);
7322 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7323 MonoException *ex = mono_get_exception_not_supported (msg);
7326 mono_raise_exception (ex);
7329 image = method->klass->image;
7330 pos = param->PositionImpl;
7331 sig = mono_method_signature (method);
7335 type = sig->params [pos];
7337 return type_array_from_modifiers (image, type, optional);
7341 get_property_type (MonoProperty *prop)
7343 MonoMethodSignature *sig;
7345 sig = mono_method_signature (prop->get);
7347 } else if (prop->set) {
7348 sig = mono_method_signature (prop->set);
7349 return sig->params [sig->param_count - 1];
7355 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7357 MonoType *type = get_property_type (property->property);
7358 MonoImage *image = property->klass->image;
7362 return type_array_from_modifiers (image, type, optional);
7366 *Construct a MonoType suited to be used to decode a constant blob object.
7368 * @type is the target type which will be constructed
7369 * @blob_type is the blob type, for example, that comes from the constant table
7370 * @real_type is the expected constructed type.
7373 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7375 type->type = blob_type;
7376 type->data.klass = NULL;
7377 if (blob_type == MONO_TYPE_CLASS)
7378 type->data.klass = mono_defaults.object_class;
7379 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7380 /* For enums, we need to use the base type */
7381 type->type = MONO_TYPE_VALUETYPE;
7382 type->data.klass = mono_class_from_mono_type (real_type);
7384 type->data.klass = mono_class_from_mono_type (real_type);
7388 property_info_get_default_value (MonoReflectionProperty *property)
7391 MonoProperty *prop = property->property;
7392 MonoType *type = get_property_type (prop);
7393 MonoDomain *domain = mono_object_domain (property);
7394 MonoTypeEnum def_type;
7395 const char *def_value;
7398 mono_class_init (prop->parent);
7400 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7401 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7403 def_value = mono_class_get_property_default_value (prop, &def_type);
7405 mono_type_from_blob_type (&blob_type, def_type, type);
7406 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7412 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7414 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7415 MonoCustomAttrInfo *cinfo;
7418 mono_class_init_or_throw (attr_class);
7420 cinfo = mono_reflection_get_custom_attrs_info (obj);
7423 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7425 mono_custom_attrs_free (cinfo);
7430 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7432 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7436 mono_class_init_or_throw (attr_class);
7438 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7440 if (mono_loader_get_last_error ()) {
7441 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7442 g_assert_not_reached ();
7451 ves_icall_Mono_Runtime_GetDisplayName (void)
7454 MonoString *display_name;
7456 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7457 display_name = mono_string_new (mono_domain_get (), info);
7459 return display_name;
7463 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7465 MonoString *message;
7469 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7470 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7473 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7475 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7483 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7484 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7485 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7486 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7487 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7488 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7489 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7490 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7494 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7499 gunichar2 last, prev_last, prev2_last;
7507 last = prev_last = 0, prev2_last = 0;
7508 for (i = 0; i < ilength; i++) {
7510 if (c >= sizeof (dbase64)) {
7511 exc = mono_exception_from_name_msg (mono_get_corlib (),
7512 "System", "FormatException",
7513 "Invalid character found.");
7514 mono_raise_exception (exc);
7515 } else if (isspace (c)) {
7518 prev2_last = prev_last;
7524 olength = ilength - ignored;
7526 if (allowWhitespaceOnly && olength == 0) {
7527 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7530 if ((olength & 3) != 0 || olength <= 0) {
7531 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7532 "FormatException", "Invalid length.");
7533 mono_raise_exception (exc);
7536 if (prev2_last == '=') {
7537 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7538 mono_raise_exception (exc);
7541 olength = (olength * 3) / 4;
7545 if (prev_last == '=')
7548 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7549 res_ptr = mono_array_addr (result, guchar, 0);
7550 for (i = 0; i < ilength; ) {
7553 for (k = 0; k < 4 && i < ilength;) {
7559 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7560 exc = mono_exception_from_name_msg (mono_get_corlib (),
7561 "System", "FormatException",
7562 "Invalid character found.");
7563 mono_raise_exception (exc);
7568 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7570 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7572 *res_ptr++ = (b [2] << 6) | b [3];
7574 while (i < ilength && isspace (start [i]))
7582 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7584 MONO_ARCH_SAVE_REGS;
7586 return base64_to_byte_array (mono_string_chars (str),
7587 mono_string_length (str), allowWhitespaceOnly);
7591 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7593 MONO_ARCH_SAVE_REGS;
7595 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7599 #define ICALL_TYPE(id,name,first)
7600 #define ICALL(id,name,func) Icall_ ## id,
7603 #include "metadata/icall-def.h"
7609 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7610 #define ICALL(id,name,func)
7612 #include "metadata/icall-def.h"
7618 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7619 #define ICALL(id,name,func)
7621 guint16 first_icall;
7624 static const IcallTypeDesc
7625 icall_type_descs [] = {
7626 #include "metadata/icall-def.h"
7630 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7633 #define ICALL_TYPE(id,name,first)
7636 #ifdef HAVE_ARRAY_ELEM_INIT
7637 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7638 #define MSGSTRFIELD1(line) str##line
7640 static const struct msgstrtn_t {
7641 #define ICALL(id,name,func)
7643 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7644 #include "metadata/icall-def.h"
7646 } icall_type_names_str = {
7647 #define ICALL_TYPE(id,name,first) (name),
7648 #include "metadata/icall-def.h"
7651 static const guint16 icall_type_names_idx [] = {
7652 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7653 #include "metadata/icall-def.h"
7656 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7658 static const struct msgstr_t {
7660 #define ICALL_TYPE(id,name,first)
7661 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7662 #include "metadata/icall-def.h"
7664 } icall_names_str = {
7665 #define ICALL(id,name,func) (name),
7666 #include "metadata/icall-def.h"
7669 static const guint16 icall_names_idx [] = {
7670 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7671 #include "metadata/icall-def.h"
7674 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7680 #define ICALL_TYPE(id,name,first) name,
7681 #define ICALL(id,name,func)
7682 static const char* const
7683 icall_type_names [] = {
7684 #include "metadata/icall-def.h"
7688 #define icall_type_name_get(id) (icall_type_names [(id)])
7692 #define ICALL_TYPE(id,name,first)
7693 #define ICALL(id,name,func) name,
7694 static const char* const
7696 #include "metadata/icall-def.h"
7699 #define icall_name_get(id) icall_names [(id)]
7701 #endif /* !HAVE_ARRAY_ELEM_INIT */
7705 #define ICALL_TYPE(id,name,first)
7706 #define ICALL(id,name,func) func,
7707 static const gconstpointer
7708 icall_functions [] = {
7709 #include "metadata/icall-def.h"
7713 static GHashTable *icall_hash = NULL;
7714 static GHashTable *jit_icall_hash_name = NULL;
7715 static GHashTable *jit_icall_hash_addr = NULL;
7718 mono_icall_init (void)
7722 /* check that tables are sorted: disable in release */
7725 const char *prev_class = NULL;
7726 const char *prev_method;
7728 for (i = 0; i < Icall_type_num; ++i) {
7729 const IcallTypeDesc *desc;
7732 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7733 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7734 prev_class = icall_type_name_get (i);
7735 desc = &icall_type_descs [i];
7736 num_icalls = icall_desc_num_icalls (desc);
7737 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7738 for (j = 0; j < num_icalls; ++j) {
7739 const char *methodn = icall_name_get (desc->first_icall + j);
7740 if (prev_method && strcmp (prev_method, methodn) >= 0)
7741 g_print ("method %s should come before method %s\n", methodn, prev_method);
7742 prev_method = methodn;
7747 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7751 mono_icall_cleanup (void)
7753 g_hash_table_destroy (icall_hash);
7754 g_hash_table_destroy (jit_icall_hash_name);
7755 g_hash_table_destroy (jit_icall_hash_addr);
7759 mono_add_internal_call (const char *name, gconstpointer method)
7761 mono_loader_lock ();
7763 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7765 mono_loader_unlock ();
7768 #ifdef HAVE_ARRAY_ELEM_INIT
7770 compare_method_imap (const void *key, const void *elem)
7772 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7773 return strcmp (key, method_name);
7777 find_method_icall (const IcallTypeDesc *imap, const char *name)
7779 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7782 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7786 compare_class_imap (const void *key, const void *elem)
7788 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7789 return strcmp (key, class_name);
7792 static const IcallTypeDesc*
7793 find_class_icalls (const char *name)
7795 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7798 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7803 compare_method_imap (const void *key, const void *elem)
7805 const char** method_name = (const char**)elem;
7806 return strcmp (key, *method_name);
7810 find_method_icall (const IcallTypeDesc *imap, const char *name)
7812 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7815 return (gpointer)icall_functions [(nameslot - icall_names)];
7819 compare_class_imap (const void *key, const void *elem)
7821 const char** class_name = (const char**)elem;
7822 return strcmp (key, *class_name);
7825 static const IcallTypeDesc*
7826 find_class_icalls (const char *name)
7828 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7831 return &icall_type_descs [nameslot - icall_type_names];
7837 * we should probably export this as an helper (handle nested types).
7838 * Returns the number of chars written in buf.
7841 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7843 int nspacelen, cnamelen;
7844 nspacelen = strlen (klass->name_space);
7845 cnamelen = strlen (klass->name);
7846 if (nspacelen + cnamelen + 2 > bufsize)
7849 memcpy (buf, klass->name_space, nspacelen);
7850 buf [nspacelen ++] = '.';
7852 memcpy (buf + nspacelen, klass->name, cnamelen);
7853 buf [nspacelen + cnamelen] = 0;
7854 return nspacelen + cnamelen;
7858 mono_lookup_internal_call (MonoMethod *method)
7863 int typelen = 0, mlen, siglen;
7865 const IcallTypeDesc *imap;
7867 g_assert (method != NULL);
7869 if (method->is_inflated)
7870 method = ((MonoMethodInflated *) method)->declaring;
7872 if (method->klass->nested_in) {
7873 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7877 mname [pos++] = '/';
7880 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7886 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7891 imap = find_class_icalls (mname);
7893 mname [typelen] = ':';
7894 mname [typelen + 1] = ':';
7896 mlen = strlen (method->name);
7897 memcpy (mname + typelen + 2, method->name, mlen);
7898 sigstart = mname + typelen + 2 + mlen;
7901 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7902 siglen = strlen (tmpsig);
7903 if (typelen + mlen + siglen + 6 > sizeof (mname))
7906 memcpy (sigstart + 1, tmpsig, siglen);
7907 sigstart [siglen + 1] = ')';
7908 sigstart [siglen + 2] = 0;
7911 mono_loader_lock ();
7913 res = g_hash_table_lookup (icall_hash, mname);
7915 mono_loader_unlock ();
7918 /* try without signature */
7920 res = g_hash_table_lookup (icall_hash, mname);
7922 mono_loader_unlock ();
7926 /* it wasn't found in the static call tables */
7928 mono_loader_unlock ();
7931 res = find_method_icall (imap, sigstart - mlen);
7933 mono_loader_unlock ();
7936 /* try _with_ signature */
7938 res = find_method_icall (imap, sigstart - mlen);
7940 mono_loader_unlock ();
7944 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7945 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7946 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7947 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7948 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");
7949 g_print ("If you see other errors or faults after this message they are probably related\n");
7950 g_print ("and you need to fix your mono install first.\n");
7952 mono_loader_unlock ();
7958 type_from_typename (char *typename)
7960 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7962 if (!strcmp (typename, "int"))
7963 klass = mono_defaults.int_class;
7964 else if (!strcmp (typename, "ptr"))
7965 klass = mono_defaults.int_class;
7966 else if (!strcmp (typename, "void"))
7967 klass = mono_defaults.void_class;
7968 else if (!strcmp (typename, "int32"))
7969 klass = mono_defaults.int32_class;
7970 else if (!strcmp (typename, "uint32"))
7971 klass = mono_defaults.uint32_class;
7972 else if (!strcmp (typename, "int8"))
7973 klass = mono_defaults.sbyte_class;
7974 else if (!strcmp (typename, "uint8"))
7975 klass = mono_defaults.byte_class;
7976 else if (!strcmp (typename, "int16"))
7977 klass = mono_defaults.int16_class;
7978 else if (!strcmp (typename, "uint16"))
7979 klass = mono_defaults.uint16_class;
7980 else if (!strcmp (typename, "long"))
7981 klass = mono_defaults.int64_class;
7982 else if (!strcmp (typename, "ulong"))
7983 klass = mono_defaults.uint64_class;
7984 else if (!strcmp (typename, "float"))
7985 klass = mono_defaults.single_class;
7986 else if (!strcmp (typename, "double"))
7987 klass = mono_defaults.double_class;
7988 else if (!strcmp (typename, "object"))
7989 klass = mono_defaults.object_class;
7990 else if (!strcmp (typename, "obj"))
7991 klass = mono_defaults.object_class;
7992 else if (!strcmp (typename, "string"))
7993 klass = mono_defaults.string_class;
7994 else if (!strcmp (typename, "bool"))
7995 klass = mono_defaults.boolean_class;
7996 else if (!strcmp (typename, "boolean"))
7997 klass = mono_defaults.boolean_class;
7999 g_error ("%s", typename);
8000 g_assert_not_reached ();
8002 return &klass->byval_arg;
8005 MonoMethodSignature*
8006 mono_create_icall_signature (const char *sigstr)
8011 MonoMethodSignature *res;
8013 mono_loader_lock ();
8014 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8016 mono_loader_unlock ();
8020 parts = g_strsplit (sigstr, " ", 256);
8029 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8034 * Under windows, the default pinvoke calling convention is STDCALL but
8037 res->call_convention = MONO_CALL_C;
8040 res->ret = type_from_typename (parts [0]);
8041 for (i = 1; i < len; ++i) {
8042 res->params [i - 1] = type_from_typename (parts [i]);
8047 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8049 mono_loader_unlock ();
8055 mono_find_jit_icall_by_name (const char *name)
8057 MonoJitICallInfo *info;
8058 g_assert (jit_icall_hash_name);
8060 mono_loader_lock ();
8061 info = g_hash_table_lookup (jit_icall_hash_name, name);
8062 mono_loader_unlock ();
8067 mono_find_jit_icall_by_addr (gconstpointer addr)
8069 MonoJitICallInfo *info;
8070 g_assert (jit_icall_hash_addr);
8072 mono_loader_lock ();
8073 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8074 mono_loader_unlock ();
8080 * mono_get_jit_icall_info:
8082 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8083 * caller should access it while holding the loader lock.
8086 mono_get_jit_icall_info (void)
8088 return jit_icall_hash_name;
8092 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8094 mono_loader_lock ();
8095 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8096 mono_loader_unlock ();
8100 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8102 MonoJitICallInfo *info;
8107 mono_loader_lock ();
8109 if (!jit_icall_hash_name) {
8110 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8111 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8114 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8115 g_warning ("jit icall already defined \"%s\"\n", name);
8116 g_assert_not_reached ();
8119 info = g_new0 (MonoJitICallInfo, 1);
8126 info->wrapper = func;
8128 info->wrapper = NULL;
8131 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8132 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8134 mono_loader_unlock ();