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_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1941 MonoMethod *method = rmethod->method.method;
1943 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1946 /* From MonoProperty.cs */
1948 PInfo_Attributes = 1,
1949 PInfo_GetMethod = 1 << 1,
1950 PInfo_SetMethod = 1 << 2,
1951 PInfo_ReflectedType = 1 << 3,
1952 PInfo_DeclaringType = 1 << 4,
1957 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1959 MonoDomain *domain = mono_object_domain (property);
1961 MONO_ARCH_SAVE_REGS;
1963 if ((req_info & PInfo_ReflectedType) != 0)
1964 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1965 else if ((req_info & PInfo_DeclaringType) != 0)
1966 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1968 if ((req_info & PInfo_Name) != 0)
1969 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1971 if ((req_info & PInfo_Attributes) != 0)
1972 info->attrs = property->property->attrs;
1974 if ((req_info & PInfo_GetMethod) != 0)
1975 MONO_STRUCT_SETREF (info, get, property->property->get ?
1976 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1978 if ((req_info & PInfo_SetMethod) != 0)
1979 MONO_STRUCT_SETREF (info, set, property->property->set ?
1980 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1982 * There may be other methods defined for properties, though, it seems they are not exposed
1983 * in the reflection API
1988 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1990 MonoDomain *domain = mono_object_domain (event);
1992 MONO_ARCH_SAVE_REGS;
1994 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1995 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1997 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1998 info->attrs = event->event->attrs;
1999 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2000 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2001 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2003 #ifndef MONO_SMALL_CONFIG
2004 if (event->event->other) {
2006 while (event->event->other [n])
2008 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2010 for (i = 0; i < n; i++)
2011 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2017 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2022 mono_class_setup_interfaces (klass, error);
2023 if (!mono_error_ok (error))
2026 for (i = 0; i < klass->interface_count; i++) {
2027 ic = klass->interfaces [i];
2028 g_hash_table_insert (ifaces, ic, ic);
2030 collect_interfaces (ic, ifaces, error);
2031 if (!mono_error_ok (error))
2037 MonoArray *iface_array;
2038 MonoGenericContext *context;
2042 } FillIfaceArrayData;
2045 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2047 FillIfaceArrayData *data = user_data;
2048 MonoClass *ic = key;
2049 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2051 if (!mono_error_ok (data->error))
2054 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2055 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2056 if (!mono_error_ok (data->error))
2060 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2063 mono_metadata_free_type (inflated);
2067 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2070 MonoClass *class = mono_class_from_mono_type (type->type);
2072 FillIfaceArrayData data = { 0 };
2075 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2077 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2078 data.context = mono_class_get_context (class);
2079 class = class->generic_class->container_class;
2082 for (parent = class; parent; parent = parent->parent) {
2083 mono_class_setup_interfaces (parent, &error);
2084 if (!mono_error_ok (&error))
2086 collect_interfaces (parent, iface_hash, &error);
2087 if (!mono_error_ok (&error))
2091 data.error = &error;
2092 data.domain = mono_object_domain (type);
2094 len = g_hash_table_size (iface_hash);
2096 return mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2098 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2099 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2100 if (!mono_error_ok (&error))
2103 g_hash_table_destroy (iface_hash);
2104 return data.iface_array;
2107 g_hash_table_destroy (iface_hash);
2108 mono_error_raise_exception (&error);
2113 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2115 gboolean variance_used;
2116 MonoClass *class = mono_class_from_mono_type (type->type);
2117 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2118 MonoReflectionMethod *member;
2121 int i = 0, len, ioffset;
2124 MONO_ARCH_SAVE_REGS;
2125 mono_class_init_or_throw (class);
2126 mono_class_init_or_throw (iclass);
2128 mono_class_setup_vtable (class);
2130 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2134 len = mono_class_num_methods (iclass);
2135 domain = mono_object_domain (type);
2136 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2137 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2139 while ((method = mono_class_get_methods (iclass, &iter))) {
2140 member = mono_method_get_object (domain, method, iclass);
2141 mono_array_setref (*methods, i, member);
2142 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2143 mono_array_setref (*targets, i, member);
2150 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2152 MonoClass *klass = mono_class_from_mono_type (type->type);
2153 mono_class_init_or_throw (klass);
2155 if (klass->image->dynamic) {
2156 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2157 *packing = tb->packing_size;
2158 *size = tb->class_size;
2160 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2164 static MonoReflectionType*
2165 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2169 MONO_ARCH_SAVE_REGS;
2171 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2172 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2174 class = mono_class_from_mono_type (type->type);
2175 mono_class_init_or_throw (class);
2177 // GetElementType should only return a type for:
2178 // Array Pointer PassedByRef
2179 if (type->type->byref)
2180 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2181 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2182 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2183 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2184 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2189 static MonoReflectionType*
2190 ves_icall_get_type_parent (MonoReflectionType *type)
2192 MonoClass *class = mono_class_from_mono_type (type->type);
2193 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2197 ves_icall_type_ispointer (MonoReflectionType *type)
2199 MONO_ARCH_SAVE_REGS;
2201 return type->type->type == MONO_TYPE_PTR;
2205 ves_icall_type_isprimitive (MonoReflectionType *type)
2207 MONO_ARCH_SAVE_REGS;
2209 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)));
2213 ves_icall_type_isbyref (MonoReflectionType *type)
2215 MONO_ARCH_SAVE_REGS;
2217 return type->type->byref;
2221 ves_icall_type_iscomobject (MonoReflectionType *type)
2223 MonoClass *klass = mono_class_from_mono_type (type->type);
2224 mono_class_init_or_throw (klass);
2226 return (klass && klass->is_com_object);
2229 static MonoReflectionModule*
2230 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2232 MonoClass *class = mono_class_from_mono_type (type->type);
2233 return mono_module_get_object (mono_object_domain (type), class->image);
2236 static MonoReflectionAssembly*
2237 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2239 MonoDomain *domain = mono_domain_get ();
2240 MonoClass *class = mono_class_from_mono_type (type->type);
2241 //mono_class_init_or_throw (class);
2242 return mono_assembly_get_object (domain, class->image->assembly);
2245 static MonoReflectionType*
2246 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2248 MonoDomain *domain = mono_domain_get ();
2251 MONO_ARCH_SAVE_REGS;
2253 if (type->type->byref)
2255 if (type->type->type == MONO_TYPE_VAR)
2256 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2257 else if (type->type->type == MONO_TYPE_MVAR)
2258 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2260 class = mono_class_from_mono_type (type->type)->nested_in;
2262 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2266 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2268 MonoDomain *domain = mono_domain_get ();
2269 MonoClass *class = mono_class_from_mono_type (type->type);
2271 if (type->type->byref) {
2272 char *n = g_strdup_printf ("%s&", class->name);
2273 MonoString *res = mono_string_new (domain, n);
2279 return mono_string_new (domain, class->name);
2284 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2286 MonoDomain *domain = mono_domain_get ();
2287 MonoClass *class = mono_class_from_mono_type (type->type);
2289 while (class->nested_in)
2290 class = class->nested_in;
2292 if (class->name_space [0] == '\0')
2295 return mono_string_new (domain, class->name_space);
2299 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2303 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2304 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2306 class = mono_class_from_mono_type (type->type);
2307 mono_class_init_or_throw (class);
2313 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2316 MonoClass *klass, *pklass;
2317 MonoDomain *domain = mono_object_domain (type);
2318 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2320 MONO_ARCH_SAVE_REGS;
2322 klass = mono_class_from_mono_type (type->type);
2323 mono_class_init_or_throw (klass);
2325 if (klass->generic_container) {
2326 MonoGenericContainer *container = klass->generic_container;
2327 res = mono_array_new_specific (array_vtable, container->type_argc);
2328 for (i = 0; i < container->type_argc; ++i) {
2329 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2330 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2332 } else if (klass->generic_class) {
2333 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2334 res = mono_array_new_specific (array_vtable, inst->type_argc);
2335 for (i = 0; i < inst->type_argc; ++i)
2336 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2338 res = mono_array_new_specific (array_vtable, 0);
2344 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2347 MONO_ARCH_SAVE_REGS;
2349 if (!IS_MONOTYPE (type))
2352 if (type->type->byref)
2355 klass = mono_class_from_mono_type (type->type);
2356 return klass->generic_container != NULL;
2359 static MonoReflectionType*
2360 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2363 MONO_ARCH_SAVE_REGS;
2365 if (type->type->byref)
2368 klass = mono_class_from_mono_type (type->type);
2369 mono_class_init_or_throw (klass);
2371 if (klass->generic_container) {
2372 return type; /* check this one */
2374 if (klass->generic_class) {
2375 MonoClass *generic_class = klass->generic_class->container_class;
2378 tb = mono_class_get_ref_info (generic_class);
2380 if (generic_class->wastypebuilder && tb)
2383 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2388 static MonoReflectionType*
2389 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2391 MonoType *geninst, **types;
2394 g_assert (IS_MONOTYPE (type));
2395 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2397 count = mono_array_length (type_array);
2398 types = g_new0 (MonoType *, count);
2400 for (i = 0; i < count; i++) {
2401 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2402 types [i] = t->type;
2405 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2410 return mono_type_get_object (mono_object_domain (type), geninst);
2414 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2417 MONO_ARCH_SAVE_REGS;
2419 if (type->type->byref)
2422 klass = mono_class_from_mono_type (type->type);
2424 return klass->generic_class != NULL;
2428 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2431 MONO_ARCH_SAVE_REGS;
2433 if (!IS_MONOTYPE (type))
2436 if (type->type->byref)
2439 klass = mono_class_from_mono_type (type->type);
2440 return klass->generic_class != NULL || klass->generic_container != NULL;
2444 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2446 MONO_ARCH_SAVE_REGS;
2448 if (!IS_MONOTYPE (type))
2451 if (is_generic_parameter (type->type))
2452 return mono_type_get_generic_param_num (type->type);
2456 static GenericParameterAttributes
2457 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2459 MONO_ARCH_SAVE_REGS;
2461 g_assert (IS_MONOTYPE (type));
2462 g_assert (is_generic_parameter (type->type));
2463 return mono_generic_param_info (type->type->data.generic_param)->flags;
2467 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2469 MonoGenericParamInfo *param_info;
2475 MONO_ARCH_SAVE_REGS;
2477 g_assert (IS_MONOTYPE (type));
2479 domain = mono_object_domain (type);
2480 param_info = mono_generic_param_info (type->type->data.generic_param);
2481 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2484 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2485 for (i = 0; i < count; i++)
2486 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2493 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2495 MONO_ARCH_SAVE_REGS;
2496 return is_generic_parameter (type->type);
2500 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2502 MONO_ARCH_SAVE_REGS;
2503 return is_generic_parameter (tb->type.type);
2507 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2508 MonoReflectionType *t)
2510 enumtype->type = t->type;
2513 static MonoReflectionMethod*
2514 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2515 MonoReflectionMethod* generic)
2522 MONO_ARCH_SAVE_REGS;
2524 domain = ((MonoObject *)type)->vtable->domain;
2526 klass = mono_class_from_mono_type (type->type);
2527 mono_class_init_or_throw (klass);
2530 while ((method = mono_class_get_methods (klass, &iter))) {
2531 if (method->token == generic->method->token)
2532 return mono_method_get_object (domain, method, klass);
2540 static MonoReflectionMethod *
2541 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2544 MonoType *type = ref_type->type;
2546 MONO_ARCH_SAVE_REGS;
2548 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2549 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2550 if (type->type == MONO_TYPE_VAR)
2553 method = mono_type_get_generic_param_owner (type)->owner.method;
2555 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2558 static MonoReflectionDllImportAttribute*
2559 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2561 static MonoClass *DllImportAttributeClass = NULL;
2562 MonoDomain *domain = mono_domain_get ();
2563 MonoReflectionDllImportAttribute *attr;
2564 MonoImage *image = method->klass->image;
2565 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2566 MonoTableInfo *tables = image->tables;
2567 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2568 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2569 guint32 im_cols [MONO_IMPLMAP_SIZE];
2570 guint32 scope_token;
2571 const char *import = NULL;
2572 const char *scope = NULL;
2575 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2578 if (!DllImportAttributeClass) {
2579 DllImportAttributeClass =
2580 mono_class_from_name (mono_defaults.corlib,
2581 "System.Runtime.InteropServices", "DllImportAttribute");
2582 g_assert (DllImportAttributeClass);
2585 if (method->klass->image->dynamic) {
2586 MonoReflectionMethodAux *method_aux =
2587 g_hash_table_lookup (
2588 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2590 import = method_aux->dllentry;
2591 scope = method_aux->dll;
2594 if (!import || !scope) {
2595 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2600 if (piinfo->implmap_idx) {
2601 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2603 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2604 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2605 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2606 scope = mono_metadata_string_heap (image, scope_token);
2609 flags = piinfo->piflags;
2611 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2613 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2614 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2615 attr->call_conv = (flags & 0x700) >> 8;
2616 attr->charset = ((flags & 0x6) >> 1) + 1;
2617 if (attr->charset == 1)
2619 attr->exact_spelling = (flags & 0x1) != 0;
2620 attr->set_last_error = (flags & 0x40) != 0;
2621 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2622 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2623 attr->preserve_sig = FALSE;
2628 static MonoReflectionMethod *
2629 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2631 MonoMethodInflated *imethod;
2634 MONO_ARCH_SAVE_REGS;
2636 if (method->method->is_generic)
2639 if (!method->method->is_inflated)
2642 imethod = (MonoMethodInflated *) method->method;
2644 result = imethod->declaring;
2645 /* Not a generic method. */
2646 if (!result->is_generic)
2649 if (method->method->klass->image->dynamic) {
2650 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2651 MonoReflectionMethod *res;
2654 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2655 * the dynamic case as well ?
2657 mono_loader_lock ();
2658 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2659 mono_loader_unlock ();
2665 if (imethod->context.class_inst) {
2666 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2667 /*Generic methods gets the context of the GTD.*/
2668 if (mono_class_get_context (klass))
2669 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2672 return mono_method_get_object (mono_object_domain (method), result, NULL);
2676 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2678 MONO_ARCH_SAVE_REGS;
2680 return mono_method_signature (method->method)->generic_param_count != 0;
2684 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2686 MONO_ARCH_SAVE_REGS;
2688 return method->method->is_generic;
2692 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2697 MONO_ARCH_SAVE_REGS;
2699 domain = mono_object_domain (method);
2701 if (method->method->is_inflated) {
2702 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2705 count = inst->type_argc;
2706 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2708 for (i = 0; i < count; i++)
2709 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2715 count = mono_method_signature (method->method)->generic_param_count;
2716 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2718 for (i = 0; i < count; i++) {
2719 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2720 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2721 MonoClass *pklass = mono_class_from_generic_parameter (
2722 param, method->method->klass->image, TRUE);
2723 mono_array_setref (res, i,
2724 mono_type_get_object (domain, &pklass->byval_arg));
2731 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2734 * Invoke from reflection is supposed to always be a virtual call (the API
2735 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2736 * greater flexibility.
2738 MonoMethod *m = method->method;
2742 MONO_ARCH_SAVE_REGS;
2746 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2747 mono_security_core_clr_ensure_reflection_access_method (m);
2749 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2750 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2751 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2756 if (!mono_object_isinst (this, m->klass)) {
2757 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2760 m = mono_object_get_virtual_method (this, m);
2761 /* must pass the pointer to the value for valuetype methods */
2762 if (m->klass->valuetype)
2763 obj = mono_object_unbox (this);
2764 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2765 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2770 pcount = params? mono_array_length (params): 0;
2771 if (pcount != mono_method_signature (m)->param_count) {
2772 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2776 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2777 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."));
2781 if (m->klass->image->assembly->ref_only) {
2782 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."));
2786 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2789 intptr_t *lower_bounds;
2790 pcount = mono_array_length (params);
2791 lengths = alloca (sizeof (uintptr_t) * pcount);
2792 /* Note: the synthetized array .ctors have int32 as argument type */
2793 for (i = 0; i < pcount; ++i)
2794 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2796 if (m->klass->rank == pcount) {
2797 /* Only lengths provided. */
2798 lower_bounds = NULL;
2800 g_assert (pcount == (m->klass->rank * 2));
2801 /* lower bounds are first. */
2802 lower_bounds = (intptr_t*)lengths;
2803 lengths += m->klass->rank;
2806 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2808 return mono_runtime_invoke_array (m, obj, params, NULL);
2812 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2814 MonoDomain *domain = mono_object_domain (method);
2815 MonoMethod *m = method->method;
2816 MonoMethodSignature *sig = mono_method_signature (m);
2817 MonoArray *out_args;
2819 int i, j, outarg_count = 0;
2821 MONO_ARCH_SAVE_REGS;
2823 if (m->klass == mono_defaults.object_class) {
2825 if (!strcmp (m->name, "FieldGetter")) {
2826 MonoClass *k = this->vtable->klass;
2830 /* If this is a proxy, then it must be a CBO */
2831 if (k == mono_defaults.transparent_proxy_class) {
2832 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2833 this = tp->rp->unwrapped_server;
2835 k = this->vtable->klass;
2838 name = mono_array_get (params, MonoString *, 1);
2839 str = mono_string_to_utf8 (name);
2842 MonoClassField* field = mono_class_get_field_from_name (k, str);
2844 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2845 if (field_klass->valuetype)
2846 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2848 result = *((gpointer *)((char *)this + field->offset));
2850 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2851 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2852 mono_array_setref (out_args, 0, result);
2860 g_assert_not_reached ();
2862 } else if (!strcmp (m->name, "FieldSetter")) {
2863 MonoClass *k = this->vtable->klass;
2869 /* If this is a proxy, then it must be a CBO */
2870 if (k == mono_defaults.transparent_proxy_class) {
2871 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2872 this = tp->rp->unwrapped_server;
2874 k = this->vtable->klass;
2877 name = mono_array_get (params, MonoString *, 1);
2878 str = mono_string_to_utf8 (name);
2881 MonoClassField* field = mono_class_get_field_from_name (k, str);
2883 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2884 MonoObject *val = mono_array_get (params, gpointer, 2);
2886 if (field_klass->valuetype) {
2887 size = mono_type_size (field->type, &align);
2888 g_assert (size == mono_class_value_size (field_klass, NULL));
2889 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2891 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2894 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2895 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2905 g_assert_not_reached ();
2910 for (i = 0; i < mono_array_length (params); i++) {
2911 if (sig->params [i]->byref)
2915 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2917 /* handle constructors only for objects already allocated */
2918 if (!strcmp (method->method->name, ".ctor"))
2921 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2922 g_assert (!method->method->klass->valuetype);
2923 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2925 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2926 if (sig->params [i]->byref) {
2928 arg = mono_array_get (params, gpointer, i);
2929 mono_array_setref (out_args, j, arg);
2934 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2940 read_enum_value (char *mem, int type)
2944 return *(guint8*)mem;
2946 return *(gint8*)mem;
2948 return *(guint16*)mem;
2950 return *(gint16*)mem;
2952 return *(guint32*)mem;
2954 return *(gint32*)mem;
2956 return *(guint64*)mem;
2958 return *(gint64*)mem;
2960 g_assert_not_reached ();
2966 write_enum_value (char *mem, int type, guint64 value)
2970 case MONO_TYPE_I1: {
2971 guint8 *p = (guint8*)mem;
2976 case MONO_TYPE_I2: {
2977 guint16 *p = (void*)mem;
2982 case MONO_TYPE_I4: {
2983 guint32 *p = (void*)mem;
2988 case MONO_TYPE_I8: {
2989 guint64 *p = (void*)mem;
2994 g_assert_not_reached ();
3000 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3003 MonoClass *enumc, *objc;
3008 MONO_ARCH_SAVE_REGS;
3010 MONO_CHECK_ARG_NULL (enumType);
3011 MONO_CHECK_ARG_NULL (value);
3013 domain = mono_object_domain (enumType);
3014 enumc = mono_class_from_mono_type (enumType->type);
3016 mono_class_init_or_throw (enumc);
3018 objc = value->vtable->klass;
3020 if (!enumc->enumtype)
3021 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3022 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3023 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."));
3025 etype = mono_class_enum_basetype (enumc);
3027 /* MS throws this for typebuilders */
3028 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3030 res = mono_object_new (domain, enumc);
3031 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3032 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3038 ves_icall_System_Enum_get_value (MonoObject *this)
3046 MONO_ARCH_SAVE_REGS;
3051 g_assert (this->vtable->klass->enumtype);
3053 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3054 res = mono_object_new (mono_object_domain (this), enumc);
3055 dst = (char *)res + sizeof (MonoObject);
3056 src = (char *)this + sizeof (MonoObject);
3057 size = mono_class_value_size (enumc, NULL);
3059 memcpy (dst, src, size);
3064 static MonoReflectionType *
3065 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3070 MONO_ARCH_SAVE_REGS;
3072 klass = mono_class_from_mono_type (type->type);
3073 mono_class_init_or_throw (klass);
3075 etype = mono_class_enum_basetype (klass);
3077 /* MS throws this for typebuilders */
3078 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3080 return mono_type_get_object (mono_object_domain (type), etype);
3084 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3086 gpointer tdata = (char *)this + sizeof (MonoObject);
3087 gpointer odata = (char *)other + sizeof (MonoObject);
3088 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3089 g_assert (basetype);
3091 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3092 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3093 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3096 return me > other ? 1 : -1; \
3099 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3100 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3101 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3104 return me - other; \
3107 switch (basetype->type) {
3109 COMPARE_ENUM_VALUES (guint8);
3111 COMPARE_ENUM_VALUES (gint8);
3112 case MONO_TYPE_CHAR:
3114 COMPARE_ENUM_VALUES_RANGE (guint16);
3116 COMPARE_ENUM_VALUES (gint16);
3118 COMPARE_ENUM_VALUES (guint32);
3120 COMPARE_ENUM_VALUES (gint32);
3122 COMPARE_ENUM_VALUES (guint64);
3124 COMPARE_ENUM_VALUES (gint64);
3126 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3128 #undef COMPARE_ENUM_VALUES_RANGE
3129 #undef COMPARE_ENUM_VALUES
3134 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3136 gpointer data = (char *)this + sizeof (MonoObject);
3137 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3138 g_assert (basetype);
3140 switch (basetype->type) {
3142 return *((gint8*)data);
3144 return *((guint8*)data);
3145 case MONO_TYPE_CHAR:
3147 return *((guint16*)data);
3150 return *((gint16*)data);
3152 return *((guint32*)data);
3154 return *((gint32*)data);
3156 case MONO_TYPE_I8: {
3157 gint64 value = *((gint64*)data);
3158 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3161 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3167 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3169 MonoDomain *domain = mono_object_domain (type);
3170 MonoClass *enumc = mono_class_from_mono_type (type->type);
3171 guint j = 0, nvalues, crow;
3173 MonoClassField *field;
3175 MONO_ARCH_SAVE_REGS;
3177 mono_class_init_or_throw (enumc);
3179 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3180 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3181 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3182 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3186 while ((field = mono_class_get_fields (enumc, &iter))) {
3189 MonoTypeEnum def_type;
3191 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3193 if (mono_field_is_deleted (field))
3195 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3197 p = mono_class_get_field_default_value (field, &def_type);
3198 len = mono_metadata_decode_blob_size (p, &p);
3199 switch (mono_class_enum_basetype (enumc)->type) {
3202 mono_array_set (info->values, gchar, j, *p);
3204 case MONO_TYPE_CHAR:
3207 mono_array_set (info->values, gint16, j, read16 (p));
3211 mono_array_set (info->values, gint32, j, read32 (p));
3215 mono_array_set (info->values, gint64, j, read64 (p));
3218 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3225 BFLAGS_IgnoreCase = 1,
3226 BFLAGS_DeclaredOnly = 2,
3227 BFLAGS_Instance = 4,
3229 BFLAGS_Public = 0x10,
3230 BFLAGS_NonPublic = 0x20,
3231 BFLAGS_FlattenHierarchy = 0x40,
3232 BFLAGS_InvokeMethod = 0x100,
3233 BFLAGS_CreateInstance = 0x200,
3234 BFLAGS_GetField = 0x400,
3235 BFLAGS_SetField = 0x800,
3236 BFLAGS_GetProperty = 0x1000,
3237 BFLAGS_SetProperty = 0x2000,
3238 BFLAGS_ExactBinding = 0x10000,
3239 BFLAGS_SuppressChangeType = 0x20000,
3240 BFLAGS_OptionalParamBinding = 0x40000
3243 static MonoReflectionField *
3244 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3247 MonoClass *startklass, *klass;
3249 MonoClassField *field;
3252 int (*compare_func) (const char *s1, const char *s2) = NULL;
3253 domain = ((MonoObject *)type)->vtable->domain;
3254 klass = startklass = mono_class_from_mono_type (type->type);
3255 mono_class_init_or_throw (klass);
3258 mono_raise_exception (mono_get_exception_argument_null ("name"));
3259 if (type->type->byref)
3262 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3265 if (klass->exception_type != MONO_EXCEPTION_NONE)
3266 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3269 while ((field = mono_class_get_fields (klass, &iter))) {
3272 if (field->type == NULL)
3274 if (mono_field_is_deleted (field))
3276 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3277 if (bflags & BFLAGS_Public)
3279 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3280 if (bflags & BFLAGS_NonPublic) {
3287 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3288 if (bflags & BFLAGS_Static)
3289 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3292 if (bflags & BFLAGS_Instance)
3299 utf8_name = mono_string_to_utf8 (name);
3301 if (compare_func (mono_field_get_name (field), utf8_name)) {
3307 return mono_field_get_object (domain, klass, field);
3309 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3316 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3319 MonoClass *startklass, *klass, *refklass;
3324 MonoClassField *field;
3325 MonoPtrArray tmp_array;
3327 MONO_ARCH_SAVE_REGS;
3329 domain = ((MonoObject *)type)->vtable->domain;
3330 if (type->type->byref)
3331 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3332 klass = startklass = mono_class_from_mono_type (type->type);
3333 refklass = mono_class_from_mono_type (reftype->type);
3335 mono_class_init_or_throw (klass);
3336 mono_class_init_or_throw (refklass);
3338 mono_ptr_array_init (tmp_array, 2);
3341 if (klass->exception_type != MONO_EXCEPTION_NONE)
3342 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3345 while ((field = mono_class_get_fields (klass, &iter))) {
3347 if (mono_field_is_deleted (field))
3349 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3350 if (bflags & BFLAGS_Public)
3352 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3353 if (bflags & BFLAGS_NonPublic) {
3360 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3361 if (bflags & BFLAGS_Static)
3362 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3365 if (bflags & BFLAGS_Instance)
3371 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3372 mono_ptr_array_append (tmp_array, member);
3374 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3377 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3379 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3380 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3382 mono_ptr_array_destroy (tmp_array);
3388 method_nonpublic (MonoMethod* method, gboolean start_klass)
3390 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3391 case METHOD_ATTRIBUTE_ASSEM:
3392 return (start_klass || mono_defaults.generic_ilist_class);
3393 case METHOD_ATTRIBUTE_PRIVATE:
3395 case METHOD_ATTRIBUTE_PUBLIC:
3403 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3405 static MonoClass *MethodInfo_array;
3407 MonoClass *startklass, *klass, *refklass;
3412 int i, len, match, nslots;
3413 /*FIXME, use MonoBitSet*/
3414 guint32 method_slots_default [8];
3415 guint32 *method_slots = NULL;
3416 gchar *mname = NULL;
3417 int (*compare_func) (const char *s1, const char *s2) = NULL;
3418 MonoVTable *array_vtable;
3420 MonoPtrArray tmp_array;
3422 mono_ptr_array_init (tmp_array, 4);
3424 if (!MethodInfo_array) {
3425 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3426 mono_memory_barrier ();
3427 MethodInfo_array = klass;
3430 domain = ((MonoObject *)type)->vtable->domain;
3431 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3432 if (type->type->byref)
3433 return mono_array_new_specific (array_vtable, 0);
3434 klass = startklass = mono_class_from_mono_type (type->type);
3435 refklass = mono_class_from_mono_type (reftype->type);
3437 mono_class_init_or_throw (klass);
3438 mono_class_init_or_throw (refklass);
3442 mname = mono_string_to_utf8 (name);
3443 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3446 /* An optimization for calls made from Delegate:CreateDelegate () */
3447 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3448 method = mono_get_delegate_invoke (klass);
3449 if (mono_loader_get_last_error ())
3452 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3454 res = mono_array_new_specific (array_vtable, 1);
3455 mono_array_setref (res, 0, member);
3460 mono_class_setup_vtable (klass);
3461 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3464 if (is_generic_parameter (type->type))
3465 nslots = mono_class_get_vtable_size (klass->parent);
3467 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3468 if (nslots >= sizeof (method_slots_default) * 8) {
3469 method_slots = g_new0 (guint32, nslots / 32 + 1);
3471 method_slots = method_slots_default;
3472 memset (method_slots, 0, sizeof (method_slots_default));
3475 mono_class_setup_vtable (klass);
3476 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3480 while ((method = mono_class_get_methods (klass, &iter))) {
3482 if (method->slot != -1) {
3483 g_assert (method->slot < nslots);
3484 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3486 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3487 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3490 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3492 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3493 if (bflags & BFLAGS_Public)
3495 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3501 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3502 if (bflags & BFLAGS_Static)
3503 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3506 if (bflags & BFLAGS_Instance)
3514 if (compare_func (mname, method->name))
3520 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3522 mono_ptr_array_append (tmp_array, member);
3524 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3528 if (method_slots != method_slots_default)
3529 g_free (method_slots);
3531 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3533 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3534 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3536 mono_ptr_array_destroy (tmp_array);
3541 if (method_slots != method_slots_default)
3542 g_free (method_slots);
3543 mono_ptr_array_destroy (tmp_array);
3544 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3545 ex = mono_class_get_exception_for_failure (klass);
3547 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3548 mono_loader_clear_error ();
3550 mono_raise_exception (ex);
3555 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3558 static MonoClass *System_Reflection_ConstructorInfo;
3559 MonoClass *startklass, *klass, *refklass;
3564 gpointer iter = NULL;
3565 MonoPtrArray tmp_array;
3567 MONO_ARCH_SAVE_REGS;
3569 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3571 domain = ((MonoObject *)type)->vtable->domain;
3572 if (type->type->byref)
3573 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3574 klass = startklass = mono_class_from_mono_type (type->type);
3575 refklass = mono_class_from_mono_type (reftype->type);
3577 mono_class_init_or_throw (klass);
3578 mono_class_init_or_throw (refklass);
3580 if (klass->exception_type != MONO_EXCEPTION_NONE)
3581 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3583 if (!System_Reflection_ConstructorInfo)
3584 System_Reflection_ConstructorInfo = mono_class_from_name (
3585 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3588 while ((method = mono_class_get_methods (klass, &iter))) {
3590 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3592 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3593 if (bflags & BFLAGS_Public)
3596 if (bflags & BFLAGS_NonPublic)
3602 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3603 if (bflags & BFLAGS_Static)
3604 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3607 if (bflags & BFLAGS_Instance)
3613 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3615 mono_ptr_array_append (tmp_array, member);
3618 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3620 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3621 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3623 mono_ptr_array_destroy (tmp_array);
3629 property_hash (gconstpointer data)
3631 MonoProperty *prop = (MonoProperty*)data;
3633 return g_str_hash (prop->name);
3637 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3639 // Properties are hide-by-name-and-signature
3640 if (!g_str_equal (prop1->name, prop2->name))
3643 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3645 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3651 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3656 return method_nonpublic (accessor, start_klass);
3660 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3663 static MonoClass *System_Reflection_PropertyInfo;
3664 MonoClass *startklass, *klass;
3670 gchar *propname = NULL;
3671 int (*compare_func) (const char *s1, const char *s2) = NULL;
3673 GHashTable *properties;
3674 MonoPtrArray tmp_array;
3676 MONO_ARCH_SAVE_REGS;
3678 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3680 if (!System_Reflection_PropertyInfo)
3681 System_Reflection_PropertyInfo = mono_class_from_name (
3682 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3684 domain = ((MonoObject *)type)->vtable->domain;
3685 if (type->type->byref)
3686 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3687 klass = startklass = mono_class_from_mono_type (type->type);
3688 mono_class_init_or_throw (klass);
3693 propname = mono_string_to_utf8 (name);
3694 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3697 mono_class_setup_vtable (klass);
3699 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3701 mono_class_setup_vtable (klass);
3702 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3703 g_hash_table_destroy (properties);
3706 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3710 while ((prop = mono_class_get_properties (klass, &iter))) {
3716 flags = method->flags;
3719 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3720 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3721 if (bflags & BFLAGS_Public)
3723 } else if (bflags & BFLAGS_NonPublic) {
3724 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3725 property_accessor_nonpublic(prop->set, startklass == klass)) {
3732 if (flags & METHOD_ATTRIBUTE_STATIC) {
3733 if (bflags & BFLAGS_Static)
3734 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3737 if (bflags & BFLAGS_Instance)
3746 if (compare_func (propname, prop->name))
3750 if (g_hash_table_lookup (properties, prop))
3753 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3755 g_hash_table_insert (properties, prop, prop);
3757 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3760 g_hash_table_destroy (properties);
3763 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3764 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3765 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3767 mono_ptr_array_destroy (tmp_array);
3772 static MonoReflectionEvent *
3773 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3776 MonoClass *klass, *startklass;
3781 int (*compare_func) (const char *s1, const char *s2);
3783 MONO_ARCH_SAVE_REGS;
3785 event_name = mono_string_to_utf8 (name);
3786 if (type->type->byref)
3788 klass = startklass = mono_class_from_mono_type (type->type);
3789 domain = mono_object_domain (type);
3791 mono_class_init_or_throw (klass);
3793 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3795 if (klass->exception_type != MONO_EXCEPTION_NONE)
3796 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3799 while ((event = mono_class_get_events (klass, &iter))) {
3800 if (compare_func (event->name, event_name))
3803 method = event->add;
3805 method = event->remove;
3807 method = event->raise;
3809 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3810 if (!(bflags & BFLAGS_Public))
3813 if (!(bflags & BFLAGS_NonPublic))
3815 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3819 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3820 if (!(bflags & BFLAGS_Static))
3822 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3825 if (!(bflags & BFLAGS_Instance))
3829 if (!(bflags & BFLAGS_NonPublic))
3832 g_free (event_name);
3833 return mono_event_get_object (domain, startklass, event);
3836 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3839 g_free (event_name);
3844 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3847 static MonoClass *System_Reflection_EventInfo;
3848 MonoClass *startklass, *klass;
3855 MonoPtrArray tmp_array;
3857 MONO_ARCH_SAVE_REGS;
3859 mono_ptr_array_init (tmp_array, 4);
3861 if (!System_Reflection_EventInfo)
3862 System_Reflection_EventInfo = mono_class_from_name (
3863 mono_defaults.corlib, "System.Reflection", "EventInfo");
3865 domain = mono_object_domain (type);
3866 if (type->type->byref)
3867 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3868 klass = startklass = mono_class_from_mono_type (type->type);
3869 mono_class_init_or_throw (klass);
3873 if (klass->exception_type != MONO_EXCEPTION_NONE)
3874 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3877 while ((event = mono_class_get_events (klass, &iter))) {
3879 method = event->add;
3881 method = event->remove;
3883 method = event->raise;
3885 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3886 if (bflags & BFLAGS_Public)
3888 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3889 if (bflags & BFLAGS_NonPublic)
3894 if (bflags & BFLAGS_NonPublic)
3900 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3901 if (bflags & BFLAGS_Static)
3902 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3905 if (bflags & BFLAGS_Instance)
3910 if (bflags & BFLAGS_Instance)
3914 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3916 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3919 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3921 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3922 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3924 mono_ptr_array_destroy (tmp_array);
3929 static MonoReflectionType *
3930 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
3938 MONO_ARCH_SAVE_REGS;
3941 mono_raise_exception (mono_get_exception_argument_null ("name"));
3943 domain = ((MonoObject *)type)->vtable->domain;
3944 if (type->type->byref)
3946 klass = mono_class_from_mono_type (type->type);
3947 mono_class_init_or_throw (klass);
3949 str = mono_string_to_utf8 (name);
3952 if (klass->exception_type != MONO_EXCEPTION_NONE)
3953 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3956 * If a nested type is generic, return its generic type definition.
3957 * Note that this means that the return value is essentially a
3958 * nested type of the generic type definition of @klass.
3960 * A note in MSDN claims that a generic type definition can have
3961 * nested types that aren't generic. In any case, the container of that
3962 * nested type would be the generic type definition.
3964 if (klass->generic_class)
3965 klass = klass->generic_class->container_class;
3968 while ((nested = mono_class_get_nested_types (klass, &iter))) {
3970 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
3971 if (bflags & BFLAGS_Public)
3974 if (bflags & BFLAGS_NonPublic)
3979 if (strcmp (nested->name, str) == 0){
3981 return mono_type_get_object (domain, &nested->byval_arg);
3984 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3991 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4000 MonoPtrArray tmp_array;
4002 MONO_ARCH_SAVE_REGS;
4004 domain = ((MonoObject *)type)->vtable->domain;
4005 if (type->type->byref)
4006 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4007 klass = mono_class_from_mono_type (type->type);
4008 mono_class_init_or_throw (klass);
4011 * If a nested type is generic, return its generic type definition.
4012 * Note that this means that the return value is essentially the set
4013 * of nested types of the generic type definition of @klass.
4015 * A note in MSDN claims that a generic type definition can have
4016 * nested types that aren't generic. In any case, the container of that
4017 * nested type would be the generic type definition.
4019 if (klass->generic_class)
4020 klass = klass->generic_class->container_class;
4022 mono_ptr_array_init (tmp_array, 1);
4024 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4026 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4027 if (bflags & BFLAGS_Public)
4030 if (bflags & BFLAGS_NonPublic)
4035 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4036 mono_ptr_array_append (tmp_array, member);
4039 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4041 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4042 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4044 mono_ptr_array_destroy (tmp_array);
4049 static MonoReflectionType*
4050 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4053 MonoType *type = NULL;
4054 MonoTypeNameParse info;
4055 gboolean type_resolve;
4057 MONO_ARCH_SAVE_REGS;
4059 /* On MS.NET, this does not fire a TypeResolve event */
4060 type_resolve = TRUE;
4061 str = mono_string_to_utf8 (name);
4062 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4063 if (!mono_reflection_parse_type (str, &info)) {
4065 mono_reflection_free_type_info (&info);
4066 if (throwOnError) /* uhm: this is a parse error, though... */
4067 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4068 /*g_print ("failed parse\n");*/
4072 if (info.assembly.name) {
4074 mono_reflection_free_type_info (&info);
4076 /* 1.0 and 2.0 throw different exceptions */
4077 if (mono_defaults.generic_ilist_class)
4078 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4080 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4085 if (module != NULL) {
4087 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4092 if (assembly->assembly->dynamic) {
4093 /* Enumerate all modules */
4094 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4098 if (abuilder->modules) {
4099 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4100 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4101 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4107 if (!type && abuilder->loaded_modules) {
4108 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4109 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4110 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4117 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4119 mono_reflection_free_type_info (&info);
4121 MonoException *e = NULL;
4124 e = mono_get_exception_type_load (name, NULL);
4126 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4127 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4129 mono_loader_clear_error ();
4132 mono_raise_exception (e);
4135 } else if (mono_loader_get_last_error ()) {
4137 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4138 mono_loader_clear_error ();
4141 if (type->type == MONO_TYPE_CLASS) {
4142 MonoClass *klass = mono_type_get_class (type);
4144 if (mono_is_security_manager_active () && !klass->exception_type)
4145 /* Some security problems are detected during generic vtable construction */
4146 mono_class_setup_vtable (klass);
4147 /* need to report exceptions ? */
4148 if (throwOnError && klass->exception_type) {
4149 /* report SecurityException (or others) that occured when loading the assembly */
4150 MonoException *exc = mono_class_get_exception_for_failure (klass);
4151 mono_loader_clear_error ();
4152 mono_raise_exception (exc);
4153 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4158 /* g_print ("got it\n"); */
4159 return mono_type_get_object (mono_object_domain (assembly), type);
4163 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4166 gchar *shadow_ini_file;
4169 /* Check for shadow-copied assembly */
4170 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4171 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4173 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4174 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4180 g_free (shadow_ini_file);
4181 if (content != NULL) {
4184 *filename = content;
4192 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4194 MonoDomain *domain = mono_object_domain (assembly);
4195 MonoAssembly *mass = assembly->assembly;
4196 MonoString *res = NULL;
4201 MONO_ARCH_SAVE_REGS;
4203 if (g_path_is_absolute (mass->image->name)) {
4204 absolute = g_strdup (mass->image->name);
4205 dirname = g_path_get_dirname (absolute);
4207 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4208 dirname = g_strdup (mass->basedir);
4211 replace_shadow_path (domain, dirname, &absolute);
4216 for (i = strlen (absolute) - 1; i >= 0; i--)
4217 if (absolute [i] == '\\')
4222 uri = g_filename_to_uri (absolute, NULL, NULL);
4224 const char *prepend = "file://";
4226 if (*absolute == '/' && *(absolute + 1) == '/') {
4229 prepend = "file:///";
4232 uri = g_strconcat (prepend, absolute, NULL);
4236 res = mono_string_new (domain, uri);
4244 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4246 MonoAssembly *mass = assembly->assembly;
4248 MONO_ARCH_SAVE_REGS;
4250 return mass->in_gac;
4253 static MonoReflectionAssembly*
4254 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4258 MonoImageOpenStatus status;
4260 MONO_ARCH_SAVE_REGS;
4262 name = mono_string_to_utf8 (mname);
4263 res = mono_assembly_load_with_partial_name (name, &status);
4269 return mono_assembly_get_object (mono_domain_get (), res);
4273 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4275 MonoDomain *domain = mono_object_domain (assembly);
4278 MONO_ARCH_SAVE_REGS;
4280 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4286 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4288 MONO_ARCH_SAVE_REGS;
4290 return assembly->assembly->ref_only;
4294 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4296 MonoDomain *domain = mono_object_domain (assembly);
4298 MONO_ARCH_SAVE_REGS;
4300 return mono_string_new (domain, assembly->assembly->image->version);
4303 static MonoReflectionMethod*
4304 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4306 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4308 MONO_ARCH_SAVE_REGS;
4312 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4315 static MonoReflectionModule*
4316 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4318 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4322 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4324 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4325 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4329 MONO_ARCH_SAVE_REGS;
4331 for (i = 0; i < table->rows; ++i) {
4332 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4333 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4339 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4341 static MonoClass *System_Version = NULL;
4342 static MonoMethod *create_version = NULL;
4346 if (!System_Version) {
4347 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4348 g_assert (System_Version);
4351 if (!create_version) {
4352 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4353 create_version = mono_method_desc_search_in_class (desc, System_Version);
4354 g_assert (create_version);
4355 mono_method_desc_free (desc);
4361 args [3] = &revision;
4362 result = mono_object_new (domain, System_Version);
4363 mono_runtime_invoke (create_version, result, args, NULL);
4369 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4371 static MonoClass *System_Reflection_AssemblyName;
4373 MonoDomain *domain = mono_object_domain (assembly);
4375 static MonoMethod *create_culture = NULL;
4376 MonoImage *image = assembly->assembly->image;
4379 MONO_ARCH_SAVE_REGS;
4381 if (!System_Reflection_AssemblyName)
4382 System_Reflection_AssemblyName = mono_class_from_name (
4383 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4385 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4388 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4390 if (count > 0 && !create_culture) {
4391 MonoMethodDesc *desc = mono_method_desc_new (
4392 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4393 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4394 g_assert (create_culture);
4395 mono_method_desc_free (desc);
4398 for (i = 0; i < count; i++) {
4399 MonoReflectionAssemblyName *aname;
4400 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4402 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4404 aname = (MonoReflectionAssemblyName *) mono_object_new (
4405 domain, System_Reflection_AssemblyName);
4407 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4409 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4410 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4411 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4412 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4413 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4414 aname->versioncompat = 1; /* SameMachine (default) */
4415 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4416 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4418 if (create_culture) {
4420 MonoBoolean assembly_ref = 1;
4421 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4422 args [1] = &assembly_ref;
4423 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4426 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4427 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4428 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4430 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4431 /* public key token isn't copied - the class library will
4432 automatically generate it from the public key if required */
4433 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4434 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4436 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4437 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4440 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4443 /* note: this function doesn't return the codebase on purpose (i.e. it can
4444 be used under partial trust as path information isn't present). */
4446 mono_array_setref (result, i, aname);
4457 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4459 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4461 mono_array_setref (info->res, info->idx, name);
4466 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4468 MonoImage *img = assembly->assembly->image;
4473 MONO_ARCH_SAVE_REGS;
4475 mono_image_lock (img);
4476 mono_image_init_name_cache (img);
4479 len = g_hash_table_size (img->name_cache);
4480 mono_image_unlock (img);
4482 /*we can't create objects holding the image lock */
4483 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4485 mono_image_lock (img);
4486 /*len might have changed, create a new array*/
4487 if (len != g_hash_table_size (img->name_cache))
4492 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4493 mono_image_unlock (img);
4498 /* move this in some file in mono/util/ */
4500 g_concat_dir_and_file (const char *dir, const char *file)
4502 g_return_val_if_fail (dir != NULL, NULL);
4503 g_return_val_if_fail (file != NULL, NULL);
4506 * If the directory name doesn't have a / on the end, we need
4507 * to add one so we get a proper path to the file
4509 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4510 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4512 return g_strconcat (dir, file, NULL);
4516 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4518 char *n = mono_string_to_utf8 (name);
4519 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4521 guint32 cols [MONO_MANIFEST_SIZE];
4522 guint32 impl, file_idx;
4526 MONO_ARCH_SAVE_REGS;
4528 for (i = 0; i < table->rows; ++i) {
4529 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4530 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4531 if (strcmp (val, n) == 0)
4535 if (i == table->rows)
4538 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4541 * this code should only be called after obtaining the
4542 * ResourceInfo and handling the other cases.
4544 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4545 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4547 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4552 module = assembly->assembly->image;
4554 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4556 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4560 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4562 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4564 guint32 cols [MONO_MANIFEST_SIZE];
4565 guint32 file_cols [MONO_FILE_SIZE];
4569 MONO_ARCH_SAVE_REGS;
4571 n = mono_string_to_utf8 (name);
4572 for (i = 0; i < table->rows; ++i) {
4573 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4574 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4575 if (strcmp (val, n) == 0)
4579 if (i == table->rows)
4582 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4583 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4586 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4587 case MONO_IMPLEMENTATION_FILE:
4588 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4589 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4590 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4591 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4592 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4593 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4596 info->location = RESOURCE_LOCATION_EMBEDDED;
4599 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4600 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4601 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4602 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4603 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4604 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4606 mono_raise_exception (ex);
4608 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4610 /* Obtain info recursively */
4611 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4612 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4615 case MONO_IMPLEMENTATION_EXP_TYPE:
4616 g_assert_not_reached ();
4625 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4627 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4628 MonoArray *result = NULL;
4633 MONO_ARCH_SAVE_REGS;
4635 /* check hash if needed */
4637 n = mono_string_to_utf8 (name);
4638 for (i = 0; i < table->rows; ++i) {
4639 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4640 if (strcmp (val, n) == 0) {
4643 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4644 fn = mono_string_new (mono_object_domain (assembly), n);
4646 return (MonoObject*)fn;
4654 for (i = 0; i < table->rows; ++i) {
4655 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4659 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4662 for (i = 0; i < table->rows; ++i) {
4663 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4664 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4665 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4666 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4671 return (MonoObject*)result;
4675 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4677 MonoDomain *domain = mono_domain_get();
4680 int i, j, file_count = 0;
4681 MonoImage **modules;
4682 guint32 module_count, real_module_count;
4683 MonoTableInfo *table;
4684 guint32 cols [MONO_FILE_SIZE];
4685 MonoImage *image = assembly->assembly->image;
4687 g_assert (image != NULL);
4688 g_assert (!assembly->assembly->dynamic);
4690 table = &image->tables [MONO_TABLE_FILE];
4691 file_count = table->rows;
4693 modules = image->modules;
4694 module_count = image->module_count;
4696 real_module_count = 0;
4697 for (i = 0; i < module_count; ++i)
4699 real_module_count ++;
4701 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4702 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4704 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4706 for (i = 0; i < module_count; ++i)
4708 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4712 for (i = 0; i < file_count; ++i, ++j) {
4713 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4714 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4715 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4717 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4719 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4720 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4722 mono_array_setref (res, j, mono_module_get_object (domain, m));
4729 static MonoReflectionMethod*
4730 ves_icall_GetCurrentMethod (void)
4732 MonoMethod *m = mono_method_get_last_managed ();
4734 while (m->is_inflated)
4735 m = ((MonoMethodInflated*)m)->declaring;
4737 return mono_method_get_object (mono_domain_get (), m, NULL);
4742 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4745 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4746 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4747 //method is inflated, we should inflate it on the other class
4748 MonoGenericContext ctx;
4749 ctx.method_inst = inflated->context.method_inst;
4750 ctx.class_inst = inflated->context.class_inst;
4751 if (klass->generic_class)
4752 ctx.class_inst = klass->generic_class->context.class_inst;
4753 else if (klass->generic_container)
4754 ctx.class_inst = klass->generic_container->context.class_inst;
4755 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4758 mono_class_setup_methods (method->klass);
4759 if (method->klass->exception_type)
4761 for (i = 0; i < method->klass->method.count; ++i) {
4762 if (method->klass->methods [i] == method) {
4767 mono_class_setup_methods (klass);
4768 if (klass->exception_type)
4770 g_assert (offset >= 0 && offset < klass->method.count);
4771 return klass->methods [offset];
4774 static MonoReflectionMethod*
4775 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4779 klass = mono_class_from_mono_type (type);
4780 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4782 if (method->klass != klass) {
4783 method = mono_method_get_equivalent_method (method, klass);
4788 klass = method->klass;
4789 return mono_method_get_object (mono_domain_get (), method, klass);
4792 static MonoReflectionMethod*
4793 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4795 return mono_method_get_object (mono_domain_get (), method, NULL);
4798 static MonoReflectionMethodBody*
4799 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4801 return mono_method_body_get_object (mono_domain_get (), method);
4804 static MonoReflectionAssembly*
4805 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4807 MonoMethod *dest = NULL;
4809 MONO_ARCH_SAVE_REGS;
4811 mono_stack_walk_no_il (get_executing, &dest);
4812 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4816 static MonoReflectionAssembly*
4817 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4819 MonoDomain* domain = mono_domain_get ();
4821 MONO_ARCH_SAVE_REGS;
4823 if (!domain->entry_assembly)
4826 return mono_assembly_get_object (domain, domain->entry_assembly);
4829 static MonoReflectionAssembly*
4830 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4835 MONO_ARCH_SAVE_REGS;
4838 mono_stack_walk_no_il (get_executing, &dest);
4840 mono_stack_walk_no_il (get_caller, &dest);
4843 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4847 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4848 gboolean assembly_qualified)
4850 MonoDomain *domain = mono_object_domain (object);
4851 MonoTypeNameFormat format;
4856 format = assembly_qualified ?
4857 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4858 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4860 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4862 name = mono_type_get_name_full (object->type, format);
4866 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4871 res = mono_string_new (domain, name);
4878 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4880 MonoClass *klass = mono_class_from_mono_type (this->type);
4881 mono_class_init_or_throw (klass);
4882 return mono_security_core_clr_class_level (klass);
4886 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4888 static MonoMethod *create_culture = NULL;
4891 const char *pkey_ptr;
4893 MonoBoolean assembly_ref = 0;
4895 MONO_ARCH_SAVE_REGS;
4897 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4898 aname->major = name->major;
4899 aname->minor = name->minor;
4900 aname->build = name->build;
4901 aname->flags = name->flags;
4902 aname->revision = name->revision;
4903 aname->hashalg = name->hash_alg;
4904 aname->versioncompat = 1; /* SameMachine (default) */
4906 if (by_default_version)
4907 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4910 if (absolute != NULL && *absolute != '\0') {
4911 const gchar *prepend = "file://";
4914 codebase = g_strdup (absolute);
4919 for (i = strlen (codebase) - 1; i >= 0; i--)
4920 if (codebase [i] == '\\')
4923 if (*codebase == '/' && *(codebase + 1) == '/') {
4926 prepend = "file:///";
4930 result = g_strconcat (prepend, codebase, NULL);
4936 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4940 if (!create_culture) {
4941 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4942 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4943 g_assert (create_culture);
4944 mono_method_desc_free (desc);
4947 if (name->culture) {
4948 args [0] = mono_string_new (domain, name->culture);
4949 args [1] = &assembly_ref;
4950 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4953 if (name->public_key) {
4954 pkey_ptr = (char*)name->public_key;
4955 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4957 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4958 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4959 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4960 } else if (default_publickey) {
4961 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4962 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4965 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4966 if (name->public_key_token [0]) {
4970 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4971 p = mono_array_addr (aname->keyToken, char, 0);
4973 for (i = 0, j = 0; i < 8; i++) {
4974 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4975 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4978 } else if (default_token) {
4979 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4984 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4986 MonoDomain *domain = mono_object_domain (assembly);
4987 MonoAssembly *mass = assembly->assembly;
4991 name = g_strdup_printf (
4992 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4994 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4995 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4996 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4997 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4999 res = mono_string_new (domain, name);
5006 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5009 MonoAssembly *mass = assembly->assembly;
5011 MONO_ARCH_SAVE_REGS;
5013 if (g_path_is_absolute (mass->image->name)) {
5014 fill_reflection_assembly_name (mono_object_domain (assembly),
5015 aname, &mass->aname, mass->image->name, TRUE,
5019 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5021 fill_reflection_assembly_name (mono_object_domain (assembly),
5022 aname, &mass->aname, absolute, TRUE, TRUE,
5029 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5032 MonoImageOpenStatus status = MONO_IMAGE_OK;
5035 MonoAssemblyName name;
5038 MONO_ARCH_SAVE_REGS;
5040 filename = mono_string_to_utf8 (fname);
5042 dirname = g_path_get_dirname (filename);
5043 replace_shadow_path (mono_domain_get (), dirname, &filename);
5046 image = mono_image_open (filename, &status);
5052 if (status == MONO_IMAGE_IMAGE_INVALID)
5053 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5055 exc = mono_get_exception_file_not_found2 (NULL, fname);
5056 mono_raise_exception (exc);
5059 res = mono_assembly_fill_assembly_name (image, &name);
5061 mono_image_close (image);
5063 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5066 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5070 mono_image_close (image);
5074 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5075 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5077 MonoBoolean result = FALSE;
5078 MonoDeclSecurityEntry entry;
5080 /* SecurityAction.RequestMinimum */
5081 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5082 *minimum = entry.blob;
5083 *minLength = entry.size;
5086 /* SecurityAction.RequestOptional */
5087 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5088 *optional = entry.blob;
5089 *optLength = entry.size;
5092 /* SecurityAction.RequestRefuse */
5093 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5094 *refused = entry.blob;
5095 *refLength = entry.size;
5103 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5107 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5109 guint32 attrs, visibility;
5111 /* we start the count from 1 because we skip the special type <Module> */
5114 for (i = 1; i < tdef->rows; ++i) {
5115 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5116 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5117 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5121 count = tdef->rows - 1;
5123 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5124 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5126 for (i = 1; i < tdef->rows; ++i) {
5127 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5128 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5129 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5130 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5132 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5134 MonoLoaderError *error;
5137 error = mono_loader_get_last_error ();
5138 g_assert (error != NULL);
5140 ex = mono_loader_error_prepare_exception (error);
5141 mono_array_setref (*exceptions, count, ex);
5143 if (mono_loader_get_last_error ())
5144 mono_loader_clear_error ();
5153 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5155 MonoArray *res = NULL;
5156 MonoArray *exceptions = NULL;
5157 MonoImage *image = NULL;
5158 MonoTableInfo *table = NULL;
5161 int i, len, ex_count;
5163 MONO_ARCH_SAVE_REGS;
5165 domain = mono_object_domain (assembly);
5167 g_assert (!assembly->assembly->dynamic);
5168 image = assembly->assembly->image;
5169 table = &image->tables [MONO_TABLE_FILE];
5170 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5172 /* Append data from all modules in the assembly */
5173 for (i = 0; i < table->rows; ++i) {
5174 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5175 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5178 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5179 /* Append the new types to the end of the array */
5180 if (mono_array_length (res2) > 0) {
5182 MonoArray *res3, *ex3;
5184 len1 = mono_array_length (res);
5185 len2 = mono_array_length (res2);
5187 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5188 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5189 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5192 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5193 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5194 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5201 /* the ReflectionTypeLoadException must have all the types (Types property),
5202 * NULL replacing types which throws an exception. The LoaderException must
5203 * contain all exceptions for NULL items.
5206 len = mono_array_length (res);
5209 for (i = 0; i < len; i++) {
5210 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5214 klass = mono_type_get_class (t->type);
5215 if ((klass != NULL) && klass->exception_type) {
5216 /* keep the class in the list */
5217 list = g_list_append (list, klass);
5218 /* and replace Type with NULL */
5219 mono_array_setref (res, i, NULL);
5226 if (list || ex_count) {
5228 MonoException *exc = NULL;
5229 MonoArray *exl = NULL;
5230 int j, length = g_list_length (list) + ex_count;
5232 mono_loader_clear_error ();
5234 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5235 /* Types for which mono_class_get () succeeded */
5236 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5237 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5238 mono_array_setref (exl, i, exc);
5240 /* Types for which it don't */
5241 for (j = 0; j < mono_array_length (exceptions); ++j) {
5242 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5244 g_assert (i < length);
5245 mono_array_setref (exl, i, exc);
5252 exc = mono_get_exception_reflection_type_load (res, exl);
5253 mono_loader_clear_error ();
5254 mono_raise_exception (exc);
5261 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5263 MonoAssemblyName aname;
5264 MonoDomain *domain = mono_object_domain (name);
5266 gboolean is_version_defined;
5267 gboolean is_token_defined;
5269 aname.public_key = NULL;
5270 val = mono_string_to_utf8 (assname);
5271 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5272 g_free ((guint8*) aname.public_key);
5277 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5278 FALSE, is_token_defined);
5280 mono_assembly_name_free (&aname);
5281 g_free ((guint8*) aname.public_key);
5287 static MonoReflectionType*
5288 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5290 MonoDomain *domain = mono_object_domain (module);
5293 MONO_ARCH_SAVE_REGS;
5295 g_assert (module->image);
5297 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5298 /* These images do not have a global type */
5301 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5302 return mono_type_get_object (domain, &klass->byval_arg);
5306 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5308 /*if (module->image)
5309 mono_image_close (module->image);*/
5313 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5315 MonoDomain *domain = mono_object_domain (module);
5317 MONO_ARCH_SAVE_REGS;
5319 g_assert (module->image);
5320 return mono_string_new (domain, module->image->guid);
5324 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5327 if (module->image && module->image->is_module_handle)
5328 return module->image->raw_data;
5331 return (gpointer) (-1);
5335 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5337 if (image->dynamic) {
5338 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5339 *pe_kind = dyn->pe_kind;
5340 *machine = dyn->machine;
5343 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5344 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5349 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5351 return (image->md_version_major << 16) | (image->md_version_minor);
5355 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5357 MonoArray *exceptions;
5360 MONO_ARCH_SAVE_REGS;
5363 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5365 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5366 for (i = 0; i < mono_array_length (exceptions); ++i) {
5367 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5369 mono_raise_exception (ex);
5376 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5378 guint32 cols [MONO_MEMBERREF_SIZE];
5380 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5381 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5382 mono_metadata_decode_blob_size (sig, &sig);
5383 return (*sig != 0x6);
5387 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5390 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5391 mono_array_addr (type_args, MonoType*, 0));
5393 context->class_inst = NULL;
5395 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5396 mono_array_addr (method_args, MonoType*, 0));
5398 context->method_inst = NULL;
5402 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5405 int table = mono_metadata_token_table (token);
5406 int index = mono_metadata_token_index (token);
5407 MonoGenericContext context;
5409 *error = ResolveTokenError_Other;
5411 /* Validate token */
5412 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5413 (table != MONO_TABLE_TYPESPEC)) {
5414 *error = ResolveTokenError_BadTable;
5418 if (image->dynamic) {
5419 if (type_args || method_args)
5420 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5421 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5424 return &klass->byval_arg;
5427 if ((index <= 0) || (index > image->tables [table].rows)) {
5428 *error = ResolveTokenError_OutOfRange;
5432 init_generic_context_from_args (&context, type_args, method_args);
5433 klass = mono_class_get_full (image, token, &context);
5435 if (mono_loader_get_last_error ())
5436 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5439 return &klass->byval_arg;
5445 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5447 int table = mono_metadata_token_table (token);
5448 int index = mono_metadata_token_index (token);
5449 MonoGenericContext context;
5452 *error = ResolveTokenError_Other;
5454 /* Validate token */
5455 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5456 (table != MONO_TABLE_MEMBERREF)) {
5457 *error = ResolveTokenError_BadTable;
5461 if (image->dynamic) {
5462 if (type_args || method_args)
5463 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5464 /* FIXME: validate memberref token type */
5465 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5468 if ((index <= 0) || (index > image->tables [table].rows)) {
5469 *error = ResolveTokenError_OutOfRange;
5472 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5473 *error = ResolveTokenError_BadTable;
5477 init_generic_context_from_args (&context, type_args, method_args);
5478 method = mono_get_method_full (image, token, NULL, &context);
5480 if (mono_loader_get_last_error ())
5481 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5487 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5489 int index = mono_metadata_token_index (token);
5491 *error = ResolveTokenError_Other;
5493 /* Validate token */
5494 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5495 *error = ResolveTokenError_BadTable;
5500 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5502 if ((index <= 0) || (index >= image->heap_us.size)) {
5503 *error = ResolveTokenError_OutOfRange;
5507 /* FIXME: What to do if the index points into the middle of a string ? */
5509 return mono_ldstr (mono_domain_get (), image, index);
5512 static MonoClassField*
5513 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5516 int table = mono_metadata_token_table (token);
5517 int index = mono_metadata_token_index (token);
5518 MonoGenericContext context;
5519 MonoClassField *field;
5521 *error = ResolveTokenError_Other;
5523 /* Validate token */
5524 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5525 *error = ResolveTokenError_BadTable;
5529 if (image->dynamic) {
5530 if (type_args || method_args)
5531 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5532 /* FIXME: validate memberref token type */
5533 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5536 if ((index <= 0) || (index > image->tables [table].rows)) {
5537 *error = ResolveTokenError_OutOfRange;
5540 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5541 *error = ResolveTokenError_BadTable;
5545 init_generic_context_from_args (&context, type_args, method_args);
5546 field = mono_field_from_token (image, token, &klass, &context);
5548 if (mono_loader_get_last_error ())
5549 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5556 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5558 int table = mono_metadata_token_table (token);
5560 *error = ResolveTokenError_Other;
5563 case MONO_TABLE_TYPEDEF:
5564 case MONO_TABLE_TYPEREF:
5565 case MONO_TABLE_TYPESPEC: {
5566 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5568 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5572 case MONO_TABLE_METHOD:
5573 case MONO_TABLE_METHODSPEC: {
5574 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5576 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5580 case MONO_TABLE_FIELD: {
5581 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5583 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5587 case MONO_TABLE_MEMBERREF:
5588 if (mono_metadata_memberref_is_method (image, token)) {
5589 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5591 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5596 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5598 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5605 *error = ResolveTokenError_BadTable;
5612 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5614 int table = mono_metadata_token_table (token);
5615 int idx = mono_metadata_token_index (token);
5616 MonoTableInfo *tables = image->tables;
5621 *error = ResolveTokenError_OutOfRange;
5623 /* FIXME: Support other tables ? */
5624 if (table != MONO_TABLE_STANDALONESIG)
5630 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5633 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5635 ptr = mono_metadata_blob_heap (image, sig);
5636 len = mono_metadata_decode_blob_size (ptr, &ptr);
5638 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5639 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5643 static MonoReflectionType*
5644 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5647 int isbyref = 0, rank;
5648 char *str = mono_string_to_utf8 (smodifiers);
5651 MONO_ARCH_SAVE_REGS;
5653 klass = mono_class_from_mono_type (tb->type.type);
5655 /* logic taken from mono_reflection_parse_type(): keep in sync */
5659 if (isbyref) { /* only one level allowed by the spec */
5666 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5669 klass = mono_ptr_class_get (&klass->byval_arg);
5670 mono_class_init (klass);
5681 else if (*p != '*') { /* '*' means unknown lower bound */
5692 klass = mono_array_class_get (klass, rank);
5693 mono_class_init (klass);
5700 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5704 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5709 MONO_ARCH_SAVE_REGS;
5712 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5718 check_for_invalid_type (MonoClass *klass)
5722 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5725 name = mono_type_get_full_name (klass);
5726 str = mono_string_new (mono_domain_get (), name);
5728 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5731 static MonoReflectionType *
5732 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5734 MonoClass *klass, *aklass;
5736 MONO_ARCH_SAVE_REGS;
5738 klass = mono_class_from_mono_type (type->type);
5739 mono_class_init_or_throw (klass);
5740 check_for_invalid_type (klass);
5742 if (rank == 0) //single dimentional array
5743 aklass = mono_array_class_get (klass, 1);
5745 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5747 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5750 static MonoReflectionType *
5751 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5755 MONO_ARCH_SAVE_REGS;
5757 klass = mono_class_from_mono_type (type->type);
5758 mono_class_init_or_throw (klass);
5759 check_for_invalid_type (klass);
5761 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5764 static MonoReflectionType *
5765 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5767 MonoClass *klass, *pklass;
5769 klass = mono_class_from_mono_type (type->type);
5770 mono_class_init_or_throw (klass);
5771 check_for_invalid_type (klass);
5773 pklass = mono_ptr_class_get (type->type);
5775 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5779 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5780 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5782 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5783 MonoObject *delegate;
5785 MonoMethod *method = info->method;
5787 MONO_ARCH_SAVE_REGS;
5789 mono_class_init_or_throw (delegate_class);
5791 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5793 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5794 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5798 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5800 if (method->dynamic) {
5801 /* Creating a trampoline would leak memory */
5802 func = mono_compile_method (method);
5804 func = mono_create_ftnptr (mono_domain_get (),
5805 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5808 mono_delegate_ctor_with_method (delegate, target, func, method);
5814 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5816 /* Reset the invoke impl to the default one */
5817 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5821 * Magic number to convert a time which is relative to
5822 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5824 #define EPOCH_ADJUST ((guint64)62135596800LL)
5827 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5829 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5832 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5834 convert_to_absolute_date(SYSTEMTIME *date)
5836 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5837 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5838 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5839 /* from the calendar FAQ */
5840 int a = (14 - date->wMonth) / 12;
5841 int y = date->wYear - a;
5842 int m = date->wMonth + 12 * a - 2;
5843 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5845 /* d is now the day of the week for the first of the month (0 == Sunday) */
5847 int day_of_week = date->wDayOfWeek;
5849 /* set day_in_month to the first day in the month which falls on day_of_week */
5850 int day_in_month = 1 + (day_of_week - d);
5851 if (day_in_month <= 0)
5854 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5855 date->wDay = day_in_month + (date->wDay - 1) * 7;
5856 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5863 * Return's the offset from GMT of a local time.
5865 * tm is a local time
5866 * t is the same local time as seconds.
5869 gmt_offset(struct tm *tm, time_t t)
5871 #if defined (HAVE_TM_GMTOFF)
5872 return tm->tm_gmtoff;
5877 g.tm_isdst = tm->tm_isdst;
5879 return (int)difftime(t, t2);
5884 * This is heavily based on zdump.c from glibc 2.2.
5886 * * data[0]: start of daylight saving time (in DateTime ticks).
5887 * * data[1]: end of daylight saving time (in DateTime ticks).
5888 * * data[2]: utcoffset (in TimeSpan ticks).
5889 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5890 * * name[0]: name of this timezone when not daylight saving.
5891 * * name[1]: name of this timezone when daylight saving.
5893 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5894 * the class library allows years between 1 and 9999.
5896 * Returns true on success and zero on failure.
5899 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5902 MonoDomain *domain = mono_domain_get ();
5903 struct tm start, tt;
5907 int is_daylight = 0, day;
5910 MONO_ARCH_SAVE_REGS;
5912 MONO_CHECK_ARG_NULL (data);
5913 MONO_CHECK_ARG_NULL (names);
5915 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5916 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5919 * no info is better than crashing: we'll need our own tz data
5920 * to make this work properly, anyway. The range is probably
5921 * reduced to 1970 .. 2037 because that is what mktime is
5922 * guaranteed to support (we get into an infinite loop
5926 memset (&start, 0, sizeof (start));
5929 start.tm_year = year-1900;
5931 t = mktime (&start);
5933 if ((year < 1970) || (year > 2037) || (t == -1)) {
5935 tt = *localtime (&t);
5936 strftime (tzone, sizeof (tzone), "%Z", &tt);
5937 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5938 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5942 gmtoff = gmt_offset (&start, t);
5944 /* For each day of the year, calculate the tm_gmtoff. */
5945 for (day = 0; day < 365; day++) {
5948 tt = *localtime (&t);
5950 /* Daylight saving starts or ends here. */
5951 if (gmt_offset (&tt, t) != gmtoff) {
5955 /* Try to find the exact hour when daylight saving starts/ends. */
5959 tt1 = *localtime (&t1);
5960 } while (gmt_offset (&tt1, t1) != gmtoff);
5962 /* Try to find the exact minute when daylight saving starts/ends. */
5965 tt1 = *localtime (&t1);
5966 } while (gmt_offset (&tt1, t1) == gmtoff);
5968 strftime (tzone, sizeof (tzone), "%Z", &tt);
5970 /* Write data, if we're already in daylight saving, we're done. */
5972 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5973 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5976 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5977 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5981 /* This is only set once when we enter daylight saving. */
5982 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5983 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5985 gmtoff = gmt_offset (&tt, t);
5990 strftime (tzone, sizeof (tzone), "%Z", &tt);
5991 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5992 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5993 mono_array_set ((*data), gint64, 0, 0);
5994 mono_array_set ((*data), gint64, 1, 0);
5995 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5996 mono_array_set ((*data), gint64, 3, 0);
6001 MonoDomain *domain = mono_domain_get ();
6002 TIME_ZONE_INFORMATION tz_info;
6007 tz_id = GetTimeZoneInformation (&tz_info);
6008 if (tz_id == TIME_ZONE_ID_INVALID)
6011 MONO_CHECK_ARG_NULL (data);
6012 MONO_CHECK_ARG_NULL (names);
6014 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6015 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6017 for (i = 0; i < 32; ++i)
6018 if (!tz_info.DaylightName [i])
6020 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6021 for (i = 0; i < 32; ++i)
6022 if (!tz_info.StandardName [i])
6024 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6026 if ((year <= 1601) || (year > 30827)) {
6028 * According to MSDN, the MS time functions can't handle dates outside
6034 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6035 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6036 tz_info.StandardDate.wYear = year;
6037 convert_to_absolute_date(&tz_info.StandardDate);
6038 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6043 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6044 tz_info.DaylightDate.wYear = year;
6045 convert_to_absolute_date(&tz_info.DaylightDate);
6046 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6051 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6053 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6054 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6061 ves_icall_System_Object_obj_address (MonoObject *this)
6063 MONO_ARCH_SAVE_REGS;
6070 static inline gint32
6071 mono_array_get_byte_length (MonoArray *array)
6077 klass = array->obj.vtable->klass;
6079 if (array->bounds == NULL)
6080 length = array->max_length;
6083 for (i = 0; i < klass->rank; ++ i)
6084 length *= array->bounds [i].length;
6087 switch (klass->element_class->byval_arg.type) {
6090 case MONO_TYPE_BOOLEAN:
6094 case MONO_TYPE_CHAR:
6102 return length * sizeof (gpointer);
6113 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6115 MONO_ARCH_SAVE_REGS;
6117 return mono_array_get_byte_length (array);
6121 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6123 MONO_ARCH_SAVE_REGS;
6125 return mono_array_get (array, gint8, idx);
6129 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6131 MONO_ARCH_SAVE_REGS;
6133 mono_array_set (array, gint8, idx, value);
6137 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6139 guint8 *src_buf, *dest_buf;
6141 MONO_ARCH_SAVE_REGS;
6143 /* watch out for integer overflow */
6144 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6147 src_buf = (guint8 *)src->vector + src_offset;
6148 dest_buf = (guint8 *)dest->vector + dest_offset;
6151 memcpy (dest_buf, src_buf, count);
6153 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6159 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6161 MonoDomain *domain = mono_object_domain (this);
6163 MonoRealProxy *rp = ((MonoRealProxy *)this);
6164 MonoTransparentProxy *tp;
6168 MONO_ARCH_SAVE_REGS;
6170 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6171 tp = (MonoTransparentProxy*) res;
6173 MONO_OBJECT_SETREF (tp, rp, rp);
6174 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6175 klass = mono_class_from_mono_type (type);
6177 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6178 tp->remote_class = mono_remote_class (domain, class_name, klass);
6180 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6184 static MonoReflectionType *
6185 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6187 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6190 /* System.Environment */
6193 ves_icall_System_Environment_get_UserName (void)
6195 MONO_ARCH_SAVE_REGS;
6197 /* using glib is more portable */
6198 return mono_string_new (mono_domain_get (), g_get_user_name ());
6203 ves_icall_System_Environment_get_MachineName (void)
6205 #if defined (HOST_WIN32)
6210 len = MAX_COMPUTERNAME_LENGTH + 1;
6211 buf = g_new (gunichar2, len);
6214 if (GetComputerName (buf, (PDWORD) &len))
6215 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6219 #elif !defined(DISABLE_SOCKETS)
6223 if (gethostname (buf, sizeof (buf)) == 0)
6224 result = mono_string_new (mono_domain_get (), buf);
6230 return mono_string_new (mono_domain_get (), "mono");
6235 ves_icall_System_Environment_get_Platform (void)
6237 #if defined (TARGET_WIN32)
6240 #elif defined(__MACH__)
6243 // For compatibility with our client code, this will be 4 for a while.
6244 // We will eventually move to 6 to match .NET, but it requires all client
6245 // code to be updated and the documentation everywhere to be updated
6256 ves_icall_System_Environment_get_NewLine (void)
6258 MONO_ARCH_SAVE_REGS;
6260 #if defined (HOST_WIN32)
6261 return mono_string_new (mono_domain_get (), "\r\n");
6263 return mono_string_new (mono_domain_get (), "\n");
6268 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6273 MONO_ARCH_SAVE_REGS;
6278 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6279 value = g_getenv (utf8_name);
6286 return mono_string_new (mono_domain_get (), value);
6290 * There is no standard way to get at environ.
6293 #ifndef __MINGW32_VERSION
6294 #if defined(__APPLE__) && !defined (__arm__)
6295 /* Apple defines this in crt_externs.h but doesn't provide that header for
6296 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6297 * in fact exist on all implementations (so far)
6299 gchar ***_NSGetEnviron(void);
6300 #define environ (*_NSGetEnviron())
6309 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6320 env_strings = GetEnvironmentStrings();
6323 env_string = env_strings;
6324 while (*env_string != '\0') {
6325 /* weird case that MS seems to skip */
6326 if (*env_string != '=')
6328 while (*env_string != '\0')
6334 domain = mono_domain_get ();
6335 names = mono_array_new (domain, mono_defaults.string_class, n);
6339 env_string = env_strings;
6340 while (*env_string != '\0') {
6341 /* weird case that MS seems to skip */
6342 if (*env_string != '=') {
6343 equal_str = wcschr(env_string, '=');
6344 g_assert(equal_str);
6345 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6346 mono_array_setref (names, n, str);
6349 while (*env_string != '\0')
6354 FreeEnvironmentStrings (env_strings);
6366 MONO_ARCH_SAVE_REGS;
6369 for (e = environ; *e != 0; ++ e)
6372 domain = mono_domain_get ();
6373 names = mono_array_new (domain, mono_defaults.string_class, n);
6376 for (e = environ; *e != 0; ++ e) {
6377 parts = g_strsplit (*e, "=", 2);
6379 str = mono_string_new (domain, *parts);
6380 mono_array_setref (names, n, str);
6393 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6395 #if !GLIB_CHECK_VERSION(2,4,0)
6396 #define g_setenv(a,b,c) setenv(a,b,c)
6397 #define g_unsetenv(a) unsetenv(a)
6401 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6406 gunichar2 *utf16_name, *utf16_value;
6408 gchar *utf8_name, *utf8_value;
6411 MONO_ARCH_SAVE_REGS;
6414 utf16_name = mono_string_to_utf16 (name);
6415 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6416 SetEnvironmentVariable (utf16_name, NULL);
6417 g_free (utf16_name);
6421 utf16_value = mono_string_to_utf16 (value);
6423 SetEnvironmentVariable (utf16_name, utf16_value);
6425 g_free (utf16_name);
6426 g_free (utf16_value);
6428 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6430 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6431 g_unsetenv (utf8_name);
6436 utf8_value = mono_string_to_utf8_checked (value, &error);
6437 if (!mono_error_ok (&error)) {
6439 mono_error_raise_exception (&error);
6441 g_setenv (utf8_name, utf8_value, TRUE);
6444 g_free (utf8_value);
6449 ves_icall_System_Environment_Exit (int result)
6451 MONO_ARCH_SAVE_REGS;
6453 mono_threads_set_shutting_down ();
6455 mono_runtime_set_shutting_down ();
6457 /* This will kill the tp threads which cannot be suspended */
6458 mono_thread_pool_cleanup ();
6460 /* Suspend all managed threads since the runtime is going away */
6461 mono_thread_suspend_all_other_threads ();
6463 mono_runtime_quit ();
6465 /* we may need to do some cleanup here... */
6470 ves_icall_System_Environment_GetGacPath (void)
6472 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6476 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6478 #if defined (HOST_WIN32)
6479 #ifndef CSIDL_FLAG_CREATE
6480 #define CSIDL_FLAG_CREATE 0x8000
6483 WCHAR path [MAX_PATH];
6484 /* Create directory if no existing */
6485 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6489 return mono_string_new_utf16 (mono_domain_get (), path, len);
6492 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6494 return mono_string_new (mono_domain_get (), "");
6498 ves_icall_System_Environment_GetLogicalDrives (void)
6500 gunichar2 buf [128], *ptr, *dname;
6502 guint initial_size = 127, size = 128;
6505 MonoString *drivestr;
6506 MonoDomain *domain = mono_domain_get ();
6509 MONO_ARCH_SAVE_REGS;
6514 while (size > initial_size) {
6515 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6516 if (size > initial_size) {
6519 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6520 initial_size = size;
6534 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6539 while (*u16) { u16++; len ++; }
6540 drivestr = mono_string_new_utf16 (domain, dname, len);
6541 mono_array_setref (result, ndrives++, drivestr);
6552 ves_icall_System_Environment_InternalGetHome (void)
6554 MONO_ARCH_SAVE_REGS;
6556 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6559 static const char *encodings [] = {
6561 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6562 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6563 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6565 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6566 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6567 "x_unicode_2_0_utf_7",
6569 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6570 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6572 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6575 "unicodefffe", "utf_16be",
6582 * Returns the internal codepage, if the value of "int_code_page" is
6583 * 1 at entry, and we can not compute a suitable code page number,
6584 * returns the code page as a string
6587 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6592 char *codepage = NULL;
6594 int want_name = *int_code_page;
6597 *int_code_page = -1;
6598 MONO_ARCH_SAVE_REGS;
6600 g_get_charset (&cset);
6601 c = codepage = strdup (cset);
6602 for (c = codepage; *c; c++){
6603 if (isascii (*c) && isalpha (*c))
6608 /* g_print ("charset: %s\n", cset); */
6610 /* handle some common aliases */
6613 for (i = 0; p != 0; ){
6614 if ((gssize) p < 7){
6616 p = encodings [++i];
6619 if (strcmp (p, codepage) == 0){
6620 *int_code_page = code;
6623 p = encodings [++i];
6626 if (strstr (codepage, "utf_8") != NULL)
6627 *int_code_page |= 0x10000000;
6630 if (want_name && *int_code_page == -1)
6631 return mono_string_new (mono_domain_get (), cset);
6637 ves_icall_System_Environment_get_HasShutdownStarted (void)
6639 if (mono_runtime_is_shutting_down ())
6642 if (mono_domain_is_unloading (mono_domain_get ()))
6649 ves_icall_System_Environment_BroadcastSettingChange (void)
6652 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6657 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6658 MonoReflectionMethod *method,
6659 MonoArray *out_args)
6661 MONO_ARCH_SAVE_REGS;
6663 mono_message_init (mono_object_domain (this), this, method, out_args);
6667 ves_icall_IsTransparentProxy (MonoObject *proxy)
6669 MONO_ARCH_SAVE_REGS;
6674 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6680 static MonoReflectionMethod *
6681 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6682 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6686 MonoMethod **vtable;
6687 MonoMethod *res = NULL;
6689 MONO_CHECK_ARG_NULL (rtype);
6690 MONO_CHECK_ARG_NULL (rmethod);
6692 method = rmethod->method;
6693 klass = mono_class_from_mono_type (rtype->type);
6694 mono_class_init_or_throw (klass);
6696 if (MONO_CLASS_IS_INTERFACE (klass))
6699 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6702 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6703 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6709 mono_class_setup_vtable (klass);
6710 vtable = klass->vtable;
6712 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6713 gboolean variance_used = FALSE;
6714 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6715 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6717 res = vtable [offs + method->slot];
6719 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6722 if (method->slot != -1)
6723 res = vtable [method->slot];
6729 return mono_method_get_object (mono_domain_get (), res, NULL);
6733 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6738 MONO_ARCH_SAVE_REGS;
6740 klass = mono_class_from_mono_type (type->type);
6741 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6743 if (enable) vtable->remote = 1;
6744 else vtable->remote = 0;
6748 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6753 MONO_ARCH_SAVE_REGS;
6755 domain = mono_object_domain (type);
6756 klass = mono_class_from_mono_type (type->type);
6757 mono_class_init_or_throw (klass);
6759 if (klass->rank >= 1) {
6760 g_assert (klass->rank == 1);
6761 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6763 /* Bypass remoting object creation check */
6764 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6769 ves_icall_System_IO_get_temp_path (void)
6771 MONO_ARCH_SAVE_REGS;
6773 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6776 #ifndef PLATFORM_NO_DRIVEINFO
6778 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6779 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6783 ULARGE_INTEGER wapi_free_bytes_avail;
6784 ULARGE_INTEGER wapi_total_number_of_bytes;
6785 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6787 MONO_ARCH_SAVE_REGS;
6789 *error = ERROR_SUCCESS;
6790 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6791 &wapi_total_number_of_free_bytes);
6794 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6795 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6796 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6798 *free_bytes_avail = 0;
6799 *total_number_of_bytes = 0;
6800 *total_number_of_free_bytes = 0;
6801 *error = GetLastError ();
6808 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6810 MONO_ARCH_SAVE_REGS;
6812 return GetDriveType (mono_string_chars (root_path_name));
6817 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6819 MONO_ARCH_SAVE_REGS;
6821 return mono_compile_method (method);
6825 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6830 MONO_ARCH_SAVE_REGS;
6832 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6834 #if defined (HOST_WIN32)
6835 /* Avoid mixing '/' and '\\' */
6838 for (i = strlen (path) - 1; i >= 0; i--)
6839 if (path [i] == '/')
6843 mcpath = mono_string_new (mono_domain_get (), path);
6850 get_bundled_app_config (void)
6852 const gchar *app_config;
6859 MONO_ARCH_SAVE_REGS;
6861 domain = mono_domain_get ();
6862 file = domain->setup->configuration_file;
6866 // Retrieve config file and remove the extension
6867 config_file = mono_string_to_utf8 (file);
6868 len = strlen (config_file) - strlen (".config");
6869 module = g_malloc0 (len + 1);
6870 memcpy (module, config_file, len);
6871 // Get the config file from the module name
6872 app_config = mono_config_string_for_assembly_file (module);
6875 g_free (config_file);
6880 return mono_string_new (mono_domain_get (), app_config);
6884 get_bundled_machine_config (void)
6886 const gchar *machine_config;
6888 MONO_ARCH_SAVE_REGS;
6890 machine_config = mono_get_machine_config ();
6892 if (!machine_config)
6895 return mono_string_new (mono_domain_get (), machine_config);
6899 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6904 MONO_ARCH_SAVE_REGS;
6906 path = g_path_get_dirname (mono_get_config_dir ());
6908 #if defined (HOST_WIN32)
6909 /* Avoid mixing '/' and '\\' */
6912 for (i = strlen (path) - 1; i >= 0; i--)
6913 if (path [i] == '/')
6917 ipath = mono_string_new (mono_domain_get (), path);
6924 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6926 MonoPEResourceDataEntry *entry;
6929 MONO_ARCH_SAVE_REGS;
6931 if (!assembly || !result || !size)
6936 image = assembly->assembly->image;
6937 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6941 *result = mono_image_rva_map (image, entry->rde_data_offset);
6946 *size = entry->rde_size;
6952 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6954 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6958 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6960 #if defined (HOST_WIN32)
6961 OutputDebugString (mono_string_chars (message));
6963 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6967 /* Only used for value types */
6969 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6974 MONO_ARCH_SAVE_REGS;
6976 domain = mono_object_domain (type);
6977 klass = mono_class_from_mono_type (type->type);
6978 mono_class_init_or_throw (klass);
6980 if (mono_class_is_nullable (klass))
6981 /* No arguments -> null */
6984 return mono_object_new (domain, klass);
6987 static MonoReflectionMethod *
6988 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6990 MonoClass *klass, *parent;
6991 MonoMethod *method = m->method;
6992 MonoMethod *result = NULL;
6994 MONO_ARCH_SAVE_REGS;
6996 if (method->klass == NULL)
6999 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7000 MONO_CLASS_IS_INTERFACE (method->klass) ||
7001 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7004 klass = method->klass;
7005 if (klass->generic_class)
7006 klass = klass->generic_class->container_class;
7009 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7010 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7011 mono_class_setup_vtable (parent);
7012 if (parent->vtable_size <= method->slot)
7017 klass = klass->parent;
7022 if (klass == method->klass)
7025 /*This is possible if definition == FALSE.
7026 * Do it here to be really sure we don't read invalid memory.
7028 if (method->slot >= klass->vtable_size)
7031 result = klass->vtable [method->slot];
7032 if (result == NULL) {
7033 /* It is an abstract method */
7034 gpointer iter = NULL;
7035 while ((result = mono_class_get_methods (klass, &iter)))
7036 if (result->slot == method->slot)
7043 return mono_method_get_object (mono_domain_get (), result, NULL);
7047 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7049 MonoMethod *method = m->method;
7051 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7056 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7058 MONO_ARCH_SAVE_REGS;
7060 iter->sig = *(MonoMethodSignature**)argsp;
7062 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7063 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7066 /* FIXME: it's not documented what start is exactly... */
7070 iter->args = argsp + sizeof (gpointer);
7072 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7074 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7078 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7080 guint32 i, arg_size;
7083 MONO_ARCH_SAVE_REGS;
7085 i = iter->sig->sentinelpos + iter->next_arg;
7087 g_assert (i < iter->sig->param_count);
7089 res.type = iter->sig->params [i];
7090 res.klass = mono_class_from_mono_type (res.type);
7091 res.value = iter->args;
7092 arg_size = mono_type_stack_size (res.type, &align);
7093 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7094 if (arg_size <= sizeof (gpointer)) {
7096 int padding = arg_size - mono_type_size (res.type, &dummy);
7097 res.value = (guint8*)res.value + padding;
7100 iter->args = (char*)iter->args + arg_size;
7103 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7109 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7111 guint32 i, arg_size;
7114 MONO_ARCH_SAVE_REGS;
7116 i = iter->sig->sentinelpos + iter->next_arg;
7118 g_assert (i < iter->sig->param_count);
7120 while (i < iter->sig->param_count) {
7121 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7123 res.type = iter->sig->params [i];
7124 res.klass = mono_class_from_mono_type (res.type);
7125 /* FIXME: endianess issue... */
7126 res.value = iter->args;
7127 arg_size = mono_type_stack_size (res.type, &align);
7128 iter->args = (char*)iter->args + arg_size;
7130 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7133 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7142 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7145 MONO_ARCH_SAVE_REGS;
7147 i = iter->sig->sentinelpos + iter->next_arg;
7149 g_assert (i < iter->sig->param_count);
7151 return iter->sig->params [i];
7155 mono_TypedReference_ToObject (MonoTypedRef tref)
7157 MONO_ARCH_SAVE_REGS;
7159 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7160 MonoObject** objp = tref.value;
7164 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7168 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7170 MONO_ARCH_SAVE_REGS;
7172 if (MONO_TYPE_IS_REFERENCE (type)) {
7173 MonoObject** objp = value;
7177 return mono_value_box (mono_domain_get (), klass, value);
7181 prelink_method (MonoMethod *method)
7183 const char *exc_class, *exc_arg;
7184 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7186 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7188 mono_raise_exception(
7189 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7191 /* create the wrapper, too? */
7195 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7197 MONO_ARCH_SAVE_REGS;
7198 prelink_method (method->method);
7202 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7204 MonoClass *klass = mono_class_from_mono_type (type->type);
7206 gpointer iter = NULL;
7207 MONO_ARCH_SAVE_REGS;
7209 mono_class_init_or_throw (klass);
7211 while ((m = mono_class_get_methods (klass, &iter)))
7215 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7217 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7218 gint32 const **exponents,
7219 gunichar2 const **digitLowerTable,
7220 gunichar2 const **digitUpperTable,
7221 gint64 const **tenPowersList,
7222 gint32 const **decHexDigits)
7224 *mantissas = Formatter_MantissaBitsTable;
7225 *exponents = Formatter_TensExponentTable;
7226 *digitLowerTable = Formatter_DigitLowerTable;
7227 *digitUpperTable = Formatter_DigitUpperTable;
7228 *tenPowersList = Formatter_TenPowersList;
7229 *decHexDigits = Formatter_DecHexDigits;
7232 /* These parameters are "readonly" in corlib/System/Char.cs */
7234 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7235 guint8 const **numeric_data,
7236 gdouble const **numeric_data_values,
7237 guint16 const **to_lower_data_low,
7238 guint16 const **to_lower_data_high,
7239 guint16 const **to_upper_data_low,
7240 guint16 const **to_upper_data_high)
7242 *category_data = CategoryData;
7243 *numeric_data = NumericData;
7244 *numeric_data_values = NumericDataValues;
7245 *to_lower_data_low = ToLowerDataLow;
7246 *to_lower_data_high = ToLowerDataHigh;
7247 *to_upper_data_low = ToUpperDataLow;
7248 *to_upper_data_high = ToUpperDataHigh;
7252 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7254 return method->method->token;
7258 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7259 * and avoid useless allocations.
7262 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7266 for (i = 0; i < type->num_mods; ++i) {
7267 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7272 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7274 for (i = 0; i < type->num_mods; ++i) {
7275 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7276 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7277 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7285 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7287 MonoType *type = param->ClassImpl->type;
7288 MonoClass *member_class = mono_object_class (param->MemberImpl);
7289 MonoMethod *method = NULL;
7292 MonoMethodSignature *sig;
7294 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7295 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7296 method = rmethod->method;
7297 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7298 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7299 if (!(method = prop->property->get))
7300 method = prop->property->set;
7303 char *type_name = mono_type_get_full_name (member_class);
7304 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7305 MonoException *ex = mono_get_exception_not_supported (msg);
7308 mono_raise_exception (ex);
7311 image = method->klass->image;
7312 pos = param->PositionImpl;
7313 sig = mono_method_signature (method);
7317 type = sig->params [pos];
7319 return type_array_from_modifiers (image, type, optional);
7323 get_property_type (MonoProperty *prop)
7325 MonoMethodSignature *sig;
7327 sig = mono_method_signature (prop->get);
7329 } else if (prop->set) {
7330 sig = mono_method_signature (prop->set);
7331 return sig->params [sig->param_count - 1];
7337 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7339 MonoType *type = get_property_type (property->property);
7340 MonoImage *image = property->klass->image;
7344 return type_array_from_modifiers (image, type, optional);
7348 *Construct a MonoType suited to be used to decode a constant blob object.
7350 * @type is the target type which will be constructed
7351 * @blob_type is the blob type, for example, that comes from the constant table
7352 * @real_type is the expected constructed type.
7355 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7357 type->type = blob_type;
7358 type->data.klass = NULL;
7359 if (blob_type == MONO_TYPE_CLASS)
7360 type->data.klass = mono_defaults.object_class;
7361 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7362 /* For enums, we need to use the base type */
7363 type->type = MONO_TYPE_VALUETYPE;
7364 type->data.klass = mono_class_from_mono_type (real_type);
7366 type->data.klass = mono_class_from_mono_type (real_type);
7370 property_info_get_default_value (MonoReflectionProperty *property)
7373 MonoProperty *prop = property->property;
7374 MonoType *type = get_property_type (prop);
7375 MonoDomain *domain = mono_object_domain (property);
7376 MonoTypeEnum def_type;
7377 const char *def_value;
7380 mono_class_init (prop->parent);
7382 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7383 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7385 def_value = mono_class_get_property_default_value (prop, &def_type);
7387 mono_type_from_blob_type (&blob_type, def_type, type);
7388 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7394 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7396 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7397 MonoCustomAttrInfo *cinfo;
7400 mono_class_init_or_throw (attr_class);
7402 cinfo = mono_reflection_get_custom_attrs_info (obj);
7405 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7407 mono_custom_attrs_free (cinfo);
7412 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7414 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7418 mono_class_init_or_throw (attr_class);
7420 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7422 if (mono_loader_get_last_error ()) {
7423 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7424 g_assert_not_reached ();
7433 ves_icall_Mono_Runtime_GetDisplayName (void)
7436 MonoString *display_name;
7438 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7439 display_name = mono_string_new (mono_domain_get (), info);
7441 return display_name;
7445 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7447 MonoString *message;
7451 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7452 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7455 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7457 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7465 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7466 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7467 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7468 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7469 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7470 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7471 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7472 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7476 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7481 gunichar2 last, prev_last, prev2_last;
7489 last = prev_last = 0, prev2_last = 0;
7490 for (i = 0; i < ilength; i++) {
7492 if (c >= sizeof (dbase64)) {
7493 exc = mono_exception_from_name_msg (mono_get_corlib (),
7494 "System", "FormatException",
7495 "Invalid character found.");
7496 mono_raise_exception (exc);
7497 } else if (isspace (c)) {
7500 prev2_last = prev_last;
7506 olength = ilength - ignored;
7508 if (allowWhitespaceOnly && olength == 0) {
7509 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7512 if ((olength & 3) != 0 || olength <= 0) {
7513 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7514 "FormatException", "Invalid length.");
7515 mono_raise_exception (exc);
7518 if (prev2_last == '=') {
7519 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7520 mono_raise_exception (exc);
7523 olength = (olength * 3) / 4;
7527 if (prev_last == '=')
7530 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7531 res_ptr = mono_array_addr (result, guchar, 0);
7532 for (i = 0; i < ilength; ) {
7535 for (k = 0; k < 4 && i < ilength;) {
7541 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7542 exc = mono_exception_from_name_msg (mono_get_corlib (),
7543 "System", "FormatException",
7544 "Invalid character found.");
7545 mono_raise_exception (exc);
7550 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7552 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7554 *res_ptr++ = (b [2] << 6) | b [3];
7556 while (i < ilength && isspace (start [i]))
7564 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7566 MONO_ARCH_SAVE_REGS;
7568 return base64_to_byte_array (mono_string_chars (str),
7569 mono_string_length (str), allowWhitespaceOnly);
7573 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7575 MONO_ARCH_SAVE_REGS;
7577 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7581 #define ICALL_TYPE(id,name,first)
7582 #define ICALL(id,name,func) Icall_ ## id,
7585 #include "metadata/icall-def.h"
7591 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7592 #define ICALL(id,name,func)
7594 #include "metadata/icall-def.h"
7600 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7601 #define ICALL(id,name,func)
7603 guint16 first_icall;
7606 static const IcallTypeDesc
7607 icall_type_descs [] = {
7608 #include "metadata/icall-def.h"
7612 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7615 #define ICALL_TYPE(id,name,first)
7618 #ifdef HAVE_ARRAY_ELEM_INIT
7619 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7620 #define MSGSTRFIELD1(line) str##line
7622 static const struct msgstrtn_t {
7623 #define ICALL(id,name,func)
7625 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7626 #include "metadata/icall-def.h"
7628 } icall_type_names_str = {
7629 #define ICALL_TYPE(id,name,first) (name),
7630 #include "metadata/icall-def.h"
7633 static const guint16 icall_type_names_idx [] = {
7634 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7635 #include "metadata/icall-def.h"
7638 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7640 static const struct msgstr_t {
7642 #define ICALL_TYPE(id,name,first)
7643 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7644 #include "metadata/icall-def.h"
7646 } icall_names_str = {
7647 #define ICALL(id,name,func) (name),
7648 #include "metadata/icall-def.h"
7651 static const guint16 icall_names_idx [] = {
7652 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7653 #include "metadata/icall-def.h"
7656 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7662 #define ICALL_TYPE(id,name,first) name,
7663 #define ICALL(id,name,func)
7664 static const char* const
7665 icall_type_names [] = {
7666 #include "metadata/icall-def.h"
7670 #define icall_type_name_get(id) (icall_type_names [(id)])
7674 #define ICALL_TYPE(id,name,first)
7675 #define ICALL(id,name,func) name,
7676 static const char* const
7678 #include "metadata/icall-def.h"
7681 #define icall_name_get(id) icall_names [(id)]
7683 #endif /* !HAVE_ARRAY_ELEM_INIT */
7687 #define ICALL_TYPE(id,name,first)
7688 #define ICALL(id,name,func) func,
7689 static const gconstpointer
7690 icall_functions [] = {
7691 #include "metadata/icall-def.h"
7695 static GHashTable *icall_hash = NULL;
7696 static GHashTable *jit_icall_hash_name = NULL;
7697 static GHashTable *jit_icall_hash_addr = NULL;
7700 mono_icall_init (void)
7704 /* check that tables are sorted: disable in release */
7707 const char *prev_class = NULL;
7708 const char *prev_method;
7710 for (i = 0; i < Icall_type_num; ++i) {
7711 const IcallTypeDesc *desc;
7714 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7715 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7716 prev_class = icall_type_name_get (i);
7717 desc = &icall_type_descs [i];
7718 num_icalls = icall_desc_num_icalls (desc);
7719 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7720 for (j = 0; j < num_icalls; ++j) {
7721 const char *methodn = icall_name_get (desc->first_icall + j);
7722 if (prev_method && strcmp (prev_method, methodn) >= 0)
7723 g_print ("method %s should come before method %s\n", methodn, prev_method);
7724 prev_method = methodn;
7729 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7733 mono_icall_cleanup (void)
7735 g_hash_table_destroy (icall_hash);
7736 g_hash_table_destroy (jit_icall_hash_name);
7737 g_hash_table_destroy (jit_icall_hash_addr);
7741 mono_add_internal_call (const char *name, gconstpointer method)
7743 mono_loader_lock ();
7745 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7747 mono_loader_unlock ();
7750 #ifdef HAVE_ARRAY_ELEM_INIT
7752 compare_method_imap (const void *key, const void *elem)
7754 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7755 return strcmp (key, method_name);
7759 find_method_icall (const IcallTypeDesc *imap, const char *name)
7761 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7764 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7768 compare_class_imap (const void *key, const void *elem)
7770 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7771 return strcmp (key, class_name);
7774 static const IcallTypeDesc*
7775 find_class_icalls (const char *name)
7777 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7780 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7785 compare_method_imap (const void *key, const void *elem)
7787 const char** method_name = (const char**)elem;
7788 return strcmp (key, *method_name);
7792 find_method_icall (const IcallTypeDesc *imap, const char *name)
7794 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7797 return (gpointer)icall_functions [(nameslot - icall_names)];
7801 compare_class_imap (const void *key, const void *elem)
7803 const char** class_name = (const char**)elem;
7804 return strcmp (key, *class_name);
7807 static const IcallTypeDesc*
7808 find_class_icalls (const char *name)
7810 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7813 return &icall_type_descs [nameslot - icall_type_names];
7819 * we should probably export this as an helper (handle nested types).
7820 * Returns the number of chars written in buf.
7823 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7825 int nspacelen, cnamelen;
7826 nspacelen = strlen (klass->name_space);
7827 cnamelen = strlen (klass->name);
7828 if (nspacelen + cnamelen + 2 > bufsize)
7831 memcpy (buf, klass->name_space, nspacelen);
7832 buf [nspacelen ++] = '.';
7834 memcpy (buf + nspacelen, klass->name, cnamelen);
7835 buf [nspacelen + cnamelen] = 0;
7836 return nspacelen + cnamelen;
7840 mono_lookup_internal_call (MonoMethod *method)
7845 int typelen = 0, mlen, siglen;
7847 const IcallTypeDesc *imap;
7849 g_assert (method != NULL);
7851 if (method->is_inflated)
7852 method = ((MonoMethodInflated *) method)->declaring;
7854 if (method->klass->nested_in) {
7855 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7859 mname [pos++] = '/';
7862 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7868 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7873 imap = find_class_icalls (mname);
7875 mname [typelen] = ':';
7876 mname [typelen + 1] = ':';
7878 mlen = strlen (method->name);
7879 memcpy (mname + typelen + 2, method->name, mlen);
7880 sigstart = mname + typelen + 2 + mlen;
7883 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7884 siglen = strlen (tmpsig);
7885 if (typelen + mlen + siglen + 6 > sizeof (mname))
7888 memcpy (sigstart + 1, tmpsig, siglen);
7889 sigstart [siglen + 1] = ')';
7890 sigstart [siglen + 2] = 0;
7893 mono_loader_lock ();
7895 res = g_hash_table_lookup (icall_hash, mname);
7897 mono_loader_unlock ();
7900 /* try without signature */
7902 res = g_hash_table_lookup (icall_hash, mname);
7904 mono_loader_unlock ();
7908 /* it wasn't found in the static call tables */
7910 mono_loader_unlock ();
7913 res = find_method_icall (imap, sigstart - mlen);
7915 mono_loader_unlock ();
7918 /* try _with_ signature */
7920 res = find_method_icall (imap, sigstart - mlen);
7922 mono_loader_unlock ();
7926 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7927 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7928 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7929 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7930 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");
7931 g_print ("If you see other errors or faults after this message they are probably related\n");
7932 g_print ("and you need to fix your mono install first.\n");
7934 mono_loader_unlock ();
7940 type_from_typename (char *typename)
7942 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7944 if (!strcmp (typename, "int"))
7945 klass = mono_defaults.int_class;
7946 else if (!strcmp (typename, "ptr"))
7947 klass = mono_defaults.int_class;
7948 else if (!strcmp (typename, "void"))
7949 klass = mono_defaults.void_class;
7950 else if (!strcmp (typename, "int32"))
7951 klass = mono_defaults.int32_class;
7952 else if (!strcmp (typename, "uint32"))
7953 klass = mono_defaults.uint32_class;
7954 else if (!strcmp (typename, "int8"))
7955 klass = mono_defaults.sbyte_class;
7956 else if (!strcmp (typename, "uint8"))
7957 klass = mono_defaults.byte_class;
7958 else if (!strcmp (typename, "int16"))
7959 klass = mono_defaults.int16_class;
7960 else if (!strcmp (typename, "uint16"))
7961 klass = mono_defaults.uint16_class;
7962 else if (!strcmp (typename, "long"))
7963 klass = mono_defaults.int64_class;
7964 else if (!strcmp (typename, "ulong"))
7965 klass = mono_defaults.uint64_class;
7966 else if (!strcmp (typename, "float"))
7967 klass = mono_defaults.single_class;
7968 else if (!strcmp (typename, "double"))
7969 klass = mono_defaults.double_class;
7970 else if (!strcmp (typename, "object"))
7971 klass = mono_defaults.object_class;
7972 else if (!strcmp (typename, "obj"))
7973 klass = mono_defaults.object_class;
7974 else if (!strcmp (typename, "string"))
7975 klass = mono_defaults.string_class;
7976 else if (!strcmp (typename, "bool"))
7977 klass = mono_defaults.boolean_class;
7978 else if (!strcmp (typename, "boolean"))
7979 klass = mono_defaults.boolean_class;
7981 g_error ("%s", typename);
7982 g_assert_not_reached ();
7984 return &klass->byval_arg;
7987 MonoMethodSignature*
7988 mono_create_icall_signature (const char *sigstr)
7993 MonoMethodSignature *res;
7995 mono_loader_lock ();
7996 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7998 mono_loader_unlock ();
8002 parts = g_strsplit (sigstr, " ", 256);
8011 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8016 * Under windows, the default pinvoke calling convention is STDCALL but
8019 res->call_convention = MONO_CALL_C;
8022 res->ret = type_from_typename (parts [0]);
8023 for (i = 1; i < len; ++i) {
8024 res->params [i - 1] = type_from_typename (parts [i]);
8029 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8031 mono_loader_unlock ();
8037 mono_find_jit_icall_by_name (const char *name)
8039 MonoJitICallInfo *info;
8040 g_assert (jit_icall_hash_name);
8042 mono_loader_lock ();
8043 info = g_hash_table_lookup (jit_icall_hash_name, name);
8044 mono_loader_unlock ();
8049 mono_find_jit_icall_by_addr (gconstpointer addr)
8051 MonoJitICallInfo *info;
8052 g_assert (jit_icall_hash_addr);
8054 mono_loader_lock ();
8055 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8056 mono_loader_unlock ();
8062 * mono_get_jit_icall_info:
8064 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8065 * caller should access it while holding the loader lock.
8068 mono_get_jit_icall_info (void)
8070 return jit_icall_hash_name;
8074 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8076 mono_loader_lock ();
8077 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8078 mono_loader_unlock ();
8082 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8084 MonoJitICallInfo *info;
8089 mono_loader_lock ();
8091 if (!jit_icall_hash_name) {
8092 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8093 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8096 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8097 g_warning ("jit icall already defined \"%s\"\n", name);
8098 g_assert_not_reached ();
8101 info = g_new0 (MonoJitICallInfo, 1);
8108 info->wrapper = func;
8110 info->wrapper = NULL;
8113 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8114 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8116 mono_loader_unlock ();