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 if (type->type->data.klass->enumtype) {
1478 t = mono_class_enum_basetype (type->type->data.klass)->type;
1481 MonoClass *k = type->type->data.klass;
1482 if (strcmp (k->name_space, "System") == 0) {
1483 if (strcmp (k->name, "Decimal") == 0)
1484 return TYPECODE_DECIMAL;
1485 else if (strcmp (k->name, "DateTime") == 0)
1486 return TYPECODE_DATETIME;
1489 return TYPECODE_OBJECT;
1490 case MONO_TYPE_STRING:
1491 return TYPECODE_STRING;
1492 case MONO_TYPE_SZARRAY:
1493 case MONO_TYPE_ARRAY:
1494 case MONO_TYPE_OBJECT:
1496 case MONO_TYPE_MVAR:
1497 case MONO_TYPE_TYPEDBYREF:
1498 return TYPECODE_OBJECT;
1499 case MONO_TYPE_CLASS:
1501 MonoClass *k = type->type->data.klass;
1502 if (strcmp (k->name_space, "System") == 0) {
1503 if (strcmp (k->name, "DBNull") == 0)
1504 return TYPECODE_DBNULL;
1507 return TYPECODE_OBJECT;
1508 case MONO_TYPE_GENERICINST:
1509 return TYPECODE_OBJECT;
1511 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1517 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1523 MONO_ARCH_SAVE_REGS;
1525 g_assert (type != NULL);
1527 domain = ((MonoObject *)type)->vtable->domain;
1529 if (!c) /* FIXME: dont know what do do here */
1532 klass = mono_class_from_mono_type (type->type);
1533 klassc = mono_class_from_mono_type (c->type);
1535 /* Interface check requires a more complex setup so we
1536 * only do for them. Otherwise we simply avoid mono_class_init.
1538 if (check_interfaces) {
1539 mono_class_init_or_throw (klass);
1540 mono_class_init_or_throw (klassc);
1541 } else if (!klass->supertypes || !klassc->supertypes) {
1542 mono_loader_lock ();
1543 mono_class_setup_supertypes (klass);
1544 mono_class_setup_supertypes (klassc);
1545 mono_loader_unlock ();
1548 if (type->type->byref)
1549 return klassc == mono_defaults.object_class;
1551 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1555 mono_type_is_primitive (MonoType *type)
1557 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1558 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1562 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1564 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1565 return mono_class_enum_basetype (type->data.klass);
1566 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1567 return mono_class_enum_basetype (type->data.generic_class->container_class);
1572 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1578 MONO_ARCH_SAVE_REGS;
1580 g_assert (type != NULL);
1582 domain = ((MonoObject *)type)->vtable->domain;
1584 klass = mono_class_from_mono_type (type->type);
1585 klassc = mono_class_from_mono_type (c->type);
1587 mono_class_init_or_throw (klass);
1588 mono_class_init_or_throw (klassc);
1590 if (type->type->byref ^ c->type->byref)
1593 if (type->type->byref) {
1594 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1595 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1597 klass = mono_class_from_mono_type (t);
1598 klassc = mono_class_from_mono_type (ot);
1600 if (mono_type_is_primitive (t)) {
1601 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1602 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1603 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1604 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1605 return t->type == ot->type;
1607 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1610 if (klass->valuetype)
1611 return klass == klassc;
1612 return klass->valuetype == klassc->valuetype;
1615 return mono_class_is_assignable_from (klass, klassc);
1619 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1621 MonoClass *klass = mono_class_from_mono_type (type->type);
1622 mono_class_init_or_throw (klass);
1623 return mono_object_isinst (obj, klass) != NULL;
1627 ves_icall_get_attributes (MonoReflectionType *type)
1629 MonoClass *klass = mono_class_from_mono_type (type->type);
1630 return klass->flags;
1633 static MonoReflectionMarshal*
1634 ves_icall_System_Reflection_FieldInfo_GetUnmanagedMarshal (MonoReflectionField *field)
1636 MonoClass *klass = field->field->parent;
1637 MonoMarshalType *info;
1640 if (klass->generic_container ||
1641 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1644 info = mono_marshal_load_type_info (klass);
1646 for (i = 0; i < info->num_fields; ++i) {
1647 if (info->fields [i].field == field->field) {
1648 if (!info->fields [i].mspec)
1651 return mono_reflection_marshal_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1658 static MonoReflectionField*
1659 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1661 gboolean found = FALSE;
1668 klass = handle->parent;
1670 klass = mono_class_from_mono_type (type);
1672 /* Check that the field belongs to the class */
1673 for (k = klass; k; k = k->parent) {
1674 if (k == handle->parent) {
1681 /* The managed code will throw the exception */
1685 return mono_field_get_object (mono_domain_get (), klass, handle);
1689 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1691 MonoType *type = field->field->type;
1693 return type_array_from_modifiers (field->field->parent->image, type, optional);
1697 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1699 MonoDomain *domain = mono_domain_get ();
1700 MonoMethodSignature* sig;
1701 MONO_ARCH_SAVE_REGS;
1703 sig = mono_method_signature (method);
1705 g_assert (mono_loader_get_last_error ());
1706 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
1709 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1710 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1711 info->attrs = method->flags;
1712 info->implattrs = method->iflags;
1713 if (sig->call_convention == MONO_CALL_DEFAULT)
1714 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1716 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1721 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1725 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1727 MonoDomain *domain = mono_domain_get ();
1729 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1732 static MonoReflectionMarshal*
1733 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1735 MonoDomain *domain = mono_domain_get ();
1736 MonoReflectionMarshal* res = NULL;
1737 MonoMarshalSpec **mspecs;
1740 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1741 mono_method_get_marshal_info (method, mspecs);
1744 res = mono_reflection_marshal_from_marshal_spec (domain, method->klass, mspecs [0]);
1746 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1748 mono_metadata_free_marshal_spec (mspecs [i]);
1755 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1757 return field->field->offset - sizeof (MonoObject);
1760 static MonoReflectionType*
1761 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1764 MONO_ARCH_SAVE_REGS;
1766 parent = declaring? field->field->parent: field->klass;
1768 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1772 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1774 MonoClass *fklass = field->klass;
1775 MonoClassField *cf = field->field;
1776 MonoDomain *domain = mono_object_domain (field);
1778 if (fklass->image->assembly->ref_only)
1779 mono_raise_exception (mono_get_exception_invalid_operation (
1780 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1782 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1783 mono_security_core_clr_ensure_reflection_access_field (cf);
1785 return mono_field_get_value_object (domain, cf, obj);
1789 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1791 MonoClassField *cf = field->field;
1794 MONO_ARCH_SAVE_REGS;
1796 if (field->klass->image->assembly->ref_only)
1797 mono_raise_exception (mono_get_exception_invalid_operation (
1798 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1800 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1801 mono_security_core_clr_ensure_reflection_access_field (cf);
1803 v = (gchar *) value;
1804 if (!cf->type->byref) {
1805 switch (cf->type->type) {
1808 case MONO_TYPE_BOOLEAN:
1811 case MONO_TYPE_CHAR:
1820 case MONO_TYPE_VALUETYPE:
1822 v += sizeof (MonoObject);
1824 case MONO_TYPE_STRING:
1825 case MONO_TYPE_OBJECT:
1826 case MONO_TYPE_CLASS:
1827 case MONO_TYPE_ARRAY:
1828 case MONO_TYPE_SZARRAY:
1831 case MONO_TYPE_GENERICINST: {
1832 MonoGenericClass *gclass = cf->type->data.generic_class;
1833 g_assert (!gclass->context.class_inst->is_open);
1835 if (mono_class_is_nullable (mono_class_from_mono_type (cf->type))) {
1836 MonoClass *nklass = mono_class_from_mono_type (cf->type);
1837 MonoObject *nullable;
1840 * Convert the boxed vtype into a Nullable structure.
1841 * This is complicated by the fact that Nullables have
1842 * a variable structure.
1844 nullable = mono_object_new (mono_domain_get (), nklass);
1846 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1848 v = mono_object_unbox (nullable);
1851 if (gclass->container_class->valuetype && (v != NULL))
1852 v += sizeof (MonoObject);
1856 g_error ("type 0x%x not handled in "
1857 "ves_icall_FieldInfo_SetValueInternal", cf->type->type);
1862 if (cf->type->attrs & FIELD_ATTRIBUTE_STATIC) {
1863 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1864 if (!vtable->initialized)
1865 mono_runtime_class_init (vtable);
1866 mono_field_static_set_value (vtable, cf, v);
1868 mono_field_set_value (obj, cf, v);
1873 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1875 MonoObject *o = NULL;
1876 MonoClassField *field = this->field;
1878 MonoDomain *domain = mono_object_domain (this);
1880 MonoTypeEnum def_type;
1881 const char *def_value;
1883 MONO_ARCH_SAVE_REGS;
1885 mono_class_init (field->parent);
1887 if (!(field->type->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1888 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1890 if (field->parent->image->dynamic) {
1892 g_assert_not_reached ();
1895 def_value = mono_class_get_field_default_value (field, &def_type);
1897 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1901 case MONO_TYPE_BOOLEAN:
1904 case MONO_TYPE_CHAR:
1912 case MONO_TYPE_R8: {
1915 /* boxed value type */
1916 t = g_new0 (MonoType, 1);
1918 klass = mono_class_from_mono_type (t);
1920 o = mono_object_new (domain, klass);
1921 v = ((gchar *) o) + sizeof (MonoObject);
1922 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1925 case MONO_TYPE_STRING:
1926 case MONO_TYPE_CLASS:
1927 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1930 g_assert_not_reached ();
1936 static MonoReflectionType*
1937 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1939 MonoMethod *method = rmethod->method.method;
1941 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1944 /* From MonoProperty.cs */
1946 PInfo_Attributes = 1,
1947 PInfo_GetMethod = 1 << 1,
1948 PInfo_SetMethod = 1 << 2,
1949 PInfo_ReflectedType = 1 << 3,
1950 PInfo_DeclaringType = 1 << 4,
1955 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1957 MonoDomain *domain = mono_object_domain (property);
1959 MONO_ARCH_SAVE_REGS;
1961 if ((req_info & PInfo_ReflectedType) != 0)
1962 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1963 else if ((req_info & PInfo_DeclaringType) != 0)
1964 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->property->parent->byval_arg));
1966 if ((req_info & PInfo_Name) != 0)
1967 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1969 if ((req_info & PInfo_Attributes) != 0)
1970 info->attrs = property->property->attrs;
1972 if ((req_info & PInfo_GetMethod) != 0)
1973 MONO_STRUCT_SETREF (info, get, property->property->get ?
1974 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1976 if ((req_info & PInfo_SetMethod) != 0)
1977 MONO_STRUCT_SETREF (info, set, property->property->set ?
1978 mono_method_get_object (domain, property->property->set, property->klass): NULL);
1980 * There may be other methods defined for properties, though, it seems they are not exposed
1981 * in the reflection API
1986 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
1988 MonoDomain *domain = mono_object_domain (event);
1990 MONO_ARCH_SAVE_REGS;
1992 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
1993 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
1995 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
1996 info->attrs = event->event->attrs;
1997 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
1998 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
1999 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2001 #ifndef MONO_SMALL_CONFIG
2002 if (event->event->other) {
2004 while (event->event->other [n])
2006 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2008 for (i = 0; i < n; i++)
2009 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2015 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2020 mono_class_setup_interfaces (klass, error);
2021 if (!mono_error_ok (error))
2024 for (i = 0; i < klass->interface_count; i++) {
2025 ic = klass->interfaces [i];
2026 g_hash_table_insert (ifaces, ic, ic);
2028 collect_interfaces (ic, ifaces, error);
2029 if (!mono_error_ok (error))
2035 MonoArray *iface_array;
2036 MonoGenericContext *context;
2040 } FillIfaceArrayData;
2043 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2045 FillIfaceArrayData *data = user_data;
2046 MonoClass *ic = key;
2047 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2049 if (!mono_error_ok (data->error))
2052 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2053 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2054 if (!mono_error_ok (data->error))
2058 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2061 mono_metadata_free_type (inflated);
2065 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2068 MonoClass *class = mono_class_from_mono_type (type->type);
2070 FillIfaceArrayData data = { 0 };
2073 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2075 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2076 data.context = mono_class_get_context (class);
2077 class = class->generic_class->container_class;
2080 for (parent = class; parent; parent = parent->parent) {
2081 mono_class_setup_interfaces (parent, &error);
2082 if (!mono_error_ok (&error))
2084 collect_interfaces (parent, iface_hash, &error);
2085 if (!mono_error_ok (&error))
2089 data.error = &error;
2090 data.domain = mono_object_domain (type);
2092 len = g_hash_table_size (iface_hash);
2094 return mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2096 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2097 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2098 if (!mono_error_ok (&error))
2101 g_hash_table_destroy (iface_hash);
2102 return data.iface_array;
2105 g_hash_table_destroy (iface_hash);
2106 mono_error_raise_exception (&error);
2111 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2113 gboolean variance_used;
2114 MonoClass *class = mono_class_from_mono_type (type->type);
2115 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2116 MonoReflectionMethod *member;
2119 int i = 0, len, ioffset;
2122 MONO_ARCH_SAVE_REGS;
2123 mono_class_init_or_throw (class);
2124 mono_class_init_or_throw (iclass);
2126 mono_class_setup_vtable (class);
2128 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2132 len = mono_class_num_methods (iclass);
2133 domain = mono_object_domain (type);
2134 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2135 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2137 while ((method = mono_class_get_methods (iclass, &iter))) {
2138 member = mono_method_get_object (domain, method, iclass);
2139 mono_array_setref (*methods, i, member);
2140 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2141 mono_array_setref (*targets, i, member);
2148 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2150 MonoClass *klass = mono_class_from_mono_type (type->type);
2151 mono_class_init_or_throw (klass);
2153 if (klass->image->dynamic) {
2154 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2155 *packing = tb->packing_size;
2156 *size = tb->class_size;
2158 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2162 static MonoReflectionType*
2163 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2167 MONO_ARCH_SAVE_REGS;
2169 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2170 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2172 class = mono_class_from_mono_type (type->type);
2173 mono_class_init_or_throw (class);
2175 // GetElementType should only return a type for:
2176 // Array Pointer PassedByRef
2177 if (type->type->byref)
2178 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2179 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2180 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2181 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2182 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2187 static MonoReflectionType*
2188 ves_icall_get_type_parent (MonoReflectionType *type)
2190 MonoClass *class = mono_class_from_mono_type (type->type);
2191 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2195 ves_icall_type_ispointer (MonoReflectionType *type)
2197 MONO_ARCH_SAVE_REGS;
2199 return type->type->type == MONO_TYPE_PTR;
2203 ves_icall_type_isprimitive (MonoReflectionType *type)
2205 MONO_ARCH_SAVE_REGS;
2207 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)));
2211 ves_icall_type_isbyref (MonoReflectionType *type)
2213 MONO_ARCH_SAVE_REGS;
2215 return type->type->byref;
2219 ves_icall_type_iscomobject (MonoReflectionType *type)
2221 MonoClass *klass = mono_class_from_mono_type (type->type);
2222 mono_class_init_or_throw (klass);
2224 return (klass && klass->is_com_object);
2227 static MonoReflectionModule*
2228 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2230 MonoClass *class = mono_class_from_mono_type (type->type);
2231 mono_class_init_or_throw (class);
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);
2242 mono_class_init_or_throw (class);
2244 return mono_assembly_get_object (domain, class->image->assembly);
2247 static MonoReflectionType*
2248 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2250 MonoDomain *domain = mono_domain_get ();
2253 MONO_ARCH_SAVE_REGS;
2255 if (type->type->byref)
2257 if (type->type->type == MONO_TYPE_VAR)
2258 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2259 else if (type->type->type == MONO_TYPE_MVAR)
2260 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2262 class = mono_class_from_mono_type (type->type)->nested_in;
2264 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2268 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2270 MonoDomain *domain = mono_domain_get ();
2271 MonoClass *class = mono_class_from_mono_type (type->type);
2273 if (type->type->byref) {
2274 char *n = g_strdup_printf ("%s&", class->name);
2275 MonoString *res = mono_string_new (domain, n);
2281 return mono_string_new (domain, class->name);
2286 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2288 MonoDomain *domain = mono_domain_get ();
2289 MonoClass *class = mono_class_from_mono_type (type->type);
2291 while (class->nested_in)
2292 class = class->nested_in;
2294 if (class->name_space [0] == '\0')
2297 return mono_string_new (domain, class->name_space);
2301 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2305 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2306 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2308 class = mono_class_from_mono_type (type->type);
2309 mono_class_init_or_throw (class);
2315 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2318 MonoClass *klass, *pklass;
2319 MonoDomain *domain = mono_object_domain (type);
2320 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2322 MONO_ARCH_SAVE_REGS;
2324 klass = mono_class_from_mono_type (type->type);
2325 mono_class_init_or_throw (klass);
2327 if (klass->generic_container) {
2328 MonoGenericContainer *container = klass->generic_container;
2329 res = mono_array_new_specific (array_vtable, container->type_argc);
2330 for (i = 0; i < container->type_argc; ++i) {
2331 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2332 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2334 } else if (klass->generic_class) {
2335 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2336 res = mono_array_new_specific (array_vtable, inst->type_argc);
2337 for (i = 0; i < inst->type_argc; ++i)
2338 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2340 res = mono_array_new_specific (array_vtable, 0);
2346 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2349 MONO_ARCH_SAVE_REGS;
2351 if (!IS_MONOTYPE (type))
2354 if (type->type->byref)
2357 klass = mono_class_from_mono_type (type->type);
2358 return klass->generic_container != NULL;
2361 static MonoReflectionType*
2362 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2365 MONO_ARCH_SAVE_REGS;
2367 if (type->type->byref)
2370 klass = mono_class_from_mono_type (type->type);
2371 mono_class_init_or_throw (klass);
2373 if (klass->generic_container) {
2374 return type; /* check this one */
2376 if (klass->generic_class) {
2377 MonoClass *generic_class = klass->generic_class->container_class;
2380 tb = mono_class_get_ref_info (generic_class);
2382 if (generic_class->wastypebuilder && tb)
2385 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2390 static MonoReflectionType*
2391 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2393 MonoType *geninst, **types;
2396 g_assert (IS_MONOTYPE (type));
2397 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2399 count = mono_array_length (type_array);
2400 types = g_new0 (MonoType *, count);
2402 for (i = 0; i < count; i++) {
2403 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2404 types [i] = t->type;
2407 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2412 return mono_type_get_object (mono_object_domain (type), geninst);
2416 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2419 MONO_ARCH_SAVE_REGS;
2421 if (type->type->byref)
2424 klass = mono_class_from_mono_type (type->type);
2426 return klass->generic_class != NULL;
2430 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2433 MONO_ARCH_SAVE_REGS;
2435 if (!IS_MONOTYPE (type))
2438 if (type->type->byref)
2441 klass = mono_class_from_mono_type (type->type);
2442 return klass->generic_class != NULL || klass->generic_container != NULL;
2446 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2448 MONO_ARCH_SAVE_REGS;
2450 if (!IS_MONOTYPE (type))
2453 if (is_generic_parameter (type->type))
2454 return mono_type_get_generic_param_num (type->type);
2458 static GenericParameterAttributes
2459 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2461 MONO_ARCH_SAVE_REGS;
2463 g_assert (IS_MONOTYPE (type));
2464 g_assert (is_generic_parameter (type->type));
2465 return mono_generic_param_info (type->type->data.generic_param)->flags;
2469 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2471 MonoGenericParamInfo *param_info;
2477 MONO_ARCH_SAVE_REGS;
2479 g_assert (IS_MONOTYPE (type));
2481 domain = mono_object_domain (type);
2482 param_info = mono_generic_param_info (type->type->data.generic_param);
2483 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2486 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2487 for (i = 0; i < count; i++)
2488 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2495 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2497 MONO_ARCH_SAVE_REGS;
2498 return is_generic_parameter (type->type);
2502 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2504 MONO_ARCH_SAVE_REGS;
2505 return is_generic_parameter (tb->type.type);
2509 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2510 MonoReflectionType *t)
2512 enumtype->type = t->type;
2515 static MonoReflectionMethod*
2516 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2517 MonoReflectionMethod* generic)
2524 MONO_ARCH_SAVE_REGS;
2526 domain = ((MonoObject *)type)->vtable->domain;
2528 klass = mono_class_from_mono_type (type->type);
2529 mono_class_init_or_throw (klass);
2532 while ((method = mono_class_get_methods (klass, &iter))) {
2533 if (method->token == generic->method->token)
2534 return mono_method_get_object (domain, method, klass);
2542 static MonoReflectionMethod *
2543 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2546 MonoType *type = ref_type->type;
2548 MONO_ARCH_SAVE_REGS;
2550 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2551 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2552 if (type->type == MONO_TYPE_VAR)
2555 method = mono_type_get_generic_param_owner (type)->owner.method;
2557 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2560 static MonoReflectionDllImportAttribute*
2561 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2563 static MonoClass *DllImportAttributeClass = NULL;
2564 MonoDomain *domain = mono_domain_get ();
2565 MonoReflectionDllImportAttribute *attr;
2566 MonoImage *image = method->klass->image;
2567 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2568 MonoTableInfo *tables = image->tables;
2569 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2570 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2571 guint32 im_cols [MONO_IMPLMAP_SIZE];
2572 guint32 scope_token;
2573 const char *import = NULL;
2574 const char *scope = NULL;
2577 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2580 if (!DllImportAttributeClass) {
2581 DllImportAttributeClass =
2582 mono_class_from_name (mono_defaults.corlib,
2583 "System.Runtime.InteropServices", "DllImportAttribute");
2584 g_assert (DllImportAttributeClass);
2587 if (method->klass->image->dynamic) {
2588 MonoReflectionMethodAux *method_aux =
2589 g_hash_table_lookup (
2590 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2592 import = method_aux->dllentry;
2593 scope = method_aux->dll;
2596 if (!import || !scope) {
2597 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2602 if (piinfo->implmap_idx) {
2603 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2605 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2606 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2607 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2608 scope = mono_metadata_string_heap (image, scope_token);
2611 flags = piinfo->piflags;
2613 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2615 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2616 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2617 attr->call_conv = (flags & 0x700) >> 8;
2618 attr->charset = ((flags & 0x6) >> 1) + 1;
2619 if (attr->charset == 1)
2621 attr->exact_spelling = (flags & 0x1) != 0;
2622 attr->set_last_error = (flags & 0x40) != 0;
2623 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2624 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2625 attr->preserve_sig = FALSE;
2630 static MonoReflectionMethod *
2631 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2633 MonoMethodInflated *imethod;
2636 MONO_ARCH_SAVE_REGS;
2638 if (method->method->is_generic)
2641 if (!method->method->is_inflated)
2644 imethod = (MonoMethodInflated *) method->method;
2646 result = imethod->declaring;
2647 /* Not a generic method. */
2648 if (!result->is_generic)
2651 if (method->method->klass->image->dynamic) {
2652 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2653 MonoReflectionMethod *res;
2656 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2657 * the dynamic case as well ?
2659 mono_loader_lock ();
2660 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2661 mono_loader_unlock ();
2667 if (imethod->context.class_inst) {
2668 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2669 /*Generic methods gets the context of the GTD.*/
2670 if (mono_class_get_context (klass))
2671 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2674 return mono_method_get_object (mono_object_domain (method), result, NULL);
2678 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2680 MONO_ARCH_SAVE_REGS;
2682 return mono_method_signature (method->method)->generic_param_count != 0;
2686 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2688 MONO_ARCH_SAVE_REGS;
2690 return method->method->is_generic;
2694 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2699 MONO_ARCH_SAVE_REGS;
2701 domain = mono_object_domain (method);
2703 if (method->method->is_inflated) {
2704 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2707 count = inst->type_argc;
2708 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2710 for (i = 0; i < count; i++)
2711 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2717 count = mono_method_signature (method->method)->generic_param_count;
2718 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2720 for (i = 0; i < count; i++) {
2721 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2722 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2723 MonoClass *pklass = mono_class_from_generic_parameter (
2724 param, method->method->klass->image, TRUE);
2725 mono_array_setref (res, i,
2726 mono_type_get_object (domain, &pklass->byval_arg));
2733 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2736 * Invoke from reflection is supposed to always be a virtual call (the API
2737 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2738 * greater flexibility.
2740 MonoMethod *m = method->method;
2744 MONO_ARCH_SAVE_REGS;
2748 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2749 mono_security_core_clr_ensure_reflection_access_method (m);
2751 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2752 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2753 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2758 if (!mono_object_isinst (this, m->klass)) {
2759 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Object does not match target type."));
2762 m = mono_object_get_virtual_method (this, m);
2763 /* must pass the pointer to the value for valuetype methods */
2764 if (m->klass->valuetype)
2765 obj = mono_object_unbox (this);
2766 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2767 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2772 pcount = params? mono_array_length (params): 0;
2773 if (pcount != mono_method_signature (m)->param_count) {
2774 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2778 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2779 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."));
2783 if (m->klass->image->assembly->ref_only) {
2784 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."));
2788 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2791 intptr_t *lower_bounds;
2792 pcount = mono_array_length (params);
2793 lengths = alloca (sizeof (uintptr_t) * pcount);
2794 /* Note: the synthetized array .ctors have int32 as argument type */
2795 for (i = 0; i < pcount; ++i)
2796 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2798 if (m->klass->rank == pcount) {
2799 /* Only lengths provided. */
2800 lower_bounds = NULL;
2802 g_assert (pcount == (m->klass->rank * 2));
2803 /* lower bounds are first. */
2804 lower_bounds = (intptr_t*)lengths;
2805 lengths += m->klass->rank;
2808 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2810 return mono_runtime_invoke_array (m, obj, params, NULL);
2814 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2816 MonoDomain *domain = mono_object_domain (method);
2817 MonoMethod *m = method->method;
2818 MonoMethodSignature *sig = mono_method_signature (m);
2819 MonoArray *out_args;
2821 int i, j, outarg_count = 0;
2823 MONO_ARCH_SAVE_REGS;
2825 if (m->klass == mono_defaults.object_class) {
2827 if (!strcmp (m->name, "FieldGetter")) {
2828 MonoClass *k = this->vtable->klass;
2832 /* If this is a proxy, then it must be a CBO */
2833 if (k == mono_defaults.transparent_proxy_class) {
2834 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2835 this = tp->rp->unwrapped_server;
2837 k = this->vtable->klass;
2840 name = mono_array_get (params, MonoString *, 1);
2841 str = mono_string_to_utf8 (name);
2844 MonoClassField* field = mono_class_get_field_from_name (k, str);
2846 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2847 if (field_klass->valuetype)
2848 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2850 result = *((gpointer *)((char *)this + field->offset));
2852 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2853 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2854 mono_array_setref (out_args, 0, result);
2862 g_assert_not_reached ();
2864 } else if (!strcmp (m->name, "FieldSetter")) {
2865 MonoClass *k = this->vtable->klass;
2871 /* If this is a proxy, then it must be a CBO */
2872 if (k == mono_defaults.transparent_proxy_class) {
2873 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2874 this = tp->rp->unwrapped_server;
2876 k = this->vtable->klass;
2879 name = mono_array_get (params, MonoString *, 1);
2880 str = mono_string_to_utf8 (name);
2883 MonoClassField* field = mono_class_get_field_from_name (k, str);
2885 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2886 MonoObject *val = mono_array_get (params, gpointer, 2);
2888 if (field_klass->valuetype) {
2889 size = mono_type_size (field->type, &align);
2890 g_assert (size == mono_class_value_size (field_klass, NULL));
2891 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2893 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2896 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2897 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2907 g_assert_not_reached ();
2912 for (i = 0; i < mono_array_length (params); i++) {
2913 if (sig->params [i]->byref)
2917 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2919 /* handle constructors only for objects already allocated */
2920 if (!strcmp (method->method->name, ".ctor"))
2923 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2924 g_assert (!method->method->klass->valuetype);
2925 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2927 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2928 if (sig->params [i]->byref) {
2930 arg = mono_array_get (params, gpointer, i);
2931 mono_array_setref (out_args, j, arg);
2936 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2942 read_enum_value (char *mem, int type)
2946 return *(guint8*)mem;
2948 return *(gint8*)mem;
2950 return *(guint16*)mem;
2952 return *(gint16*)mem;
2954 return *(guint32*)mem;
2956 return *(gint32*)mem;
2958 return *(guint64*)mem;
2960 return *(gint64*)mem;
2962 g_assert_not_reached ();
2968 write_enum_value (char *mem, int type, guint64 value)
2972 case MONO_TYPE_I1: {
2973 guint8 *p = (guint8*)mem;
2978 case MONO_TYPE_I2: {
2979 guint16 *p = (void*)mem;
2984 case MONO_TYPE_I4: {
2985 guint32 *p = (void*)mem;
2990 case MONO_TYPE_I8: {
2991 guint64 *p = (void*)mem;
2996 g_assert_not_reached ();
3002 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3005 MonoClass *enumc, *objc;
3010 MONO_ARCH_SAVE_REGS;
3012 MONO_CHECK_ARG_NULL (enumType);
3013 MONO_CHECK_ARG_NULL (value);
3015 domain = mono_object_domain (enumType);
3016 enumc = mono_class_from_mono_type (enumType->type);
3018 mono_class_init_or_throw (enumc);
3020 objc = value->vtable->klass;
3022 if (!enumc->enumtype)
3023 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3024 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3025 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."));
3027 etype = mono_class_enum_basetype (enumc);
3029 /* MS throws this for typebuilders */
3030 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3032 res = mono_object_new (domain, enumc);
3033 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3034 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3040 ves_icall_System_Enum_get_value (MonoObject *this)
3048 MONO_ARCH_SAVE_REGS;
3053 g_assert (this->vtable->klass->enumtype);
3055 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3056 res = mono_object_new (mono_object_domain (this), enumc);
3057 dst = (char *)res + sizeof (MonoObject);
3058 src = (char *)this + sizeof (MonoObject);
3059 size = mono_class_value_size (enumc, NULL);
3061 memcpy (dst, src, size);
3066 static MonoReflectionType *
3067 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3072 MONO_ARCH_SAVE_REGS;
3074 klass = mono_class_from_mono_type (type->type);
3075 mono_class_init_or_throw (klass);
3077 etype = mono_class_enum_basetype (klass);
3079 /* MS throws this for typebuilders */
3080 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3082 return mono_type_get_object (mono_object_domain (type), etype);
3086 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3088 gpointer tdata = (char *)this + sizeof (MonoObject);
3089 gpointer odata = (char *)other + sizeof (MonoObject);
3090 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3091 g_assert (basetype);
3093 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3094 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3095 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3098 return me > other ? 1 : -1; \
3101 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3102 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3103 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3106 return me - other; \
3109 switch (basetype->type) {
3111 COMPARE_ENUM_VALUES (guint8);
3113 COMPARE_ENUM_VALUES (gint8);
3114 case MONO_TYPE_CHAR:
3116 COMPARE_ENUM_VALUES_RANGE (guint16);
3118 COMPARE_ENUM_VALUES (gint16);
3120 COMPARE_ENUM_VALUES (guint32);
3122 COMPARE_ENUM_VALUES (gint32);
3124 COMPARE_ENUM_VALUES (guint64);
3126 COMPARE_ENUM_VALUES (gint64);
3128 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3130 #undef COMPARE_ENUM_VALUES_RANGE
3131 #undef COMPARE_ENUM_VALUES
3136 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3138 gpointer data = (char *)this + sizeof (MonoObject);
3139 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3140 g_assert (basetype);
3142 switch (basetype->type) {
3144 return *((gint8*)data);
3146 return *((guint8*)data);
3147 case MONO_TYPE_CHAR:
3149 return *((guint16*)data);
3152 return *((gint16*)data);
3154 return *((guint32*)data);
3156 return *((gint32*)data);
3158 case MONO_TYPE_I8: {
3159 gint64 value = *((gint64*)data);
3160 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3163 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3169 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3171 MonoDomain *domain = mono_object_domain (type);
3172 MonoClass *enumc = mono_class_from_mono_type (type->type);
3173 guint j = 0, nvalues, crow;
3175 MonoClassField *field;
3177 MONO_ARCH_SAVE_REGS;
3179 mono_class_init_or_throw (enumc);
3181 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3182 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3183 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3184 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3188 while ((field = mono_class_get_fields (enumc, &iter))) {
3191 MonoTypeEnum def_type;
3193 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3195 if (mono_field_is_deleted (field))
3197 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3199 p = mono_class_get_field_default_value (field, &def_type);
3200 len = mono_metadata_decode_blob_size (p, &p);
3201 switch (mono_class_enum_basetype (enumc)->type) {
3204 mono_array_set (info->values, gchar, j, *p);
3206 case MONO_TYPE_CHAR:
3209 mono_array_set (info->values, gint16, j, read16 (p));
3213 mono_array_set (info->values, gint32, j, read32 (p));
3217 mono_array_set (info->values, gint64, j, read64 (p));
3220 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3227 BFLAGS_IgnoreCase = 1,
3228 BFLAGS_DeclaredOnly = 2,
3229 BFLAGS_Instance = 4,
3231 BFLAGS_Public = 0x10,
3232 BFLAGS_NonPublic = 0x20,
3233 BFLAGS_FlattenHierarchy = 0x40,
3234 BFLAGS_InvokeMethod = 0x100,
3235 BFLAGS_CreateInstance = 0x200,
3236 BFLAGS_GetField = 0x400,
3237 BFLAGS_SetField = 0x800,
3238 BFLAGS_GetProperty = 0x1000,
3239 BFLAGS_SetProperty = 0x2000,
3240 BFLAGS_ExactBinding = 0x10000,
3241 BFLAGS_SuppressChangeType = 0x20000,
3242 BFLAGS_OptionalParamBinding = 0x40000
3245 static MonoReflectionField *
3246 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3249 MonoClass *startklass, *klass;
3251 MonoClassField *field;
3254 int (*compare_func) (const char *s1, const char *s2) = NULL;
3255 domain = ((MonoObject *)type)->vtable->domain;
3256 klass = startklass = mono_class_from_mono_type (type->type);
3257 mono_class_init_or_throw (klass);
3260 mono_raise_exception (mono_get_exception_argument_null ("name"));
3261 if (type->type->byref)
3264 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3267 if (klass->exception_type != MONO_EXCEPTION_NONE)
3268 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3271 while ((field = mono_class_get_fields (klass, &iter))) {
3274 if (field->type == NULL)
3276 if (mono_field_is_deleted (field))
3278 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3279 if (bflags & BFLAGS_Public)
3281 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3282 if (bflags & BFLAGS_NonPublic) {
3289 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3290 if (bflags & BFLAGS_Static)
3291 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3294 if (bflags & BFLAGS_Instance)
3301 utf8_name = mono_string_to_utf8 (name);
3303 if (compare_func (mono_field_get_name (field), utf8_name)) {
3309 return mono_field_get_object (domain, klass, field);
3311 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3318 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3321 MonoClass *startklass, *klass, *refklass;
3326 MonoClassField *field;
3327 MonoPtrArray tmp_array;
3329 MONO_ARCH_SAVE_REGS;
3331 domain = ((MonoObject *)type)->vtable->domain;
3332 if (type->type->byref)
3333 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3334 klass = startklass = mono_class_from_mono_type (type->type);
3335 refklass = mono_class_from_mono_type (reftype->type);
3337 mono_class_init_or_throw (klass);
3338 mono_class_init_or_throw (refklass);
3340 mono_ptr_array_init (tmp_array, 2);
3343 if (klass->exception_type != MONO_EXCEPTION_NONE)
3344 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3347 while ((field = mono_class_get_fields (klass, &iter))) {
3349 if (mono_field_is_deleted (field))
3351 if ((field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3352 if (bflags & BFLAGS_Public)
3354 } else if ((klass == startklass) || (field->type->attrs & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3355 if (bflags & BFLAGS_NonPublic) {
3362 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC) {
3363 if (bflags & BFLAGS_Static)
3364 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3367 if (bflags & BFLAGS_Instance)
3373 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3374 mono_ptr_array_append (tmp_array, member);
3376 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3379 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3381 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3382 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3384 mono_ptr_array_destroy (tmp_array);
3390 method_nonpublic (MonoMethod* method, gboolean start_klass)
3392 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3393 case METHOD_ATTRIBUTE_ASSEM:
3394 return (start_klass || mono_defaults.generic_ilist_class);
3395 case METHOD_ATTRIBUTE_PRIVATE:
3397 case METHOD_ATTRIBUTE_PUBLIC:
3405 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3407 static MonoClass *MethodInfo_array;
3409 MonoClass *startklass, *klass, *refklass;
3414 int i, len, match, nslots;
3415 /*FIXME, use MonoBitSet*/
3416 guint32 method_slots_default [8];
3417 guint32 *method_slots = NULL;
3418 gchar *mname = NULL;
3419 int (*compare_func) (const char *s1, const char *s2) = NULL;
3420 MonoVTable *array_vtable;
3422 MonoPtrArray tmp_array;
3424 mono_ptr_array_init (tmp_array, 4);
3426 if (!MethodInfo_array) {
3427 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3428 mono_memory_barrier ();
3429 MethodInfo_array = klass;
3432 domain = ((MonoObject *)type)->vtable->domain;
3433 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3434 if (type->type->byref)
3435 return mono_array_new_specific (array_vtable, 0);
3436 klass = startklass = mono_class_from_mono_type (type->type);
3437 refklass = mono_class_from_mono_type (reftype->type);
3439 mono_class_init_or_throw (klass);
3440 mono_class_init_or_throw (refklass);
3444 mname = mono_string_to_utf8 (name);
3445 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3448 /* An optimization for calls made from Delegate:CreateDelegate () */
3449 if (klass->delegate && mname && !strcmp (mname, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3450 method = mono_get_delegate_invoke (klass);
3451 if (mono_loader_get_last_error ())
3454 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3456 res = mono_array_new_specific (array_vtable, 1);
3457 mono_array_setref (res, 0, member);
3462 mono_class_setup_vtable (klass);
3463 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3466 if (is_generic_parameter (type->type))
3467 nslots = mono_class_get_vtable_size (klass->parent);
3469 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3470 if (nslots >= sizeof (method_slots_default) * 8) {
3471 method_slots = g_new0 (guint32, nslots / 32 + 1);
3473 method_slots = method_slots_default;
3474 memset (method_slots, 0, sizeof (method_slots_default));
3477 mono_class_setup_vtable (klass);
3478 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3482 while ((method = mono_class_get_methods (klass, &iter))) {
3484 if (method->slot != -1) {
3485 g_assert (method->slot < nslots);
3486 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3488 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3489 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3492 if (method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3494 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3495 if (bflags & BFLAGS_Public)
3497 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3503 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3504 if (bflags & BFLAGS_Static)
3505 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3508 if (bflags & BFLAGS_Instance)
3516 if (compare_func (mname, method->name))
3522 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3524 mono_ptr_array_append (tmp_array, member);
3526 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3530 if (method_slots != method_slots_default)
3531 g_free (method_slots);
3533 res = mono_array_new_specific (array_vtable, mono_ptr_array_size (tmp_array));
3535 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3536 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3538 mono_ptr_array_destroy (tmp_array);
3543 if (method_slots != method_slots_default)
3544 g_free (method_slots);
3545 mono_ptr_array_destroy (tmp_array);
3546 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3547 ex = mono_class_get_exception_for_failure (klass);
3549 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3550 mono_loader_clear_error ();
3552 mono_raise_exception (ex);
3557 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3560 static MonoClass *System_Reflection_ConstructorInfo;
3561 MonoClass *startklass, *klass, *refklass;
3566 gpointer iter = NULL;
3567 MonoPtrArray tmp_array;
3569 MONO_ARCH_SAVE_REGS;
3571 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3573 domain = ((MonoObject *)type)->vtable->domain;
3574 if (type->type->byref)
3575 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3576 klass = startklass = mono_class_from_mono_type (type->type);
3577 refklass = mono_class_from_mono_type (reftype->type);
3579 mono_class_init_or_throw (klass);
3580 mono_class_init_or_throw (refklass);
3582 if (klass->exception_type != MONO_EXCEPTION_NONE)
3583 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3585 if (!System_Reflection_ConstructorInfo)
3586 System_Reflection_ConstructorInfo = mono_class_from_name (
3587 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3590 while ((method = mono_class_get_methods (klass, &iter))) {
3592 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3594 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3595 if (bflags & BFLAGS_Public)
3598 if (bflags & BFLAGS_NonPublic)
3604 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3605 if (bflags & BFLAGS_Static)
3606 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3609 if (bflags & BFLAGS_Instance)
3615 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3617 mono_ptr_array_append (tmp_array, member);
3620 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3622 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3623 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3625 mono_ptr_array_destroy (tmp_array);
3631 property_hash (gconstpointer data)
3633 MonoProperty *prop = (MonoProperty*)data;
3635 return g_str_hash (prop->name);
3639 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3641 // Properties are hide-by-name-and-signature
3642 if (!g_str_equal (prop1->name, prop2->name))
3645 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3647 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3653 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3658 return method_nonpublic (accessor, start_klass);
3662 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3665 static MonoClass *System_Reflection_PropertyInfo;
3666 MonoClass *startklass, *klass;
3672 gchar *propname = NULL;
3673 int (*compare_func) (const char *s1, const char *s2) = NULL;
3675 GHashTable *properties;
3676 MonoPtrArray tmp_array;
3678 MONO_ARCH_SAVE_REGS;
3680 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3682 if (!System_Reflection_PropertyInfo)
3683 System_Reflection_PropertyInfo = mono_class_from_name (
3684 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3686 domain = ((MonoObject *)type)->vtable->domain;
3687 if (type->type->byref)
3688 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3689 klass = startklass = mono_class_from_mono_type (type->type);
3690 mono_class_init_or_throw (klass);
3695 propname = mono_string_to_utf8 (name);
3696 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3699 mono_class_setup_vtable (klass);
3701 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3703 mono_class_setup_vtable (klass);
3704 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3705 g_hash_table_destroy (properties);
3708 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3712 while ((prop = mono_class_get_properties (klass, &iter))) {
3718 flags = method->flags;
3721 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3722 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3723 if (bflags & BFLAGS_Public)
3725 } else if (bflags & BFLAGS_NonPublic) {
3726 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3727 property_accessor_nonpublic(prop->set, startklass == klass)) {
3734 if (flags & METHOD_ATTRIBUTE_STATIC) {
3735 if (bflags & BFLAGS_Static)
3736 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3739 if (bflags & BFLAGS_Instance)
3748 if (compare_func (propname, prop->name))
3752 if (g_hash_table_lookup (properties, prop))
3755 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3757 g_hash_table_insert (properties, prop, prop);
3759 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3762 g_hash_table_destroy (properties);
3765 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3766 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3767 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3769 mono_ptr_array_destroy (tmp_array);
3774 static MonoReflectionEvent *
3775 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3778 MonoClass *klass, *startklass;
3784 MONO_ARCH_SAVE_REGS;
3786 event_name = mono_string_to_utf8 (name);
3787 if (type->type->byref)
3789 klass = startklass = mono_class_from_mono_type (type->type);
3790 domain = mono_object_domain (type);
3792 mono_class_init_or_throw (klass);
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 (strcmp (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);
4137 if (type->type == MONO_TYPE_CLASS) {
4138 MonoClass *klass = mono_type_get_class (type);
4140 if (mono_is_security_manager_active () && !klass->exception_type)
4141 /* Some security problems are detected during generic vtable construction */
4142 mono_class_setup_vtable (klass);
4143 /* need to report exceptions ? */
4144 if (throwOnError && klass->exception_type) {
4145 /* report SecurityException (or others) that occured when loading the assembly */
4146 MonoException *exc = mono_class_get_exception_for_failure (klass);
4147 mono_loader_clear_error ();
4148 mono_raise_exception (exc);
4149 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4154 /* g_print ("got it\n"); */
4155 return mono_type_get_object (mono_object_domain (assembly), type);
4159 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4162 gchar *shadow_ini_file;
4165 /* Check for shadow-copied assembly */
4166 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4167 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4169 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4170 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4176 g_free (shadow_ini_file);
4177 if (content != NULL) {
4180 *filename = content;
4188 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4190 MonoDomain *domain = mono_object_domain (assembly);
4191 MonoAssembly *mass = assembly->assembly;
4192 MonoString *res = NULL;
4197 MONO_ARCH_SAVE_REGS;
4199 if (g_path_is_absolute (mass->image->name)) {
4200 absolute = g_strdup (mass->image->name);
4201 dirname = g_path_get_dirname (absolute);
4203 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4204 dirname = g_strdup (mass->basedir);
4207 replace_shadow_path (domain, dirname, &absolute);
4212 for (i = strlen (absolute) - 1; i >= 0; i--)
4213 if (absolute [i] == '\\')
4218 uri = g_filename_to_uri (absolute, NULL, NULL);
4220 const char *prepend = "file://";
4222 if (*absolute == '/' && *(absolute + 1) == '/') {
4225 prepend = "file:///";
4228 uri = g_strconcat (prepend, absolute, NULL);
4232 res = mono_string_new (domain, uri);
4240 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4242 MonoAssembly *mass = assembly->assembly;
4244 MONO_ARCH_SAVE_REGS;
4246 return mass->in_gac;
4249 static MonoReflectionAssembly*
4250 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4254 MonoImageOpenStatus status;
4256 MONO_ARCH_SAVE_REGS;
4258 name = mono_string_to_utf8 (mname);
4259 res = mono_assembly_load_with_partial_name (name, &status);
4265 return mono_assembly_get_object (mono_domain_get (), res);
4269 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4271 MonoDomain *domain = mono_object_domain (assembly);
4274 MONO_ARCH_SAVE_REGS;
4276 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4282 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4284 MONO_ARCH_SAVE_REGS;
4286 return assembly->assembly->ref_only;
4290 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4292 MonoDomain *domain = mono_object_domain (assembly);
4294 MONO_ARCH_SAVE_REGS;
4296 return mono_string_new (domain, assembly->assembly->image->version);
4299 static MonoReflectionMethod*
4300 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4302 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4304 MONO_ARCH_SAVE_REGS;
4308 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4311 static MonoReflectionModule*
4312 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4314 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4318 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4320 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4321 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4325 MONO_ARCH_SAVE_REGS;
4327 for (i = 0; i < table->rows; ++i) {
4328 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4329 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4335 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4337 static MonoClass *System_Version = NULL;
4338 static MonoMethod *create_version = NULL;
4342 if (!System_Version) {
4343 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4344 g_assert (System_Version);
4347 if (!create_version) {
4348 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4349 create_version = mono_method_desc_search_in_class (desc, System_Version);
4350 g_assert (create_version);
4351 mono_method_desc_free (desc);
4357 args [3] = &revision;
4358 result = mono_object_new (domain, System_Version);
4359 mono_runtime_invoke (create_version, result, args, NULL);
4365 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4367 static MonoClass *System_Reflection_AssemblyName;
4369 MonoDomain *domain = mono_object_domain (assembly);
4371 static MonoMethod *create_culture = NULL;
4372 MonoImage *image = assembly->assembly->image;
4375 MONO_ARCH_SAVE_REGS;
4377 if (!System_Reflection_AssemblyName)
4378 System_Reflection_AssemblyName = mono_class_from_name (
4379 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4381 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4384 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4386 if (count > 0 && !create_culture) {
4387 MonoMethodDesc *desc = mono_method_desc_new (
4388 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4389 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4390 g_assert (create_culture);
4391 mono_method_desc_free (desc);
4394 for (i = 0; i < count; i++) {
4395 MonoReflectionAssemblyName *aname;
4396 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4398 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4400 aname = (MonoReflectionAssemblyName *) mono_object_new (
4401 domain, System_Reflection_AssemblyName);
4403 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4405 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4406 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4407 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4408 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4409 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4410 aname->versioncompat = 1; /* SameMachine (default) */
4411 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4412 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4414 if (create_culture) {
4416 MonoBoolean assembly_ref = 1;
4417 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4418 args [1] = &assembly_ref;
4419 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4422 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4423 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4424 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4426 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4427 /* public key token isn't copied - the class library will
4428 automatically generate it from the public key if required */
4429 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4430 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4432 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4433 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4436 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4439 /* note: this function doesn't return the codebase on purpose (i.e. it can
4440 be used under partial trust as path information isn't present). */
4442 mono_array_setref (result, i, aname);
4453 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4455 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4457 mono_array_setref (info->res, info->idx, name);
4462 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4464 MonoImage *img = assembly->assembly->image;
4469 MONO_ARCH_SAVE_REGS;
4471 mono_image_lock (img);
4472 mono_image_init_name_cache (img);
4475 len = g_hash_table_size (img->name_cache);
4476 mono_image_unlock (img);
4478 /*we can't create objects holding the image lock */
4479 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4481 mono_image_lock (img);
4482 /*len might have changed, create a new array*/
4483 if (len != g_hash_table_size (img->name_cache))
4488 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4489 mono_image_unlock (img);
4494 /* move this in some file in mono/util/ */
4496 g_concat_dir_and_file (const char *dir, const char *file)
4498 g_return_val_if_fail (dir != NULL, NULL);
4499 g_return_val_if_fail (file != NULL, NULL);
4502 * If the directory name doesn't have a / on the end, we need
4503 * to add one so we get a proper path to the file
4505 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4506 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4508 return g_strconcat (dir, file, NULL);
4512 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4514 char *n = mono_string_to_utf8 (name);
4515 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4517 guint32 cols [MONO_MANIFEST_SIZE];
4518 guint32 impl, file_idx;
4522 MONO_ARCH_SAVE_REGS;
4524 for (i = 0; i < table->rows; ++i) {
4525 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4526 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4527 if (strcmp (val, n) == 0)
4531 if (i == table->rows)
4534 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4537 * this code should only be called after obtaining the
4538 * ResourceInfo and handling the other cases.
4540 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4541 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4543 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4548 module = assembly->assembly->image;
4550 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4552 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4556 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4558 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4560 guint32 cols [MONO_MANIFEST_SIZE];
4561 guint32 file_cols [MONO_FILE_SIZE];
4565 MONO_ARCH_SAVE_REGS;
4567 n = mono_string_to_utf8 (name);
4568 for (i = 0; i < table->rows; ++i) {
4569 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4570 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4571 if (strcmp (val, n) == 0)
4575 if (i == table->rows)
4578 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4579 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4582 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4583 case MONO_IMPLEMENTATION_FILE:
4584 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4585 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4586 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4587 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4588 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4589 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4592 info->location = RESOURCE_LOCATION_EMBEDDED;
4595 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4596 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4597 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4598 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4599 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4600 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4602 mono_raise_exception (ex);
4604 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4606 /* Obtain info recursively */
4607 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4608 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4611 case MONO_IMPLEMENTATION_EXP_TYPE:
4612 g_assert_not_reached ();
4621 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4623 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4624 MonoArray *result = NULL;
4629 MONO_ARCH_SAVE_REGS;
4631 /* check hash if needed */
4633 n = mono_string_to_utf8 (name);
4634 for (i = 0; i < table->rows; ++i) {
4635 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4636 if (strcmp (val, n) == 0) {
4639 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4640 fn = mono_string_new (mono_object_domain (assembly), n);
4642 return (MonoObject*)fn;
4650 for (i = 0; i < table->rows; ++i) {
4651 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4655 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4658 for (i = 0; i < table->rows; ++i) {
4659 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4660 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4661 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4662 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4667 return (MonoObject*)result;
4671 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4673 MonoDomain *domain = mono_domain_get();
4676 int i, j, file_count = 0;
4677 MonoImage **modules;
4678 guint32 module_count, real_module_count;
4679 MonoTableInfo *table;
4680 guint32 cols [MONO_FILE_SIZE];
4681 MonoImage *image = assembly->assembly->image;
4683 g_assert (image != NULL);
4684 g_assert (!assembly->assembly->dynamic);
4686 table = &image->tables [MONO_TABLE_FILE];
4687 file_count = table->rows;
4689 modules = image->modules;
4690 module_count = image->module_count;
4692 real_module_count = 0;
4693 for (i = 0; i < module_count; ++i)
4695 real_module_count ++;
4697 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4698 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4700 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4702 for (i = 0; i < module_count; ++i)
4704 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4708 for (i = 0; i < file_count; ++i, ++j) {
4709 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4710 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4711 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4713 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4715 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4716 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4718 mono_array_setref (res, j, mono_module_get_object (domain, m));
4725 static MonoReflectionMethod*
4726 ves_icall_GetCurrentMethod (void)
4728 MonoMethod *m = mono_method_get_last_managed ();
4730 while (m->is_inflated)
4731 m = ((MonoMethodInflated*)m)->declaring;
4733 return mono_method_get_object (mono_domain_get (), m, NULL);
4738 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4741 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4742 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4743 //method is inflated, we should inflate it on the other class
4744 MonoGenericContext ctx;
4745 ctx.method_inst = inflated->context.method_inst;
4746 ctx.class_inst = inflated->context.class_inst;
4747 if (klass->generic_class)
4748 ctx.class_inst = klass->generic_class->context.class_inst;
4749 else if (klass->generic_container)
4750 ctx.class_inst = klass->generic_container->context.class_inst;
4751 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4754 mono_class_setup_methods (method->klass);
4755 if (method->klass->exception_type)
4757 for (i = 0; i < method->klass->method.count; ++i) {
4758 if (method->klass->methods [i] == method) {
4763 mono_class_setup_methods (klass);
4764 if (klass->exception_type)
4766 g_assert (offset >= 0 && offset < klass->method.count);
4767 return klass->methods [offset];
4770 static MonoReflectionMethod*
4771 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4775 klass = mono_class_from_mono_type (type);
4776 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4778 if (method->klass != klass) {
4779 method = mono_method_get_equivalent_method (method, klass);
4784 klass = method->klass;
4785 return mono_method_get_object (mono_domain_get (), method, klass);
4788 static MonoReflectionMethod*
4789 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4791 return mono_method_get_object (mono_domain_get (), method, NULL);
4794 static MonoReflectionMethodBody*
4795 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4797 return mono_method_body_get_object (mono_domain_get (), method);
4800 static MonoReflectionAssembly*
4801 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4803 MonoMethod *dest = NULL;
4805 MONO_ARCH_SAVE_REGS;
4807 mono_stack_walk_no_il (get_executing, &dest);
4808 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4812 static MonoReflectionAssembly*
4813 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4815 MonoDomain* domain = mono_domain_get ();
4817 MONO_ARCH_SAVE_REGS;
4819 if (!domain->entry_assembly)
4822 return mono_assembly_get_object (domain, domain->entry_assembly);
4825 static MonoReflectionAssembly*
4826 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4831 MONO_ARCH_SAVE_REGS;
4834 mono_stack_walk_no_il (get_executing, &dest);
4836 mono_stack_walk_no_il (get_caller, &dest);
4839 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4843 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4844 gboolean assembly_qualified)
4846 MonoDomain *domain = mono_object_domain (object);
4847 MonoTypeNameFormat format;
4852 format = assembly_qualified ?
4853 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4854 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4856 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4858 name = mono_type_get_name_full (object->type, format);
4862 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4867 res = mono_string_new (domain, name);
4874 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4876 MonoClass *klass = mono_class_from_mono_type (this->type);
4877 mono_class_init_or_throw (klass);
4878 return mono_security_core_clr_class_level (klass);
4882 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4884 static MonoMethod *create_culture = NULL;
4887 const char *pkey_ptr;
4889 MonoBoolean assembly_ref = 0;
4891 MONO_ARCH_SAVE_REGS;
4893 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4894 aname->major = name->major;
4895 aname->minor = name->minor;
4896 aname->build = name->build;
4897 aname->flags = name->flags;
4898 aname->revision = name->revision;
4899 aname->hashalg = name->hash_alg;
4900 aname->versioncompat = 1; /* SameMachine (default) */
4902 if (by_default_version)
4903 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4906 if (absolute != NULL && *absolute != '\0') {
4907 const gchar *prepend = "file://";
4910 codebase = g_strdup (absolute);
4915 for (i = strlen (codebase) - 1; i >= 0; i--)
4916 if (codebase [i] == '\\')
4919 if (*codebase == '/' && *(codebase + 1) == '/') {
4922 prepend = "file:///";
4926 result = g_strconcat (prepend, codebase, NULL);
4932 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4936 if (!create_culture) {
4937 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4938 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4939 g_assert (create_culture);
4940 mono_method_desc_free (desc);
4943 if (name->culture) {
4944 args [0] = mono_string_new (domain, name->culture);
4945 args [1] = &assembly_ref;
4946 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4949 if (name->public_key) {
4950 pkey_ptr = (char*)name->public_key;
4951 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4953 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4954 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4955 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4956 } else if (default_publickey) {
4957 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
4958 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
4961 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
4962 if (name->public_key_token [0]) {
4966 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
4967 p = mono_array_addr (aname->keyToken, char, 0);
4969 for (i = 0, j = 0; i < 8; i++) {
4970 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
4971 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
4974 } else if (default_token) {
4975 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4980 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
4982 MonoDomain *domain = mono_object_domain (assembly);
4983 MonoAssembly *mass = assembly->assembly;
4987 name = g_strdup_printf (
4988 "%s, Version=%d.%d.%d.%d, Culture=%s, PublicKeyToken=%s%s",
4990 mass->aname.major, mass->aname.minor, mass->aname.build, mass->aname.revision,
4991 mass->aname.culture && *mass->aname.culture? mass->aname.culture: "neutral",
4992 mass->aname.public_key_token [0] ? (char *)mass->aname.public_key_token : "null",
4993 (mass->aname.flags & ASSEMBLYREF_RETARGETABLE_FLAG) ? ", Retargetable=Yes" : "");
4995 res = mono_string_new (domain, name);
5002 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5005 MonoAssembly *mass = assembly->assembly;
5007 MONO_ARCH_SAVE_REGS;
5009 if (g_path_is_absolute (mass->image->name)) {
5010 fill_reflection_assembly_name (mono_object_domain (assembly),
5011 aname, &mass->aname, mass->image->name, TRUE,
5015 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5017 fill_reflection_assembly_name (mono_object_domain (assembly),
5018 aname, &mass->aname, absolute, TRUE, TRUE,
5025 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5028 MonoImageOpenStatus status = MONO_IMAGE_OK;
5031 MonoAssemblyName name;
5034 MONO_ARCH_SAVE_REGS;
5036 filename = mono_string_to_utf8 (fname);
5038 dirname = g_path_get_dirname (filename);
5039 replace_shadow_path (mono_domain_get (), dirname, &filename);
5042 image = mono_image_open (filename, &status);
5048 if (status == MONO_IMAGE_IMAGE_INVALID)
5049 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5051 exc = mono_get_exception_file_not_found2 (NULL, fname);
5052 mono_raise_exception (exc);
5055 res = mono_assembly_fill_assembly_name (image, &name);
5057 mono_image_close (image);
5059 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5062 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5066 mono_image_close (image);
5070 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5071 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5073 MonoBoolean result = FALSE;
5074 MonoDeclSecurityEntry entry;
5076 /* SecurityAction.RequestMinimum */
5077 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5078 *minimum = entry.blob;
5079 *minLength = entry.size;
5082 /* SecurityAction.RequestOptional */
5083 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5084 *optional = entry.blob;
5085 *optLength = entry.size;
5088 /* SecurityAction.RequestRefuse */
5089 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5090 *refused = entry.blob;
5091 *refLength = entry.size;
5099 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5103 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5105 guint32 attrs, visibility;
5107 /* we start the count from 1 because we skip the special type <Module> */
5110 for (i = 1; i < tdef->rows; ++i) {
5111 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5112 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5113 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5117 count = tdef->rows - 1;
5119 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5120 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5122 for (i = 1; i < tdef->rows; ++i) {
5123 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5124 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5125 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5126 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5128 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5130 MonoLoaderError *error;
5133 error = mono_loader_get_last_error ();
5134 g_assert (error != NULL);
5136 ex = mono_loader_error_prepare_exception (error);
5137 mono_array_setref (*exceptions, count, ex);
5139 if (mono_loader_get_last_error ())
5140 mono_loader_clear_error ();
5149 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5151 MonoArray *res = NULL;
5152 MonoArray *exceptions = NULL;
5153 MonoImage *image = NULL;
5154 MonoTableInfo *table = NULL;
5157 int i, len, ex_count;
5159 MONO_ARCH_SAVE_REGS;
5161 domain = mono_object_domain (assembly);
5163 g_assert (!assembly->assembly->dynamic);
5164 image = assembly->assembly->image;
5165 table = &image->tables [MONO_TABLE_FILE];
5166 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5168 /* Append data from all modules in the assembly */
5169 for (i = 0; i < table->rows; ++i) {
5170 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5171 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5174 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5175 /* Append the new types to the end of the array */
5176 if (mono_array_length (res2) > 0) {
5178 MonoArray *res3, *ex3;
5180 len1 = mono_array_length (res);
5181 len2 = mono_array_length (res2);
5183 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5184 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5185 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5188 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5189 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5190 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5197 /* the ReflectionTypeLoadException must have all the types (Types property),
5198 * NULL replacing types which throws an exception. The LoaderException must
5199 * contain all exceptions for NULL items.
5202 len = mono_array_length (res);
5205 for (i = 0; i < len; i++) {
5206 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5210 klass = mono_type_get_class (t->type);
5211 if ((klass != NULL) && klass->exception_type) {
5212 /* keep the class in the list */
5213 list = g_list_append (list, klass);
5214 /* and replace Type with NULL */
5215 mono_array_setref (res, i, NULL);
5222 if (list || ex_count) {
5224 MonoException *exc = NULL;
5225 MonoArray *exl = NULL;
5226 int j, length = g_list_length (list) + ex_count;
5228 mono_loader_clear_error ();
5230 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5231 /* Types for which mono_class_get () succeeded */
5232 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5233 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5234 mono_array_setref (exl, i, exc);
5236 /* Types for which it don't */
5237 for (j = 0; j < mono_array_length (exceptions); ++j) {
5238 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5240 g_assert (i < length);
5241 mono_array_setref (exl, i, exc);
5248 exc = mono_get_exception_reflection_type_load (res, exl);
5249 mono_loader_clear_error ();
5250 mono_raise_exception (exc);
5257 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5259 MonoAssemblyName aname;
5260 MonoDomain *domain = mono_object_domain (name);
5262 gboolean is_version_defined;
5263 gboolean is_token_defined;
5265 aname.public_key = NULL;
5266 val = mono_string_to_utf8 (assname);
5267 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5268 g_free ((guint8*) aname.public_key);
5273 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5274 FALSE, is_token_defined);
5276 mono_assembly_name_free (&aname);
5277 g_free ((guint8*) aname.public_key);
5283 static MonoReflectionType*
5284 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5286 MonoDomain *domain = mono_object_domain (module);
5289 MONO_ARCH_SAVE_REGS;
5291 g_assert (module->image);
5293 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5294 /* These images do not have a global type */
5297 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5298 return mono_type_get_object (domain, &klass->byval_arg);
5302 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5304 /*if (module->image)
5305 mono_image_close (module->image);*/
5309 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5311 MonoDomain *domain = mono_object_domain (module);
5313 MONO_ARCH_SAVE_REGS;
5315 g_assert (module->image);
5316 return mono_string_new (domain, module->image->guid);
5320 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5323 if (module->image && module->image->is_module_handle)
5324 return module->image->raw_data;
5327 return (gpointer) (-1);
5331 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5333 if (image->dynamic) {
5334 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5335 *pe_kind = dyn->pe_kind;
5336 *machine = dyn->machine;
5339 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5340 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5345 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5347 return (image->md_version_major << 16) | (image->md_version_minor);
5351 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5353 MonoArray *exceptions;
5356 MONO_ARCH_SAVE_REGS;
5359 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5361 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5362 for (i = 0; i < mono_array_length (exceptions); ++i) {
5363 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5365 mono_raise_exception (ex);
5372 mono_metadata_memberref_is_method (MonoImage *image, guint32 token)
5374 guint32 cols [MONO_MEMBERREF_SIZE];
5376 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5377 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5378 mono_metadata_decode_blob_size (sig, &sig);
5379 return (*sig != 0x6);
5383 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5386 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5387 mono_array_addr (type_args, MonoType*, 0));
5389 context->class_inst = NULL;
5391 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5392 mono_array_addr (method_args, MonoType*, 0));
5394 context->method_inst = NULL;
5398 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5401 int table = mono_metadata_token_table (token);
5402 int index = mono_metadata_token_index (token);
5403 MonoGenericContext context;
5405 *error = ResolveTokenError_Other;
5407 /* Validate token */
5408 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5409 (table != MONO_TABLE_TYPESPEC)) {
5410 *error = ResolveTokenError_BadTable;
5414 if (image->dynamic) {
5415 if (type_args || method_args)
5416 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5417 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5420 return &klass->byval_arg;
5423 if ((index <= 0) || (index > image->tables [table].rows)) {
5424 *error = ResolveTokenError_OutOfRange;
5428 init_generic_context_from_args (&context, type_args, method_args);
5429 klass = mono_class_get_full (image, token, &context);
5431 if (mono_loader_get_last_error ())
5432 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5435 return &klass->byval_arg;
5441 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5443 int table = mono_metadata_token_table (token);
5444 int index = mono_metadata_token_index (token);
5445 MonoGenericContext context;
5448 *error = ResolveTokenError_Other;
5450 /* Validate token */
5451 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5452 (table != MONO_TABLE_MEMBERREF)) {
5453 *error = ResolveTokenError_BadTable;
5457 if (image->dynamic) {
5458 if (type_args || method_args)
5459 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5460 /* FIXME: validate memberref token type */
5461 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5464 if ((index <= 0) || (index > image->tables [table].rows)) {
5465 *error = ResolveTokenError_OutOfRange;
5468 if ((table == MONO_TABLE_MEMBERREF) && (!mono_metadata_memberref_is_method (image, token))) {
5469 *error = ResolveTokenError_BadTable;
5473 init_generic_context_from_args (&context, type_args, method_args);
5474 method = mono_get_method_full (image, token, NULL, &context);
5476 if (mono_loader_get_last_error ())
5477 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5483 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5485 int index = mono_metadata_token_index (token);
5487 *error = ResolveTokenError_Other;
5489 /* Validate token */
5490 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5491 *error = ResolveTokenError_BadTable;
5496 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5498 if ((index <= 0) || (index >= image->heap_us.size)) {
5499 *error = ResolveTokenError_OutOfRange;
5503 /* FIXME: What to do if the index points into the middle of a string ? */
5505 return mono_ldstr (mono_domain_get (), image, index);
5508 static MonoClassField*
5509 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5512 int table = mono_metadata_token_table (token);
5513 int index = mono_metadata_token_index (token);
5514 MonoGenericContext context;
5515 MonoClassField *field;
5517 *error = ResolveTokenError_Other;
5519 /* Validate token */
5520 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5521 *error = ResolveTokenError_BadTable;
5525 if (image->dynamic) {
5526 if (type_args || method_args)
5527 mono_raise_exception (mono_get_exception_not_implemented (NULL));
5528 /* FIXME: validate memberref token type */
5529 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5532 if ((index <= 0) || (index > image->tables [table].rows)) {
5533 *error = ResolveTokenError_OutOfRange;
5536 if ((table == MONO_TABLE_MEMBERREF) && (mono_metadata_memberref_is_method (image, token))) {
5537 *error = ResolveTokenError_BadTable;
5541 init_generic_context_from_args (&context, type_args, method_args);
5542 field = mono_field_from_token (image, token, &klass, &context);
5544 if (mono_loader_get_last_error ())
5545 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5552 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5554 int table = mono_metadata_token_table (token);
5556 *error = ResolveTokenError_Other;
5559 case MONO_TABLE_TYPEDEF:
5560 case MONO_TABLE_TYPEREF:
5561 case MONO_TABLE_TYPESPEC: {
5562 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5564 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5568 case MONO_TABLE_METHOD:
5569 case MONO_TABLE_METHODSPEC: {
5570 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5572 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5576 case MONO_TABLE_FIELD: {
5577 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5579 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5583 case MONO_TABLE_MEMBERREF:
5584 if (mono_metadata_memberref_is_method (image, token)) {
5585 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5587 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5592 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5594 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5601 *error = ResolveTokenError_BadTable;
5608 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5610 int table = mono_metadata_token_table (token);
5611 int idx = mono_metadata_token_index (token);
5612 MonoTableInfo *tables = image->tables;
5617 *error = ResolveTokenError_OutOfRange;
5619 /* FIXME: Support other tables ? */
5620 if (table != MONO_TABLE_STANDALONESIG)
5626 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5629 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5631 ptr = mono_metadata_blob_heap (image, sig);
5632 len = mono_metadata_decode_blob_size (ptr, &ptr);
5634 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5635 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5639 static MonoReflectionType*
5640 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5643 int isbyref = 0, rank;
5644 char *str = mono_string_to_utf8 (smodifiers);
5647 MONO_ARCH_SAVE_REGS;
5649 klass = mono_class_from_mono_type (tb->type.type);
5651 /* logic taken from mono_reflection_parse_type(): keep in sync */
5655 if (isbyref) { /* only one level allowed by the spec */
5662 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5665 klass = mono_ptr_class_get (&klass->byval_arg);
5666 mono_class_init (klass);
5677 else if (*p != '*') { /* '*' means unknown lower bound */
5688 klass = mono_array_class_get (klass, rank);
5689 mono_class_init (klass);
5696 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5700 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5705 MONO_ARCH_SAVE_REGS;
5708 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5713 static MonoReflectionType *
5714 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5716 MonoClass *klass, *aklass;
5718 MONO_ARCH_SAVE_REGS;
5720 klass = mono_class_from_mono_type (type->type);
5721 mono_class_init_or_throw (klass);
5723 if (rank == 0) //single dimentional array
5724 aklass = mono_array_class_get (klass, 1);
5726 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5728 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5731 static MonoReflectionType *
5732 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5736 MONO_ARCH_SAVE_REGS;
5738 klass = mono_class_from_mono_type (type->type);
5739 mono_class_init_or_throw (klass);
5741 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5744 static MonoReflectionType *
5745 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5749 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
5751 pklass = mono_ptr_class_get (type->type);
5753 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5757 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5758 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5760 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5761 MonoObject *delegate;
5763 MonoMethod *method = info->method;
5765 MONO_ARCH_SAVE_REGS;
5767 mono_class_init_or_throw (delegate_class);
5769 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5771 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5772 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5776 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5778 if (method->dynamic) {
5779 /* Creating a trampoline would leak memory */
5780 func = mono_compile_method (method);
5782 func = mono_create_ftnptr (mono_domain_get (),
5783 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5786 mono_delegate_ctor_with_method (delegate, target, func, method);
5792 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5794 /* Reset the invoke impl to the default one */
5795 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5799 * Magic number to convert a time which is relative to
5800 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5802 #define EPOCH_ADJUST ((guint64)62135596800LL)
5805 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5807 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5810 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5812 convert_to_absolute_date(SYSTEMTIME *date)
5814 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5815 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5816 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5817 /* from the calendar FAQ */
5818 int a = (14 - date->wMonth) / 12;
5819 int y = date->wYear - a;
5820 int m = date->wMonth + 12 * a - 2;
5821 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5823 /* d is now the day of the week for the first of the month (0 == Sunday) */
5825 int day_of_week = date->wDayOfWeek;
5827 /* set day_in_month to the first day in the month which falls on day_of_week */
5828 int day_in_month = 1 + (day_of_week - d);
5829 if (day_in_month <= 0)
5832 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5833 date->wDay = day_in_month + (date->wDay - 1) * 7;
5834 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5841 * Return's the offset from GMT of a local time.
5843 * tm is a local time
5844 * t is the same local time as seconds.
5847 gmt_offset(struct tm *tm, time_t t)
5849 #if defined (HAVE_TM_GMTOFF)
5850 return tm->tm_gmtoff;
5855 g.tm_isdst = tm->tm_isdst;
5857 return (int)difftime(t, t2);
5862 * This is heavily based on zdump.c from glibc 2.2.
5864 * * data[0]: start of daylight saving time (in DateTime ticks).
5865 * * data[1]: end of daylight saving time (in DateTime ticks).
5866 * * data[2]: utcoffset (in TimeSpan ticks).
5867 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5868 * * name[0]: name of this timezone when not daylight saving.
5869 * * name[1]: name of this timezone when daylight saving.
5871 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5872 * the class library allows years between 1 and 9999.
5874 * Returns true on success and zero on failure.
5877 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5880 MonoDomain *domain = mono_domain_get ();
5881 struct tm start, tt;
5885 int is_daylight = 0, day;
5888 MONO_ARCH_SAVE_REGS;
5890 MONO_CHECK_ARG_NULL (data);
5891 MONO_CHECK_ARG_NULL (names);
5893 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5894 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5897 * no info is better than crashing: we'll need our own tz data
5898 * to make this work properly, anyway. The range is probably
5899 * reduced to 1970 .. 2037 because that is what mktime is
5900 * guaranteed to support (we get into an infinite loop
5904 memset (&start, 0, sizeof (start));
5907 start.tm_year = year-1900;
5909 t = mktime (&start);
5911 if ((year < 1970) || (year > 2037) || (t == -1)) {
5913 tt = *localtime (&t);
5914 strftime (tzone, sizeof (tzone), "%Z", &tt);
5915 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5916 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5920 gmtoff = gmt_offset (&start, t);
5922 /* For each day of the year, calculate the tm_gmtoff. */
5923 for (day = 0; day < 365; day++) {
5926 tt = *localtime (&t);
5928 /* Daylight saving starts or ends here. */
5929 if (gmt_offset (&tt, t) != gmtoff) {
5933 /* Try to find the exact hour when daylight saving starts/ends. */
5937 tt1 = *localtime (&t1);
5938 } while (gmt_offset (&tt1, t1) != gmtoff);
5940 /* Try to find the exact minute when daylight saving starts/ends. */
5943 tt1 = *localtime (&t1);
5944 } while (gmt_offset (&tt1, t1) == gmtoff);
5946 strftime (tzone, sizeof (tzone), "%Z", &tt);
5948 /* Write data, if we're already in daylight saving, we're done. */
5950 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5951 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5954 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5955 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
5959 /* This is only set once when we enter daylight saving. */
5960 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
5961 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
5963 gmtoff = gmt_offset (&tt, t);
5968 strftime (tzone, sizeof (tzone), "%Z", &tt);
5969 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
5970 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
5971 mono_array_set ((*data), gint64, 0, 0);
5972 mono_array_set ((*data), gint64, 1, 0);
5973 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
5974 mono_array_set ((*data), gint64, 3, 0);
5979 MonoDomain *domain = mono_domain_get ();
5980 TIME_ZONE_INFORMATION tz_info;
5985 tz_id = GetTimeZoneInformation (&tz_info);
5986 if (tz_id == TIME_ZONE_ID_INVALID)
5989 MONO_CHECK_ARG_NULL (data);
5990 MONO_CHECK_ARG_NULL (names);
5992 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
5993 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
5995 for (i = 0; i < 32; ++i)
5996 if (!tz_info.DaylightName [i])
5998 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
5999 for (i = 0; i < 32; ++i)
6000 if (!tz_info.StandardName [i])
6002 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6004 if ((year <= 1601) || (year > 30827)) {
6006 * According to MSDN, the MS time functions can't handle dates outside
6012 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6013 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6014 tz_info.StandardDate.wYear = year;
6015 convert_to_absolute_date(&tz_info.StandardDate);
6016 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6021 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6022 tz_info.DaylightDate.wYear = year;
6023 convert_to_absolute_date(&tz_info.DaylightDate);
6024 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6029 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6031 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6032 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6039 ves_icall_System_Object_obj_address (MonoObject *this)
6041 MONO_ARCH_SAVE_REGS;
6048 static inline gint32
6049 mono_array_get_byte_length (MonoArray *array)
6055 klass = array->obj.vtable->klass;
6057 if (array->bounds == NULL)
6058 length = array->max_length;
6061 for (i = 0; i < klass->rank; ++ i)
6062 length *= array->bounds [i].length;
6065 switch (klass->element_class->byval_arg.type) {
6068 case MONO_TYPE_BOOLEAN:
6072 case MONO_TYPE_CHAR:
6080 return length * sizeof (gpointer);
6091 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6093 MONO_ARCH_SAVE_REGS;
6095 return mono_array_get_byte_length (array);
6099 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6101 MONO_ARCH_SAVE_REGS;
6103 return mono_array_get (array, gint8, idx);
6107 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6109 MONO_ARCH_SAVE_REGS;
6111 mono_array_set (array, gint8, idx, value);
6115 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6117 guint8 *src_buf, *dest_buf;
6119 MONO_ARCH_SAVE_REGS;
6121 /* watch out for integer overflow */
6122 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6125 src_buf = (guint8 *)src->vector + src_offset;
6126 dest_buf = (guint8 *)dest->vector + dest_offset;
6129 memcpy (dest_buf, src_buf, count);
6131 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6137 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6139 MonoDomain *domain = mono_object_domain (this);
6141 MonoRealProxy *rp = ((MonoRealProxy *)this);
6142 MonoTransparentProxy *tp;
6146 MONO_ARCH_SAVE_REGS;
6148 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6149 tp = (MonoTransparentProxy*) res;
6151 MONO_OBJECT_SETREF (tp, rp, rp);
6152 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6153 klass = mono_class_from_mono_type (type);
6155 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6156 tp->remote_class = mono_remote_class (domain, class_name, klass);
6158 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6162 static MonoReflectionType *
6163 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6165 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6168 /* System.Environment */
6171 ves_icall_System_Environment_get_UserName (void)
6173 MONO_ARCH_SAVE_REGS;
6175 /* using glib is more portable */
6176 return mono_string_new (mono_domain_get (), g_get_user_name ());
6181 ves_icall_System_Environment_get_MachineName (void)
6183 #if defined (HOST_WIN32)
6188 len = MAX_COMPUTERNAME_LENGTH + 1;
6189 buf = g_new (gunichar2, len);
6192 if (GetComputerName (buf, (PDWORD) &len))
6193 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6197 #elif !defined(DISABLE_SOCKETS)
6201 if (gethostname (buf, sizeof (buf)) == 0)
6202 result = mono_string_new (mono_domain_get (), buf);
6208 return mono_string_new (mono_domain_get (), "mono");
6213 ves_icall_System_Environment_get_Platform (void)
6215 #if defined (TARGET_WIN32)
6218 #elif defined(__MACH__)
6221 // For compatibility with our client code, this will be 4 for a while.
6222 // We will eventually move to 6 to match .NET, but it requires all client
6223 // code to be updated and the documentation everywhere to be updated
6234 ves_icall_System_Environment_get_NewLine (void)
6236 MONO_ARCH_SAVE_REGS;
6238 #if defined (HOST_WIN32)
6239 return mono_string_new (mono_domain_get (), "\r\n");
6241 return mono_string_new (mono_domain_get (), "\n");
6246 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6251 MONO_ARCH_SAVE_REGS;
6256 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6257 value = g_getenv (utf8_name);
6264 return mono_string_new (mono_domain_get (), value);
6268 * There is no standard way to get at environ.
6271 #ifndef __MINGW32_VERSION
6273 /* Apple defines this in crt_externs.h but doesn't provide that header for
6274 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6275 * in fact exist on all implementations (so far)
6277 gchar ***_NSGetEnviron(void);
6278 #define environ (*_NSGetEnviron())
6287 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6298 env_strings = GetEnvironmentStrings();
6301 env_string = env_strings;
6302 while (*env_string != '\0') {
6303 /* weird case that MS seems to skip */
6304 if (*env_string != '=')
6306 while (*env_string != '\0')
6312 domain = mono_domain_get ();
6313 names = mono_array_new (domain, mono_defaults.string_class, n);
6317 env_string = env_strings;
6318 while (*env_string != '\0') {
6319 /* weird case that MS seems to skip */
6320 if (*env_string != '=') {
6321 equal_str = wcschr(env_string, '=');
6322 g_assert(equal_str);
6323 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6324 mono_array_setref (names, n, str);
6327 while (*env_string != '\0')
6332 FreeEnvironmentStrings (env_strings);
6344 MONO_ARCH_SAVE_REGS;
6347 for (e = environ; *e != 0; ++ e)
6350 domain = mono_domain_get ();
6351 names = mono_array_new (domain, mono_defaults.string_class, n);
6354 for (e = environ; *e != 0; ++ e) {
6355 parts = g_strsplit (*e, "=", 2);
6357 str = mono_string_new (domain, *parts);
6358 mono_array_setref (names, n, str);
6371 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6373 #if !GLIB_CHECK_VERSION(2,4,0)
6374 #define g_setenv(a,b,c) setenv(a,b,c)
6375 #define g_unsetenv(a) unsetenv(a)
6379 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6384 gunichar2 *utf16_name, *utf16_value;
6386 gchar *utf8_name, *utf8_value;
6389 MONO_ARCH_SAVE_REGS;
6392 utf16_name = mono_string_to_utf16 (name);
6393 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6394 SetEnvironmentVariable (utf16_name, NULL);
6395 g_free (utf16_name);
6399 utf16_value = mono_string_to_utf16 (value);
6401 SetEnvironmentVariable (utf16_name, utf16_value);
6403 g_free (utf16_name);
6404 g_free (utf16_value);
6406 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6408 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6409 g_unsetenv (utf8_name);
6414 utf8_value = mono_string_to_utf8_checked (value, &error);
6415 if (!mono_error_ok (&error)) {
6417 mono_error_raise_exception (&error);
6419 g_setenv (utf8_name, utf8_value, TRUE);
6422 g_free (utf8_value);
6427 ves_icall_System_Environment_Exit (int result)
6429 MONO_ARCH_SAVE_REGS;
6431 mono_threads_set_shutting_down ();
6433 mono_runtime_set_shutting_down ();
6435 /* This will kill the tp threads which cannot be suspended */
6436 mono_thread_pool_cleanup ();
6438 /* Suspend all managed threads since the runtime is going away */
6439 mono_thread_suspend_all_other_threads ();
6441 mono_runtime_quit ();
6443 /* we may need to do some cleanup here... */
6448 ves_icall_System_Environment_GetGacPath (void)
6450 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6454 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6456 #if defined (HOST_WIN32)
6457 #ifndef CSIDL_FLAG_CREATE
6458 #define CSIDL_FLAG_CREATE 0x8000
6461 WCHAR path [MAX_PATH];
6462 /* Create directory if no existing */
6463 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6467 return mono_string_new_utf16 (mono_domain_get (), path, len);
6470 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6472 return mono_string_new (mono_domain_get (), "");
6476 ves_icall_System_Environment_GetLogicalDrives (void)
6478 gunichar2 buf [128], *ptr, *dname;
6480 guint initial_size = 127, size = 128;
6483 MonoString *drivestr;
6484 MonoDomain *domain = mono_domain_get ();
6487 MONO_ARCH_SAVE_REGS;
6492 while (size > initial_size) {
6493 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6494 if (size > initial_size) {
6497 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6498 initial_size = size;
6512 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6517 while (*u16) { u16++; len ++; }
6518 drivestr = mono_string_new_utf16 (domain, dname, len);
6519 mono_array_setref (result, ndrives++, drivestr);
6530 ves_icall_System_Environment_InternalGetHome (void)
6532 MONO_ARCH_SAVE_REGS;
6534 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6537 static const char *encodings [] = {
6539 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6540 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6541 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6543 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6544 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6545 "x_unicode_2_0_utf_7",
6547 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6548 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6550 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6553 "unicodefffe", "utf_16be",
6560 * Returns the internal codepage, if the value of "int_code_page" is
6561 * 1 at entry, and we can not compute a suitable code page number,
6562 * returns the code page as a string
6565 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6570 char *codepage = NULL;
6572 int want_name = *int_code_page;
6575 *int_code_page = -1;
6576 MONO_ARCH_SAVE_REGS;
6578 g_get_charset (&cset);
6579 c = codepage = strdup (cset);
6580 for (c = codepage; *c; c++){
6581 if (isascii (*c) && isalpha (*c))
6586 /* g_print ("charset: %s\n", cset); */
6588 /* handle some common aliases */
6591 for (i = 0; p != 0; ){
6592 if ((gssize) p < 7){
6594 p = encodings [++i];
6597 if (strcmp (p, codepage) == 0){
6598 *int_code_page = code;
6601 p = encodings [++i];
6604 if (strstr (codepage, "utf_8") != NULL)
6605 *int_code_page |= 0x10000000;
6608 if (want_name && *int_code_page == -1)
6609 return mono_string_new (mono_domain_get (), cset);
6615 ves_icall_System_Environment_get_HasShutdownStarted (void)
6617 if (mono_runtime_is_shutting_down ())
6620 if (mono_domain_is_unloading (mono_domain_get ()))
6627 ves_icall_System_Environment_BroadcastSettingChange (void)
6630 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6635 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6636 MonoReflectionMethod *method,
6637 MonoArray *out_args)
6639 MONO_ARCH_SAVE_REGS;
6641 mono_message_init (mono_object_domain (this), this, method, out_args);
6645 ves_icall_IsTransparentProxy (MonoObject *proxy)
6647 MONO_ARCH_SAVE_REGS;
6652 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6658 static MonoReflectionMethod *
6659 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6660 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6664 MonoMethod **vtable;
6665 MonoMethod *res = NULL;
6667 MONO_CHECK_ARG_NULL (rtype);
6668 MONO_CHECK_ARG_NULL (rmethod);
6670 method = rmethod->method;
6671 klass = mono_class_from_mono_type (rtype->type);
6672 mono_class_init_or_throw (klass);
6674 if (MONO_CLASS_IS_INTERFACE (klass))
6677 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6680 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6681 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6687 mono_class_setup_vtable (klass);
6688 vtable = klass->vtable;
6690 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6691 gboolean variance_used = FALSE;
6692 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6693 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6695 res = vtable [offs + method->slot];
6697 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6700 if (method->slot != -1)
6701 res = vtable [method->slot];
6707 return mono_method_get_object (mono_domain_get (), res, NULL);
6711 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6716 MONO_ARCH_SAVE_REGS;
6718 klass = mono_class_from_mono_type (type->type);
6719 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6721 if (enable) vtable->remote = 1;
6722 else vtable->remote = 0;
6726 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6731 MONO_ARCH_SAVE_REGS;
6733 domain = mono_object_domain (type);
6734 klass = mono_class_from_mono_type (type->type);
6735 mono_class_init_or_throw (klass);
6737 if (klass->rank >= 1) {
6738 g_assert (klass->rank == 1);
6739 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6741 /* Bypass remoting object creation check */
6742 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6747 ves_icall_System_IO_get_temp_path (void)
6749 MONO_ARCH_SAVE_REGS;
6751 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6754 #ifndef PLATFORM_NO_DRIVEINFO
6756 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6757 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6761 ULARGE_INTEGER wapi_free_bytes_avail;
6762 ULARGE_INTEGER wapi_total_number_of_bytes;
6763 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6765 MONO_ARCH_SAVE_REGS;
6767 *error = ERROR_SUCCESS;
6768 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6769 &wapi_total_number_of_free_bytes);
6772 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6773 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6774 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6776 *free_bytes_avail = 0;
6777 *total_number_of_bytes = 0;
6778 *total_number_of_free_bytes = 0;
6779 *error = GetLastError ();
6786 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6788 MONO_ARCH_SAVE_REGS;
6790 return GetDriveType (mono_string_chars (root_path_name));
6795 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6797 MONO_ARCH_SAVE_REGS;
6799 return mono_compile_method (method);
6803 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6808 MONO_ARCH_SAVE_REGS;
6810 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6812 #if defined (HOST_WIN32)
6813 /* Avoid mixing '/' and '\\' */
6816 for (i = strlen (path) - 1; i >= 0; i--)
6817 if (path [i] == '/')
6821 mcpath = mono_string_new (mono_domain_get (), path);
6828 get_bundled_machine_config (void)
6830 const gchar *machine_config;
6832 MONO_ARCH_SAVE_REGS;
6834 machine_config = mono_get_machine_config ();
6836 if (!machine_config)
6839 return mono_string_new (mono_domain_get (), machine_config);
6843 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
6848 MONO_ARCH_SAVE_REGS;
6850 path = g_path_get_dirname (mono_get_config_dir ());
6852 #if defined (HOST_WIN32)
6853 /* Avoid mixing '/' and '\\' */
6856 for (i = strlen (path) - 1; i >= 0; i--)
6857 if (path [i] == '/')
6861 ipath = mono_string_new (mono_domain_get (), path);
6868 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
6870 MonoPEResourceDataEntry *entry;
6873 MONO_ARCH_SAVE_REGS;
6875 if (!assembly || !result || !size)
6880 image = assembly->assembly->image;
6881 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
6885 *result = mono_image_rva_map (image, entry->rde_data_offset);
6890 *size = entry->rde_size;
6896 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
6898 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
6902 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
6904 #if defined (HOST_WIN32)
6905 OutputDebugString (mono_string_chars (message));
6907 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
6911 /* Only used for value types */
6913 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
6918 MONO_ARCH_SAVE_REGS;
6920 domain = mono_object_domain (type);
6921 klass = mono_class_from_mono_type (type->type);
6922 mono_class_init_or_throw (klass);
6924 if (mono_class_is_nullable (klass))
6925 /* No arguments -> null */
6928 return mono_object_new (domain, klass);
6931 static MonoReflectionMethod *
6932 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
6934 MonoClass *klass, *parent;
6935 MonoMethod *method = m->method;
6936 MonoMethod *result = NULL;
6938 MONO_ARCH_SAVE_REGS;
6940 if (method->klass == NULL)
6943 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
6944 MONO_CLASS_IS_INTERFACE (method->klass) ||
6945 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
6948 klass = method->klass;
6949 if (klass->generic_class)
6950 klass = klass->generic_class->container_class;
6953 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
6954 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
6955 mono_class_setup_vtable (parent);
6956 if (parent->vtable_size <= method->slot)
6961 klass = klass->parent;
6966 if (klass == method->klass)
6969 result = klass->vtable [method->slot];
6970 if (result == NULL) {
6971 /* It is an abstract method */
6972 gpointer iter = NULL;
6973 while ((result = mono_class_get_methods (klass, &iter)))
6974 if (result->slot == method->slot)
6981 return mono_method_get_object (mono_domain_get (), result, NULL);
6985 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
6987 MonoMethod *method = m->method;
6989 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
6994 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
6996 MONO_ARCH_SAVE_REGS;
6998 iter->sig = *(MonoMethodSignature**)argsp;
7000 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7001 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7004 /* FIXME: it's not documented what start is exactly... */
7008 iter->args = argsp + sizeof (gpointer);
7010 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7012 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7016 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7018 guint32 i, arg_size;
7021 MONO_ARCH_SAVE_REGS;
7023 i = iter->sig->sentinelpos + iter->next_arg;
7025 g_assert (i < iter->sig->param_count);
7027 res.type = iter->sig->params [i];
7028 res.klass = mono_class_from_mono_type (res.type);
7029 res.value = iter->args;
7030 arg_size = mono_type_stack_size (res.type, &align);
7031 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7032 if (arg_size <= sizeof (gpointer)) {
7034 int padding = arg_size - mono_type_size (res.type, &dummy);
7035 res.value = (guint8*)res.value + padding;
7038 iter->args = (char*)iter->args + arg_size;
7041 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7047 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7049 guint32 i, arg_size;
7052 MONO_ARCH_SAVE_REGS;
7054 i = iter->sig->sentinelpos + iter->next_arg;
7056 g_assert (i < iter->sig->param_count);
7058 while (i < iter->sig->param_count) {
7059 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7061 res.type = iter->sig->params [i];
7062 res.klass = mono_class_from_mono_type (res.type);
7063 /* FIXME: endianess issue... */
7064 res.value = iter->args;
7065 arg_size = mono_type_stack_size (res.type, &align);
7066 iter->args = (char*)iter->args + arg_size;
7068 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7071 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7080 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7083 MONO_ARCH_SAVE_REGS;
7085 i = iter->sig->sentinelpos + iter->next_arg;
7087 g_assert (i < iter->sig->param_count);
7089 return iter->sig->params [i];
7093 mono_TypedReference_ToObject (MonoTypedRef tref)
7095 MONO_ARCH_SAVE_REGS;
7097 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7098 MonoObject** objp = tref.value;
7102 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7106 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7108 MONO_ARCH_SAVE_REGS;
7110 if (MONO_TYPE_IS_REFERENCE (type)) {
7111 MonoObject** objp = value;
7115 return mono_value_box (mono_domain_get (), klass, value);
7119 prelink_method (MonoMethod *method)
7121 const char *exc_class, *exc_arg;
7122 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7124 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7126 mono_raise_exception(
7127 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7129 /* create the wrapper, too? */
7133 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7135 MONO_ARCH_SAVE_REGS;
7136 prelink_method (method->method);
7140 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7142 MonoClass *klass = mono_class_from_mono_type (type->type);
7144 gpointer iter = NULL;
7145 MONO_ARCH_SAVE_REGS;
7147 mono_class_init_or_throw (klass);
7149 while ((m = mono_class_get_methods (klass, &iter)))
7153 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7155 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7156 gint32 const **exponents,
7157 gunichar2 const **digitLowerTable,
7158 gunichar2 const **digitUpperTable,
7159 gint64 const **tenPowersList,
7160 gint32 const **decHexDigits)
7162 *mantissas = Formatter_MantissaBitsTable;
7163 *exponents = Formatter_TensExponentTable;
7164 *digitLowerTable = Formatter_DigitLowerTable;
7165 *digitUpperTable = Formatter_DigitUpperTable;
7166 *tenPowersList = Formatter_TenPowersList;
7167 *decHexDigits = Formatter_DecHexDigits;
7170 /* These parameters are "readonly" in corlib/System/Char.cs */
7172 ves_icall_System_Char_GetDataTablePointers (guint8 const **category_data,
7173 guint8 const **numeric_data,
7174 gdouble const **numeric_data_values,
7175 guint16 const **to_lower_data_low,
7176 guint16 const **to_lower_data_high,
7177 guint16 const **to_upper_data_low,
7178 guint16 const **to_upper_data_high)
7180 *category_data = CategoryData;
7181 *numeric_data = NumericData;
7182 *numeric_data_values = NumericDataValues;
7183 *to_lower_data_low = ToLowerDataLow;
7184 *to_lower_data_high = ToLowerDataHigh;
7185 *to_upper_data_low = ToUpperDataLow;
7186 *to_upper_data_high = ToUpperDataHigh;
7190 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7192 return method->method->token;
7196 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7197 * and avoid useless allocations.
7200 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7204 for (i = 0; i < type->num_mods; ++i) {
7205 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7210 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7212 for (i = 0; i < type->num_mods; ++i) {
7213 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7214 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7215 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7223 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7225 MonoType *type = param->ClassImpl->type;
7226 MonoClass *member_class = mono_object_class (param->MemberImpl);
7227 MonoMethod *method = NULL;
7230 MonoMethodSignature *sig;
7232 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7233 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7234 method = rmethod->method;
7235 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7236 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7237 if (!(method = prop->property->get))
7238 method = prop->property->set;
7241 char *type_name = mono_type_get_full_name (member_class);
7242 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7243 MonoException *ex = mono_get_exception_not_supported (msg);
7246 mono_raise_exception (ex);
7249 image = method->klass->image;
7250 pos = param->PositionImpl;
7251 sig = mono_method_signature (method);
7255 type = sig->params [pos];
7257 return type_array_from_modifiers (image, type, optional);
7261 get_property_type (MonoProperty *prop)
7263 MonoMethodSignature *sig;
7265 sig = mono_method_signature (prop->get);
7267 } else if (prop->set) {
7268 sig = mono_method_signature (prop->set);
7269 return sig->params [sig->param_count - 1];
7275 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7277 MonoType *type = get_property_type (property->property);
7278 MonoImage *image = property->klass->image;
7282 return type_array_from_modifiers (image, type, optional);
7286 *Construct a MonoType suited to be used to decode a constant blob object.
7288 * @type is the target type which will be constructed
7289 * @blob_type is the blob type, for example, that comes from the constant table
7290 * @real_type is the expected constructed type.
7293 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7295 type->type = blob_type;
7296 type->data.klass = NULL;
7297 if (blob_type == MONO_TYPE_CLASS)
7298 type->data.klass = mono_defaults.object_class;
7299 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7300 /* For enums, we need to use the base type */
7301 type->type = MONO_TYPE_VALUETYPE;
7302 type->data.klass = mono_class_from_mono_type (real_type);
7304 type->data.klass = mono_class_from_mono_type (real_type);
7308 property_info_get_default_value (MonoReflectionProperty *property)
7311 MonoProperty *prop = property->property;
7312 MonoType *type = get_property_type (prop);
7313 MonoDomain *domain = mono_object_domain (property);
7314 MonoTypeEnum def_type;
7315 const char *def_value;
7318 g_assert (!prop->parent->image->dynamic);
7320 mono_class_init (prop->parent);
7322 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7323 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7325 def_value = mono_class_get_property_default_value (prop, &def_type);
7327 mono_type_from_blob_type (&blob_type, def_type, type);
7328 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7334 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7336 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7337 MonoCustomAttrInfo *cinfo;
7340 mono_class_init_or_throw (attr_class);
7342 cinfo = mono_reflection_get_custom_attrs_info (obj);
7345 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7347 mono_custom_attrs_free (cinfo);
7352 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7354 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7358 mono_class_init_or_throw (attr_class);
7360 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class);
7362 if (mono_loader_get_last_error ()) {
7363 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7364 g_assert_not_reached ();
7373 ves_icall_Mono_Runtime_GetDisplayName (void)
7376 MonoString *display_name;
7378 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7379 display_name = mono_string_new (mono_domain_get (), info);
7381 return display_name;
7385 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7387 MonoString *message;
7391 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7392 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7395 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7397 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7405 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7406 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7407 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7408 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7409 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7410 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7411 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7412 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7416 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7421 gunichar2 last, prev_last, prev2_last;
7429 last = prev_last = 0, prev2_last = 0;
7430 for (i = 0; i < ilength; i++) {
7432 if (c >= sizeof (dbase64)) {
7433 exc = mono_exception_from_name_msg (mono_get_corlib (),
7434 "System", "FormatException",
7435 "Invalid character found.");
7436 mono_raise_exception (exc);
7437 } else if (isspace (c)) {
7440 prev2_last = prev_last;
7446 olength = ilength - ignored;
7448 if (allowWhitespaceOnly && olength == 0) {
7449 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7452 if ((olength & 3) != 0 || olength <= 0) {
7453 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7454 "FormatException", "Invalid length.");
7455 mono_raise_exception (exc);
7458 if (prev2_last == '=') {
7459 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7460 mono_raise_exception (exc);
7463 olength = (olength * 3) / 4;
7467 if (prev_last == '=')
7470 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7471 res_ptr = mono_array_addr (result, guchar, 0);
7472 for (i = 0; i < ilength; ) {
7475 for (k = 0; k < 4 && i < ilength;) {
7481 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7482 exc = mono_exception_from_name_msg (mono_get_corlib (),
7483 "System", "FormatException",
7484 "Invalid character found.");
7485 mono_raise_exception (exc);
7490 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7492 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7494 *res_ptr++ = (b [2] << 6) | b [3];
7496 while (i < ilength && isspace (start [i]))
7504 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7506 MONO_ARCH_SAVE_REGS;
7508 return base64_to_byte_array (mono_string_chars (str),
7509 mono_string_length (str), allowWhitespaceOnly);
7513 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7515 MONO_ARCH_SAVE_REGS;
7517 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7521 #define ICALL_TYPE(id,name,first)
7522 #define ICALL(id,name,func) Icall_ ## id,
7525 #include "metadata/icall-def.h"
7531 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7532 #define ICALL(id,name,func)
7534 #include "metadata/icall-def.h"
7540 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7541 #define ICALL(id,name,func)
7543 guint16 first_icall;
7546 static const IcallTypeDesc
7547 icall_type_descs [] = {
7548 #include "metadata/icall-def.h"
7552 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7555 #define ICALL_TYPE(id,name,first)
7558 #ifdef HAVE_ARRAY_ELEM_INIT
7559 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7560 #define MSGSTRFIELD1(line) str##line
7562 static const struct msgstrtn_t {
7563 #define ICALL(id,name,func)
7565 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7566 #include "metadata/icall-def.h"
7568 } icall_type_names_str = {
7569 #define ICALL_TYPE(id,name,first) (name),
7570 #include "metadata/icall-def.h"
7573 static const guint16 icall_type_names_idx [] = {
7574 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7575 #include "metadata/icall-def.h"
7578 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7580 static const struct msgstr_t {
7582 #define ICALL_TYPE(id,name,first)
7583 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7584 #include "metadata/icall-def.h"
7586 } icall_names_str = {
7587 #define ICALL(id,name,func) (name),
7588 #include "metadata/icall-def.h"
7591 static const guint16 icall_names_idx [] = {
7592 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7593 #include "metadata/icall-def.h"
7596 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7602 #define ICALL_TYPE(id,name,first) name,
7603 #define ICALL(id,name,func)
7604 static const char* const
7605 icall_type_names [] = {
7606 #include "metadata/icall-def.h"
7610 #define icall_type_name_get(id) (icall_type_names [(id)])
7614 #define ICALL_TYPE(id,name,first)
7615 #define ICALL(id,name,func) name,
7616 static const char* const
7618 #include "metadata/icall-def.h"
7621 #define icall_name_get(id) icall_names [(id)]
7623 #endif /* !HAVE_ARRAY_ELEM_INIT */
7627 #define ICALL_TYPE(id,name,first)
7628 #define ICALL(id,name,func) func,
7629 static const gconstpointer
7630 icall_functions [] = {
7631 #include "metadata/icall-def.h"
7635 static GHashTable *icall_hash = NULL;
7636 static GHashTable *jit_icall_hash_name = NULL;
7637 static GHashTable *jit_icall_hash_addr = NULL;
7640 mono_icall_init (void)
7644 /* check that tables are sorted: disable in release */
7647 const char *prev_class = NULL;
7648 const char *prev_method;
7650 for (i = 0; i < Icall_type_num; ++i) {
7651 const IcallTypeDesc *desc;
7654 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7655 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7656 prev_class = icall_type_name_get (i);
7657 desc = &icall_type_descs [i];
7658 num_icalls = icall_desc_num_icalls (desc);
7659 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7660 for (j = 0; j < num_icalls; ++j) {
7661 const char *methodn = icall_name_get (desc->first_icall + j);
7662 if (prev_method && strcmp (prev_method, methodn) >= 0)
7663 g_print ("method %s should come before method %s\n", methodn, prev_method);
7664 prev_method = methodn;
7669 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7673 mono_icall_cleanup (void)
7675 g_hash_table_destroy (icall_hash);
7676 g_hash_table_destroy (jit_icall_hash_name);
7677 g_hash_table_destroy (jit_icall_hash_addr);
7681 mono_add_internal_call (const char *name, gconstpointer method)
7683 mono_loader_lock ();
7685 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7687 mono_loader_unlock ();
7690 #ifdef HAVE_ARRAY_ELEM_INIT
7692 compare_method_imap (const void *key, const void *elem)
7694 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7695 return strcmp (key, method_name);
7699 find_method_icall (const IcallTypeDesc *imap, const char *name)
7701 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7704 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7708 compare_class_imap (const void *key, const void *elem)
7710 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7711 return strcmp (key, class_name);
7714 static const IcallTypeDesc*
7715 find_class_icalls (const char *name)
7717 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7720 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7725 compare_method_imap (const void *key, const void *elem)
7727 const char** method_name = (const char**)elem;
7728 return strcmp (key, *method_name);
7732 find_method_icall (const IcallTypeDesc *imap, const char *name)
7734 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
7737 return (gpointer)icall_functions [(nameslot - icall_names)];
7741 compare_class_imap (const void *key, const void *elem)
7743 const char** class_name = (const char**)elem;
7744 return strcmp (key, *class_name);
7747 static const IcallTypeDesc*
7748 find_class_icalls (const char *name)
7750 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
7753 return &icall_type_descs [nameslot - icall_type_names];
7759 * we should probably export this as an helper (handle nested types).
7760 * Returns the number of chars written in buf.
7763 concat_class_name (char *buf, int bufsize, MonoClass *klass)
7765 int nspacelen, cnamelen;
7766 nspacelen = strlen (klass->name_space);
7767 cnamelen = strlen (klass->name);
7768 if (nspacelen + cnamelen + 2 > bufsize)
7771 memcpy (buf, klass->name_space, nspacelen);
7772 buf [nspacelen ++] = '.';
7774 memcpy (buf + nspacelen, klass->name, cnamelen);
7775 buf [nspacelen + cnamelen] = 0;
7776 return nspacelen + cnamelen;
7780 mono_lookup_internal_call (MonoMethod *method)
7785 int typelen = 0, mlen, siglen;
7787 const IcallTypeDesc *imap;
7789 g_assert (method != NULL);
7791 if (method->is_inflated)
7792 method = ((MonoMethodInflated *) method)->declaring;
7794 if (method->klass->nested_in) {
7795 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
7799 mname [pos++] = '/';
7802 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
7808 typelen = concat_class_name (mname, sizeof (mname), method->klass);
7813 imap = find_class_icalls (mname);
7815 mname [typelen] = ':';
7816 mname [typelen + 1] = ':';
7818 mlen = strlen (method->name);
7819 memcpy (mname + typelen + 2, method->name, mlen);
7820 sigstart = mname + typelen + 2 + mlen;
7823 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
7824 siglen = strlen (tmpsig);
7825 if (typelen + mlen + siglen + 6 > sizeof (mname))
7828 memcpy (sigstart + 1, tmpsig, siglen);
7829 sigstart [siglen + 1] = ')';
7830 sigstart [siglen + 2] = 0;
7833 mono_loader_lock ();
7835 res = g_hash_table_lookup (icall_hash, mname);
7837 mono_loader_unlock ();
7840 /* try without signature */
7842 res = g_hash_table_lookup (icall_hash, mname);
7844 mono_loader_unlock ();
7848 /* it wasn't found in the static call tables */
7850 mono_loader_unlock ();
7853 res = find_method_icall (imap, sigstart - mlen);
7855 mono_loader_unlock ();
7858 /* try _with_ signature */
7860 res = find_method_icall (imap, sigstart - mlen);
7862 mono_loader_unlock ();
7866 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
7867 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
7868 g_print ("The out of sync library is: %s\n", method->klass->image->name);
7869 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
7870 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");
7871 g_print ("If you see other errors or faults after this message they are probably related\n");
7872 g_print ("and you need to fix your mono install first.\n");
7874 mono_loader_unlock ();
7880 type_from_typename (char *typename)
7882 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
7884 if (!strcmp (typename, "int"))
7885 klass = mono_defaults.int_class;
7886 else if (!strcmp (typename, "ptr"))
7887 klass = mono_defaults.int_class;
7888 else if (!strcmp (typename, "void"))
7889 klass = mono_defaults.void_class;
7890 else if (!strcmp (typename, "int32"))
7891 klass = mono_defaults.int32_class;
7892 else if (!strcmp (typename, "uint32"))
7893 klass = mono_defaults.uint32_class;
7894 else if (!strcmp (typename, "int8"))
7895 klass = mono_defaults.sbyte_class;
7896 else if (!strcmp (typename, "uint8"))
7897 klass = mono_defaults.byte_class;
7898 else if (!strcmp (typename, "int16"))
7899 klass = mono_defaults.int16_class;
7900 else if (!strcmp (typename, "uint16"))
7901 klass = mono_defaults.uint16_class;
7902 else if (!strcmp (typename, "long"))
7903 klass = mono_defaults.int64_class;
7904 else if (!strcmp (typename, "ulong"))
7905 klass = mono_defaults.uint64_class;
7906 else if (!strcmp (typename, "float"))
7907 klass = mono_defaults.single_class;
7908 else if (!strcmp (typename, "double"))
7909 klass = mono_defaults.double_class;
7910 else if (!strcmp (typename, "object"))
7911 klass = mono_defaults.object_class;
7912 else if (!strcmp (typename, "obj"))
7913 klass = mono_defaults.object_class;
7914 else if (!strcmp (typename, "string"))
7915 klass = mono_defaults.string_class;
7916 else if (!strcmp (typename, "bool"))
7917 klass = mono_defaults.boolean_class;
7918 else if (!strcmp (typename, "boolean"))
7919 klass = mono_defaults.boolean_class;
7921 g_error ("%s", typename);
7922 g_assert_not_reached ();
7924 return &klass->byval_arg;
7927 MonoMethodSignature*
7928 mono_create_icall_signature (const char *sigstr)
7933 MonoMethodSignature *res;
7935 mono_loader_lock ();
7936 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
7938 mono_loader_unlock ();
7942 parts = g_strsplit (sigstr, " ", 256);
7951 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
7956 * Under windows, the default pinvoke calling convention is STDCALL but
7959 res->call_convention = MONO_CALL_C;
7962 res->ret = type_from_typename (parts [0]);
7963 for (i = 1; i < len; ++i) {
7964 res->params [i - 1] = type_from_typename (parts [i]);
7969 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
7971 mono_loader_unlock ();
7977 mono_find_jit_icall_by_name (const char *name)
7979 MonoJitICallInfo *info;
7980 g_assert (jit_icall_hash_name);
7982 mono_loader_lock ();
7983 info = g_hash_table_lookup (jit_icall_hash_name, name);
7984 mono_loader_unlock ();
7989 mono_find_jit_icall_by_addr (gconstpointer addr)
7991 MonoJitICallInfo *info;
7992 g_assert (jit_icall_hash_addr);
7994 mono_loader_lock ();
7995 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
7996 mono_loader_unlock ();
8002 * mono_get_jit_icall_info:
8004 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8005 * caller should access it while holding the loader lock.
8008 mono_get_jit_icall_info (void)
8010 return jit_icall_hash_name;
8014 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8016 mono_loader_lock ();
8017 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8018 mono_loader_unlock ();
8022 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8024 MonoJitICallInfo *info;
8029 mono_loader_lock ();
8031 if (!jit_icall_hash_name) {
8032 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8033 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8036 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8037 g_warning ("jit icall already defined \"%s\"\n", name);
8038 g_assert_not_reached ();
8041 info = g_new0 (MonoJitICallInfo, 1);
8048 info->wrapper = func;
8050 info->wrapper = NULL;
8053 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8054 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8056 mono_loader_unlock ();