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)
11 * Copyright 2011-2012 Xamarin Inc (http://www.xamarin.com).
22 #ifdef HAVE_SYS_TIME_H
28 #if defined (HOST_WIN32)
31 #if defined (HAVE_WCHAR_H)
35 #include "mono/utils/mono-membar.h"
36 #include <mono/metadata/object.h>
37 #include <mono/metadata/threads.h>
38 #include <mono/metadata/threads-types.h>
39 #include <mono/metadata/threadpool.h>
40 #include <mono/metadata/monitor.h>
41 #include <mono/metadata/reflection.h>
42 #include <mono/metadata/assembly.h>
43 #include <mono/metadata/tabledefs.h>
44 #include <mono/metadata/exception.h>
45 #include <mono/metadata/file-io.h>
46 #include <mono/metadata/console-io.h>
47 #include <mono/metadata/socket-io.h>
48 #include <mono/metadata/mono-endian.h>
49 #include <mono/metadata/tokentype.h>
50 #include <mono/metadata/domain-internals.h>
51 #include <mono/metadata/metadata-internals.h>
52 #include <mono/metadata/class-internals.h>
53 #include <mono/metadata/marshal.h>
54 #include <mono/metadata/gc-internal.h>
55 #include <mono/metadata/mono-gc.h>
56 #include <mono/metadata/rand.h>
57 #include <mono/metadata/sysmath.h>
58 #include <mono/metadata/string-icalls.h>
59 #include <mono/metadata/debug-helpers.h>
60 #include <mono/metadata/process.h>
61 #include <mono/metadata/environment.h>
62 #include <mono/metadata/profiler-private.h>
63 #include <mono/metadata/locales.h>
64 #include <mono/metadata/filewatcher.h>
65 #include <mono/metadata/char-conversions.h>
66 #include <mono/metadata/security.h>
67 #include <mono/metadata/mono-config.h>
68 #include <mono/metadata/cil-coff.h>
69 #include <mono/metadata/number-formatter.h>
70 #include <mono/metadata/security-manager.h>
71 #include <mono/metadata/security-core-clr.h>
72 #include <mono/metadata/mono-perfcounters.h>
73 #include <mono/metadata/mono-debug.h>
74 #include <mono/metadata/mono-ptr-array.h>
75 #include <mono/metadata/verify-internals.h>
76 #include <mono/io-layer/io-layer.h>
77 #include <mono/utils/strtod.h>
78 #include <mono/utils/monobitset.h>
79 #include <mono/utils/mono-time.h>
80 #include <mono/utils/mono-proclib.h>
81 #include <mono/utils/mono-string.h>
82 #include <mono/utils/mono-error-internals.h>
83 #include <mono/utils/mono-mmap.h>
84 #include <mono/utils/mono-io-portability.h>
85 #include <mono/utils/mono-digest.h>
87 #if defined (HOST_WIN32)
93 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
95 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
98 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
100 static inline MonoBoolean
101 is_generic_parameter (MonoType *type)
103 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
107 mono_class_init_or_throw (MonoClass *klass)
109 if (!mono_class_init (klass))
110 mono_raise_exception (mono_class_get_exception_for_failure (klass));
114 * We expect a pointer to a char, not a string
116 ICALL_EXPORT gboolean
117 mono_double_ParseImpl (char *ptr, double *result)
119 gchar *endptr = NULL;
126 *result = strtod (ptr, &endptr);
129 /* mono_strtod () is not thread-safe */
130 EnterCriticalSection (&mono_strtod_mutex);
131 *result = mono_strtod (ptr, &endptr);
132 LeaveCriticalSection (&mono_strtod_mutex);
136 if (!*ptr || (endptr && *endptr))
142 ICALL_EXPORT MonoObject *
143 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
152 ao = (MonoArray *)this;
153 ac = (MonoClass *)ao->obj.vtable->klass;
155 esize = mono_array_element_size (ac);
156 ea = (gpointer*)((char*)ao->vector + (pos * esize));
158 if (ac->element_class->valuetype)
159 return mono_value_box (this->vtable->domain, ac->element_class, ea);
164 ICALL_EXPORT MonoObject *
165 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
173 MONO_CHECK_ARG_NULL (idxs);
175 io = (MonoArray *)idxs;
176 ic = (MonoClass *)io->obj.vtable->klass;
178 ao = (MonoArray *)this;
179 ac = (MonoClass *)ao->obj.vtable->klass;
181 g_assert (ic->rank == 1);
182 if (io->bounds != NULL || io->max_length != ac->rank)
183 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
185 ind = (gint32 *)io->vector;
187 if (ao->bounds == NULL) {
188 if (*ind < 0 || *ind >= ao->max_length)
189 mono_raise_exception (mono_get_exception_index_out_of_range ());
191 return ves_icall_System_Array_GetValueImpl (this, *ind);
194 for (i = 0; i < ac->rank; i++)
195 if ((ind [i] < ao->bounds [i].lower_bound) ||
196 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
197 mono_raise_exception (mono_get_exception_index_out_of_range ());
199 pos = ind [0] - ao->bounds [0].lower_bound;
200 for (i = 1; i < ac->rank; i++)
201 pos = pos*ao->bounds [i].length + ind [i] -
202 ao->bounds [i].lower_bound;
204 return ves_icall_System_Array_GetValueImpl (this, pos);
208 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
210 MonoClass *ac, *vc, *ec;
222 vc = value->vtable->klass;
226 ac = this->obj.vtable->klass;
227 ec = ac->element_class;
229 esize = mono_array_element_size (ac);
230 ea = (gpointer*)((char*)this->vector + (pos * esize));
231 va = (gpointer*)((char*)value + sizeof (MonoObject));
233 if (mono_class_is_nullable (ec)) {
234 mono_nullable_init ((guint8*)ea, value, ec);
239 mono_gc_bzero (ea, esize);
243 #define NO_WIDENING_CONVERSION G_STMT_START{\
244 mono_raise_exception (mono_get_exception_argument ( \
245 "value", "not a widening conversion")); \
248 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
249 if (esize < vsize + (extra)) \
250 mono_raise_exception (mono_get_exception_argument ( \
251 "value", "not a widening conversion")); \
254 #define INVALID_CAST G_STMT_START{ \
255 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
256 mono_raise_exception (mono_get_exception_invalid_cast ()); \
259 /* Check element (destination) type. */
260 switch (ec->byval_arg.type) {
261 case MONO_TYPE_STRING:
262 switch (vc->byval_arg.type) {
263 case MONO_TYPE_STRING:
269 case MONO_TYPE_BOOLEAN:
270 switch (vc->byval_arg.type) {
271 case MONO_TYPE_BOOLEAN:
284 NO_WIDENING_CONVERSION;
291 if (!ec->valuetype) {
292 if (!mono_object_isinst (value, ec))
294 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
298 if (mono_object_isinst (value, ec)) {
299 if (ec->has_references)
300 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
302 mono_gc_memmove (ea, (char *)value + sizeof (MonoObject), esize);
309 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
311 et = ec->byval_arg.type;
312 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
313 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
315 vt = vc->byval_arg.type;
316 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
317 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
319 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
325 case MONO_TYPE_CHAR: \
326 CHECK_WIDENING_CONVERSION(0); \
327 *(etype *) ea = (etype) u64; \
329 /* You can't assign a signed value to an unsigned array. */ \
334 /* You can't assign a floating point number to an integer array. */ \
337 NO_WIDENING_CONVERSION; \
341 #define ASSIGN_SIGNED(etype) G_STMT_START{\
347 CHECK_WIDENING_CONVERSION(0); \
348 *(etype *) ea = (etype) i64; \
350 /* You can assign an unsigned value to a signed array if the array's */ \
351 /* element size is larger than the value size. */ \
356 case MONO_TYPE_CHAR: \
357 CHECK_WIDENING_CONVERSION(1); \
358 *(etype *) ea = (etype) u64; \
360 /* You can't assign a floating point number to an integer array. */ \
363 NO_WIDENING_CONVERSION; \
367 #define ASSIGN_REAL(etype) G_STMT_START{\
371 CHECK_WIDENING_CONVERSION(0); \
372 *(etype *) ea = (etype) r64; \
374 /* All integer values fit into a floating point array, so we don't */ \
375 /* need to CHECK_WIDENING_CONVERSION here. */ \
380 *(etype *) ea = (etype) i64; \
386 case MONO_TYPE_CHAR: \
387 *(etype *) ea = (etype) u64; \
394 u64 = *(guint8 *) va;
397 u64 = *(guint16 *) va;
400 u64 = *(guint32 *) va;
403 u64 = *(guint64 *) va;
409 i64 = *(gint16 *) va;
412 i64 = *(gint32 *) va;
415 i64 = *(gint64 *) va;
418 r64 = *(gfloat *) va;
421 r64 = *(gdouble *) va;
424 u64 = *(guint16 *) va;
426 case MONO_TYPE_BOOLEAN:
427 /* Boolean is only compatible with itself. */
440 NO_WIDENING_CONVERSION;
447 /* If we can't do a direct copy, let's try a widening conversion. */
450 ASSIGN_UNSIGNED (guint16);
452 ASSIGN_UNSIGNED (guint8);
454 ASSIGN_UNSIGNED (guint16);
456 ASSIGN_UNSIGNED (guint32);
458 ASSIGN_UNSIGNED (guint64);
460 ASSIGN_SIGNED (gint8);
462 ASSIGN_SIGNED (gint16);
464 ASSIGN_SIGNED (gint32);
466 ASSIGN_SIGNED (gint64);
468 ASSIGN_REAL (gfloat);
470 ASSIGN_REAL (gdouble);
474 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
478 #undef NO_WIDENING_CONVERSION
479 #undef CHECK_WIDENING_CONVERSION
480 #undef ASSIGN_UNSIGNED
486 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
494 MONO_CHECK_ARG_NULL (idxs);
496 ic = idxs->obj.vtable->klass;
497 ac = this->obj.vtable->klass;
499 g_assert (ic->rank == 1);
500 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
501 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
503 ind = (gint32 *)idxs->vector;
505 if (this->bounds == NULL) {
506 if (*ind < 0 || *ind >= this->max_length)
507 mono_raise_exception (mono_get_exception_index_out_of_range ());
509 ves_icall_System_Array_SetValueImpl (this, value, *ind);
513 for (i = 0; i < ac->rank; i++)
514 if ((ind [i] < this->bounds [i].lower_bound) ||
515 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
516 mono_raise_exception (mono_get_exception_index_out_of_range ());
518 pos = ind [0] - this->bounds [0].lower_bound;
519 for (i = 1; i < ac->rank; i++)
520 pos = pos * this->bounds [i].length + ind [i] -
521 this->bounds [i].lower_bound;
523 ves_icall_System_Array_SetValueImpl (this, value, pos);
526 ICALL_EXPORT MonoArray *
527 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
529 MonoClass *aklass, *klass;
532 gboolean bounded = FALSE;
536 MONO_CHECK_ARG_NULL (type);
537 MONO_CHECK_ARG_NULL (lengths);
539 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
541 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
543 for (i = 0; i < mono_array_length (lengths); i++)
544 if (mono_array_get (lengths, gint32, i) < 0)
545 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
547 klass = mono_class_from_mono_type (type->type);
548 mono_class_init_or_throw (klass);
550 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
551 /* vectors are not the same as one dimensional arrays with no-zero bounds */
556 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
558 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
559 for (i = 0; i < aklass->rank; ++i) {
560 sizes [i] = mono_array_get (lengths, guint32, i);
562 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
564 sizes [i + aklass->rank] = 0;
567 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
572 ICALL_EXPORT MonoArray *
573 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
575 MonoClass *aklass, *klass;
578 gboolean bounded = FALSE;
582 MONO_CHECK_ARG_NULL (type);
583 MONO_CHECK_ARG_NULL (lengths);
585 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
587 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
589 for (i = 0; i < mono_array_length (lengths); i++)
590 if ((mono_array_get (lengths, gint64, i) < 0) ||
591 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
592 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
594 klass = mono_class_from_mono_type (type->type);
595 mono_class_init_or_throw (klass);
597 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
598 /* vectors are not the same as one dimensional arrays with no-zero bounds */
603 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
605 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
606 for (i = 0; i < aklass->rank; ++i) {
607 sizes [i] = mono_array_get (lengths, guint64, i);
609 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
611 sizes [i + aklass->rank] = 0;
614 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
620 ves_icall_System_Array_GetRank (MonoObject *this)
624 return this->vtable->klass->rank;
628 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
630 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
635 if ((dimension < 0) || (dimension >= rank))
636 mono_raise_exception (mono_get_exception_index_out_of_range ());
638 if (this->bounds == NULL)
639 length = this->max_length;
641 length = this->bounds [dimension].length;
643 #ifdef MONO_BIG_ARRAYS
644 if (length > G_MAXINT32)
645 mono_raise_exception (mono_get_exception_overflow ());
651 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
653 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
657 if ((dimension < 0) || (dimension >= rank))
658 mono_raise_exception (mono_get_exception_index_out_of_range ());
660 if (this->bounds == NULL)
661 return this->max_length;
663 return this->bounds [dimension].length;
667 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
669 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
673 if ((dimension < 0) || (dimension >= rank))
674 mono_raise_exception (mono_get_exception_index_out_of_range ());
676 if (this->bounds == NULL)
679 return this->bounds [dimension].lower_bound;
683 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
685 int sz = mono_array_element_size (mono_object_class (arr));
686 mono_gc_bzero (mono_array_addr_with_size (arr, sz, idx), length * sz);
689 ICALL_EXPORT gboolean
690 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
695 MonoClass *src_class;
696 MonoClass *dest_class;
700 if (source->obj.vtable->klass->rank != dest->obj.vtable->klass->rank)
703 if (source->bounds || dest->bounds)
706 /* there's no integer overflow since mono_array_length returns an unsigned integer */
707 if ((dest_idx + length > mono_array_length (dest)) ||
708 (source_idx + length > mono_array_length (source)))
711 src_class = source->obj.vtable->klass->element_class;
712 dest_class = dest->obj.vtable->klass->element_class;
715 * Handle common cases.
718 /* Case1: object[] -> valuetype[] (ArrayList::ToArray) */
719 if (src_class == mono_defaults.object_class && dest_class->valuetype) {
720 // FIXME: This is racy
724 int has_refs = dest_class->has_references;
725 for (i = source_idx; i < source_idx + length; ++i) {
726 MonoObject *elem = mono_array_get (source, MonoObject*, i);
727 if (elem && !mono_object_isinst (elem, dest_class))
731 element_size = mono_array_element_size (dest->obj.vtable->klass);
732 memset (mono_array_addr_with_size (dest, element_size, dest_idx), 0, element_size * length);
733 for (i = 0; i < length; ++i) {
734 MonoObject *elem = mono_array_get (source, MonoObject*, source_idx + i);
735 void *addr = mono_array_addr_with_size (dest, element_size, dest_idx + i);
739 mono_value_copy (addr, (char *)elem + sizeof (MonoObject), dest_class);
741 memcpy (addr, (char *)elem + sizeof (MonoObject), element_size);
747 /* Check if we're copying a char[] <==> (u)short[] */
748 if (src_class != dest_class) {
749 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
752 if (mono_class_is_subclass_of (src_class, dest_class, FALSE))
754 /* Case2: object[] -> reftype[] (ArrayList::ToArray) */
755 else if (mono_class_is_subclass_of (dest_class, src_class, FALSE)) {
756 // FIXME: This is racy
760 for (i = source_idx; i < source_idx + length; ++i) {
761 MonoObject *elem = mono_array_get (source, MonoObject*, i);
762 if (elem && !mono_object_isinst (elem, dest_class))
770 if (dest_class->valuetype) {
771 element_size = mono_array_element_size (source->obj.vtable->klass);
772 source_addr = mono_array_addr_with_size (source, element_size, source_idx);
773 if (dest_class->has_references) {
774 mono_value_copy_array (dest, dest_idx, source_addr, length);
776 dest_addr = mono_array_addr_with_size (dest, element_size, dest_idx);
777 mono_gc_memmove (dest_addr, source_addr, element_size * length);
780 mono_array_memcpy_refs (dest, dest_idx, source, source_idx, length);
787 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
796 ao = (MonoArray *)this;
797 ac = (MonoClass *)ao->obj.vtable->klass;
799 esize = mono_array_element_size (ac);
800 ea = (gpointer*)((char*)ao->vector + (pos * esize));
802 mono_gc_memmove (value, ea, esize);
806 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
815 ao = (MonoArray *)this;
816 ac = (MonoClass *)ao->obj.vtable->klass;
817 ec = ac->element_class;
819 esize = mono_array_element_size (ac);
820 ea = (gpointer*)((char*)ao->vector + (pos * esize));
822 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
823 g_assert (esize == sizeof (gpointer));
824 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
826 g_assert (ec->inited);
827 g_assert (esize == mono_class_value_size (ec, NULL));
828 if (ec->has_references)
829 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
831 mono_gc_memmove (ea, value, esize);
836 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
838 MonoClass *klass = array->obj.vtable->klass;
839 guint32 size = mono_array_element_size (klass);
840 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
842 const char *field_data;
844 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
845 MonoException *exc = mono_get_exception_argument("array",
846 "Cannot initialize array of non-primitive type.");
847 mono_raise_exception (exc);
850 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
851 MonoException *exc = mono_get_exception_argument("field_handle",
852 "Field doesn't have an RVA");
853 mono_raise_exception (exc);
856 size *= array->max_length;
857 field_data = mono_field_get_data (field_handle);
859 if (size > mono_type_size (field_handle->type, &align)) {
860 MonoException *exc = mono_get_exception_argument("field_handle",
861 "Field not large enough to fill array");
862 mono_raise_exception (exc);
865 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
867 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
868 guint ## n *src = (guint ## n *) field_data; \
869 guint ## n *end = (guint ## n *)((char*)src + size); \
871 for (; src < end; data++, src++) { \
872 *data = read ## n (src); \
876 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
878 switch (type->type) {
895 memcpy (mono_array_addr (array, char, 0), field_data, size);
899 memcpy (mono_array_addr (array, char, 0), field_data, size);
901 if (klass->element_class->byval_arg.type == MONO_TYPE_R8) {
904 double *data = (double*)mono_array_addr (array, double, 0);
906 for (i = 0; i < size; i++, data++) {
916 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
920 return offsetof (MonoString, chars);
923 ICALL_EXPORT MonoObject *
924 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
928 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
931 return mono_object_clone (obj);
935 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
940 MONO_CHECK_ARG_NULL (handle);
942 klass = mono_class_from_mono_type (handle);
943 MONO_CHECK_ARG (handle, klass);
945 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
947 /* This will call the type constructor */
948 mono_runtime_class_init (vtable);
952 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
956 mono_image_check_for_module_cctor (image);
957 if (image->has_module_cctor) {
958 MonoClass *module_klass = mono_class_get (image, MONO_TOKEN_TYPE_DEF | 1);
959 /*It's fine to raise the exception here*/
960 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
964 ICALL_EXPORT MonoBoolean
965 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
970 /* later make this configurable and per-arch */
971 int min_size = 4096 * 4 * sizeof (void*);
972 mono_thread_get_stack_bounds (&stack_addr, &stack_size);
973 /* if we have no info we are optimistic and assume there is enough room */
976 current = (guint8 *)&stack_addr;
977 if (current > stack_addr) {
978 if ((current - stack_addr) < min_size)
981 if (current - (stack_addr - stack_size) < min_size)
987 ICALL_EXPORT MonoObject *
988 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
992 return mono_object_clone (this);
996 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
999 MonoObject **values = NULL;
1003 MonoClassField* field;
1006 MONO_ARCH_SAVE_REGS;
1008 klass = mono_object_class (this);
1010 if (mono_class_num_fields (klass) == 0)
1011 return mono_object_hash (this);
1014 * Compute the starting value of the hashcode for fields of primitive
1015 * types, and return the remaining fields in an array to the managed side.
1016 * This way, we can avoid costly reflection operations in managed code.
1019 while ((field = mono_class_get_fields (klass, &iter))) {
1020 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1022 if (mono_field_is_deleted (field))
1024 /* FIXME: Add more types */
1025 switch (field->type->type) {
1027 result ^= *(gint32*)((guint8*)this + field->offset);
1029 case MONO_TYPE_STRING: {
1031 s = *(MonoString**)((guint8*)this + field->offset);
1033 result ^= mono_string_hash (s);
1038 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1039 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1040 values [count++] = o;
1046 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1047 for (i = 0; i < count; ++i)
1048 mono_array_setref (*fields, i, values [i]);
1055 ICALL_EXPORT MonoBoolean
1056 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1059 MonoObject **values = NULL;
1061 MonoClassField* field;
1065 MONO_ARCH_SAVE_REGS;
1067 MONO_CHECK_ARG_NULL (that);
1069 if (this->vtable != that->vtable)
1072 klass = mono_object_class (this);
1074 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1075 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1078 * Do the comparison for fields of primitive type and return a result if
1079 * possible. Otherwise, return the remaining fields in an array to the
1080 * managed side. This way, we can avoid costly reflection operations in
1085 while ((field = mono_class_get_fields (klass, &iter))) {
1086 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1088 if (mono_field_is_deleted (field))
1090 /* FIXME: Add more types */
1091 switch (field->type->type) {
1094 case MONO_TYPE_BOOLEAN:
1095 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1100 case MONO_TYPE_CHAR:
1101 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1106 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1111 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1115 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1119 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1124 case MONO_TYPE_STRING: {
1125 MonoString *s1, *s2;
1126 guint32 s1len, s2len;
1127 s1 = *(MonoString**)((guint8*)this + field->offset);
1128 s2 = *(MonoString**)((guint8*)that + field->offset);
1131 if ((s1 == NULL) || (s2 == NULL))
1133 s1len = mono_string_length (s1);
1134 s2len = mono_string_length (s2);
1138 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1144 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1145 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1146 values [count++] = o;
1147 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1148 values [count++] = o;
1151 if (klass->enumtype)
1152 /* enums only have one non-static field */
1158 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1159 for (i = 0; i < count; ++i)
1160 mono_array_setref (*fields, i, values [i]);
1167 ICALL_EXPORT MonoReflectionType *
1168 ves_icall_System_Object_GetType (MonoObject *obj)
1170 MONO_ARCH_SAVE_REGS;
1172 if (obj->vtable->klass != mono_defaults.transparent_proxy_class)
1173 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1175 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1179 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1181 MONO_ARCH_SAVE_REGS;
1183 mtype->type = &obj->vtable->klass->byval_arg;
1184 g_assert (mtype->type->type);
1188 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1190 MONO_ARCH_SAVE_REGS;
1192 MONO_CHECK_ARG_NULL (obj);
1194 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1198 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1199 MonoReflectionMethod *method,
1200 MonoArray *opt_param_types)
1202 MONO_ARCH_SAVE_REGS;
1204 MONO_CHECK_ARG_NULL (method);
1206 return mono_image_create_method_token (
1207 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1211 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1213 MONO_ARCH_SAVE_REGS;
1215 mono_image_create_pefile (mb, file);
1219 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1221 MONO_ARCH_SAVE_REGS;
1223 mono_image_build_metadata (mb);
1227 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1229 MONO_ARCH_SAVE_REGS;
1231 mono_image_register_token (mb->dynamic_image, token, obj);
1235 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1237 MonoMethod **dest = data;
1239 /* skip unmanaged frames */
1255 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1257 MonoMethod **dest = data;
1259 /* skip unmanaged frames */
1264 if (!strcmp (m->klass->name_space, "System.Reflection"))
1273 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1275 MonoMethod **dest = data;
1277 /* skip unmanaged frames */
1281 if (m->wrapper_type != MONO_WRAPPER_NONE)
1284 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1298 static MonoReflectionType *
1299 type_from_name (const char *str, MonoBoolean ignoreCase)
1301 MonoType *type = NULL;
1302 MonoAssembly *assembly = NULL;
1303 MonoTypeNameParse info;
1304 char *temp_str = g_strdup (str);
1305 gboolean type_resolve = FALSE;
1307 MONO_ARCH_SAVE_REGS;
1309 /* mono_reflection_parse_type() mangles the string */
1310 if (!mono_reflection_parse_type (temp_str, &info)) {
1311 mono_reflection_free_type_info (&info);
1316 if (info.assembly.name) {
1317 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1319 MonoMethod *m = mono_method_get_last_managed ();
1320 MonoMethod *dest = m;
1322 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1327 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1328 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1329 * to crash. This only seems to happen in some strange remoting
1330 * scenarios and I was unable to figure out what's happening there.
1331 * Dec 10, 2005 - Martin.
1335 assembly = dest->klass->image->assembly;
1336 type_resolve = TRUE;
1338 g_warning (G_STRLOC);
1343 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1344 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1347 if (!info.assembly.name && !type) /* try mscorlib */
1348 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1350 if (assembly && !type && type_resolve) {
1351 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1352 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1355 mono_reflection_free_type_info (&info);
1361 return mono_type_get_object (mono_domain_get (), type);
1365 MonoReflectionType *
1366 mono_type_get (const char *str)
1368 char *copy = g_strdup (str);
1369 MonoReflectionType *type = type_from_name (copy, FALSE);
1376 ICALL_EXPORT MonoReflectionType*
1377 ves_icall_type_from_name (MonoString *name,
1378 MonoBoolean throwOnError,
1379 MonoBoolean ignoreCase)
1381 char *str = mono_string_to_utf8 (name);
1382 MonoReflectionType *type;
1384 type = type_from_name (str, ignoreCase);
1387 MonoException *e = NULL;
1390 e = mono_get_exception_type_load (name, NULL);
1392 mono_loader_clear_error ();
1394 mono_raise_exception (e);
1401 ICALL_EXPORT MonoReflectionType*
1402 ves_icall_type_from_handle (MonoType *handle)
1404 MonoDomain *domain = mono_domain_get ();
1406 MONO_ARCH_SAVE_REGS;
1408 return mono_type_get_object (domain, handle);
1411 ICALL_EXPORT MonoBoolean
1412 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1414 MONO_ARCH_SAVE_REGS;
1416 if (c && type->type && c->type)
1417 return mono_metadata_type_equal (type->type, c->type);
1419 return (type == c) ? TRUE : FALSE;
1422 /* System.TypeCode */
1441 TYPECODE_STRING = 18
1444 ICALL_EXPORT guint32
1445 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1447 int t = type->type->type;
1449 MONO_ARCH_SAVE_REGS;
1451 if (type->type->byref)
1452 return TYPECODE_OBJECT;
1456 case MONO_TYPE_VOID:
1457 return TYPECODE_OBJECT;
1458 case MONO_TYPE_BOOLEAN:
1459 return TYPECODE_BOOLEAN;
1461 return TYPECODE_BYTE;
1463 return TYPECODE_SBYTE;
1465 return TYPECODE_UINT16;
1467 return TYPECODE_INT16;
1468 case MONO_TYPE_CHAR:
1469 return TYPECODE_CHAR;
1473 return TYPECODE_OBJECT;
1475 return TYPECODE_UINT32;
1477 return TYPECODE_INT32;
1479 return TYPECODE_UINT64;
1481 return TYPECODE_INT64;
1483 return TYPECODE_SINGLE;
1485 return TYPECODE_DOUBLE;
1486 case MONO_TYPE_VALUETYPE: {
1487 MonoClass *klass = type->type->data.klass;
1489 if (klass->enumtype) {
1490 t = mono_class_enum_basetype (klass)->type;
1492 } else if (mono_is_corlib_image (klass->image)) {
1493 if (strcmp (klass->name_space, "System") == 0) {
1494 if (strcmp (klass->name, "Decimal") == 0)
1495 return TYPECODE_DECIMAL;
1496 else if (strcmp (klass->name, "DateTime") == 0)
1497 return TYPECODE_DATETIME;
1500 return TYPECODE_OBJECT;
1502 case MONO_TYPE_STRING:
1503 return TYPECODE_STRING;
1504 case MONO_TYPE_SZARRAY:
1505 case MONO_TYPE_ARRAY:
1506 case MONO_TYPE_OBJECT:
1508 case MONO_TYPE_MVAR:
1509 case MONO_TYPE_TYPEDBYREF:
1510 return TYPECODE_OBJECT;
1511 case MONO_TYPE_CLASS:
1513 MonoClass *klass = type->type->data.klass;
1514 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1515 if (strcmp (klass->name, "DBNull") == 0)
1516 return TYPECODE_DBNULL;
1519 return TYPECODE_OBJECT;
1520 case MONO_TYPE_GENERICINST:
1521 return TYPECODE_OBJECT;
1523 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1528 ICALL_EXPORT guint32
1529 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1535 MONO_ARCH_SAVE_REGS;
1537 g_assert (type != NULL);
1539 domain = ((MonoObject *)type)->vtable->domain;
1541 if (!c) /* FIXME: dont know what do do here */
1544 klass = mono_class_from_mono_type (type->type);
1545 klassc = mono_class_from_mono_type (c->type);
1547 /* Interface check requires a more complex setup so we
1548 * only do for them. Otherwise we simply avoid mono_class_init.
1550 if (check_interfaces) {
1551 mono_class_init_or_throw (klass);
1552 mono_class_init_or_throw (klassc);
1553 } else if (!klass->supertypes || !klassc->supertypes) {
1554 mono_loader_lock ();
1555 mono_class_setup_supertypes (klass);
1556 mono_class_setup_supertypes (klassc);
1557 mono_loader_unlock ();
1560 if (type->type->byref)
1561 return klassc == mono_defaults.object_class;
1563 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1567 mono_type_is_primitive (MonoType *type)
1569 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1570 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1574 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1576 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1577 return mono_class_enum_basetype (type->data.klass);
1578 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1579 return mono_class_enum_basetype (type->data.generic_class->container_class);
1583 ICALL_EXPORT guint32
1584 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1590 MONO_ARCH_SAVE_REGS;
1592 g_assert (type != NULL);
1594 domain = ((MonoObject *)type)->vtable->domain;
1596 klass = mono_class_from_mono_type (type->type);
1597 klassc = mono_class_from_mono_type (c->type);
1599 mono_class_init_or_throw (klass);
1600 mono_class_init_or_throw (klassc);
1602 if (type->type->byref ^ c->type->byref)
1605 if (type->type->byref) {
1606 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1607 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1609 klass = mono_class_from_mono_type (t);
1610 klassc = mono_class_from_mono_type (ot);
1612 if (mono_type_is_primitive (t)) {
1613 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1614 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1615 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1616 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1617 return t->type == ot->type;
1619 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1622 if (klass->valuetype)
1623 return klass == klassc;
1624 return klass->valuetype == klassc->valuetype;
1627 return mono_class_is_assignable_from (klass, klassc);
1630 ICALL_EXPORT guint32
1631 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1633 MonoClass *klass = mono_class_from_mono_type (type->type);
1634 mono_class_init_or_throw (klass);
1635 return mono_object_isinst (obj, klass) != NULL;
1638 ICALL_EXPORT guint32
1639 ves_icall_get_attributes (MonoReflectionType *type)
1641 MonoClass *klass = mono_class_from_mono_type (type->type);
1642 return klass->flags;
1645 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1646 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1648 MonoClass *klass = field->field->parent;
1649 MonoMarshalType *info;
1652 if (klass->generic_container ||
1653 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1656 info = mono_marshal_load_type_info (klass);
1658 for (i = 0; i < info->num_fields; ++i) {
1659 if (info->fields [i].field == field->field) {
1660 if (!info->fields [i].mspec)
1663 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1670 ICALL_EXPORT MonoReflectionField*
1671 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1673 gboolean found = FALSE;
1680 klass = handle->parent;
1682 klass = mono_class_from_mono_type (type);
1684 /* Check that the field belongs to the class */
1685 for (k = klass; k; k = k->parent) {
1686 if (k == handle->parent) {
1693 /* The managed code will throw the exception */
1697 return mono_field_get_object (mono_domain_get (), klass, handle);
1700 ICALL_EXPORT MonoArray*
1701 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1704 MonoType *type = mono_field_get_type_checked (field->field, &error);
1705 if (!mono_error_ok (&error))
1706 mono_error_raise_exception (&error);
1708 return type_array_from_modifiers (field->field->parent->image, type, optional);
1712 vell_icall_get_method_attributes (MonoMethod *method)
1714 return method->flags;
1718 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1721 MonoDomain *domain = mono_domain_get ();
1722 MonoMethodSignature* sig;
1723 MONO_ARCH_SAVE_REGS;
1725 sig = mono_method_signature_checked (method, &error);
1726 if (!mono_error_ok (&error))
1727 mono_error_raise_exception (&error);
1730 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1731 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1732 info->attrs = method->flags;
1733 info->implattrs = method->iflags;
1734 if (sig->call_convention == MONO_CALL_DEFAULT)
1735 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1737 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1742 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1745 ICALL_EXPORT MonoArray*
1746 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1748 MonoDomain *domain = mono_domain_get ();
1750 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1753 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1754 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1756 MonoDomain *domain = mono_domain_get ();
1757 MonoReflectionMarshalAsAttribute* res = NULL;
1758 MonoMarshalSpec **mspecs;
1761 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1762 mono_method_get_marshal_info (method, mspecs);
1765 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1767 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1769 mono_metadata_free_marshal_spec (mspecs [i]);
1776 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1778 MonoClass *parent = field->field->parent;
1779 if (!parent->size_inited)
1780 mono_class_init (parent);
1782 return field->field->offset - sizeof (MonoObject);
1785 ICALL_EXPORT MonoReflectionType*
1786 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1789 MONO_ARCH_SAVE_REGS;
1791 parent = declaring? field->field->parent: field->klass;
1793 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1796 ICALL_EXPORT MonoObject *
1797 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1799 MonoClass *fklass = field->klass;
1800 MonoClassField *cf = field->field;
1801 MonoDomain *domain = mono_object_domain (field);
1803 if (fklass->image->assembly->ref_only)
1804 mono_raise_exception (mono_get_exception_invalid_operation (
1805 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1807 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1808 mono_security_core_clr_ensure_reflection_access_field (cf);
1810 return mono_field_get_value_object (domain, cf, obj);
1814 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1817 MonoClassField *cf = field->field;
1821 MONO_ARCH_SAVE_REGS;
1823 if (field->klass->image->assembly->ref_only)
1824 mono_raise_exception (mono_get_exception_invalid_operation (
1825 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1827 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1828 mono_security_core_clr_ensure_reflection_access_field (cf);
1830 type = mono_field_get_type_checked (cf, &error);
1831 if (!mono_error_ok (&error))
1832 mono_error_raise_exception (&error);
1834 v = (gchar *) value;
1836 switch (type->type) {
1839 case MONO_TYPE_BOOLEAN:
1842 case MONO_TYPE_CHAR:
1851 case MONO_TYPE_VALUETYPE:
1854 v += sizeof (MonoObject);
1856 case MONO_TYPE_STRING:
1857 case MONO_TYPE_OBJECT:
1858 case MONO_TYPE_CLASS:
1859 case MONO_TYPE_ARRAY:
1860 case MONO_TYPE_SZARRAY:
1863 case MONO_TYPE_GENERICINST: {
1864 MonoGenericClass *gclass = type->data.generic_class;
1865 g_assert (!gclass->context.class_inst->is_open);
1867 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1868 MonoClass *nklass = mono_class_from_mono_type (type);
1869 MonoObject *nullable;
1872 * Convert the boxed vtype into a Nullable structure.
1873 * This is complicated by the fact that Nullables have
1874 * a variable structure.
1876 nullable = mono_object_new (mono_domain_get (), nklass);
1878 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1880 v = mono_object_unbox (nullable);
1883 if (gclass->container_class->valuetype && (v != NULL))
1884 v += sizeof (MonoObject);
1888 g_error ("type 0x%x not handled in "
1889 "ves_icall_FieldInfo_SetValueInternal", type->type);
1894 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1895 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1896 if (!vtable->initialized)
1897 mono_runtime_class_init (vtable);
1898 mono_field_static_set_value (vtable, cf, v);
1900 mono_field_set_value (obj, cf, v);
1904 ICALL_EXPORT MonoObject *
1905 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1907 MonoObject *o = NULL;
1908 MonoClassField *field = this->field;
1910 MonoDomain *domain = mono_object_domain (this);
1912 MonoTypeEnum def_type;
1913 const char *def_value;
1917 MONO_ARCH_SAVE_REGS;
1919 mono_class_init (field->parent);
1921 t = mono_field_get_type_checked (field, &error);
1922 if (!mono_error_ok (&error))
1923 mono_error_raise_exception (&error);
1925 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1926 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1928 if (field->parent->image->dynamic) {
1930 g_assert_not_reached ();
1933 def_value = mono_class_get_field_default_value (field, &def_type);
1934 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1935 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1937 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1941 case MONO_TYPE_BOOLEAN:
1944 case MONO_TYPE_CHAR:
1952 case MONO_TYPE_R8: {
1955 /* boxed value type */
1956 t = g_new0 (MonoType, 1);
1958 klass = mono_class_from_mono_type (t);
1960 o = mono_object_new (domain, klass);
1961 v = ((gchar *) o) + sizeof (MonoObject);
1962 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1965 case MONO_TYPE_STRING:
1966 case MONO_TYPE_CLASS:
1967 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1970 g_assert_not_reached ();
1976 ICALL_EXPORT MonoReflectionType*
1977 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1980 MonoClassField *field = ref_field->field;
1981 MonoType *type = mono_field_get_type_checked (field, &error);
1982 if (!mono_error_ok (&error))
1983 mono_error_raise_exception (&error);
1984 return mono_type_get_object (mono_object_domain (ref_field), type);
1987 ICALL_EXPORT MonoReflectionType*
1988 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1990 MonoMethod *method = rmethod->method.method;
1992 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1995 /* From MonoProperty.cs */
1997 PInfo_Attributes = 1,
1998 PInfo_GetMethod = 1 << 1,
1999 PInfo_SetMethod = 1 << 2,
2000 PInfo_ReflectedType = 1 << 3,
2001 PInfo_DeclaringType = 1 << 4,
2006 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2008 MonoDomain *domain = mono_object_domain (property);
2010 MONO_ARCH_SAVE_REGS;
2012 if ((req_info & PInfo_ReflectedType) != 0)
2013 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2014 if ((req_info & PInfo_DeclaringType) != 0)
2015 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2017 if ((req_info & PInfo_Name) != 0)
2018 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2020 if ((req_info & PInfo_Attributes) != 0)
2021 info->attrs = property->property->attrs;
2023 if ((req_info & PInfo_GetMethod) != 0)
2024 MONO_STRUCT_SETREF (info, get, property->property->get ?
2025 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2027 if ((req_info & PInfo_SetMethod) != 0)
2028 MONO_STRUCT_SETREF (info, set, property->property->set ?
2029 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2031 * There may be other methods defined for properties, though, it seems they are not exposed
2032 * in the reflection API
2037 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2039 MonoDomain *domain = mono_object_domain (event);
2041 MONO_ARCH_SAVE_REGS;
2043 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2044 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2046 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2047 info->attrs = event->event->attrs;
2048 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2049 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2050 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2052 #ifndef MONO_SMALL_CONFIG
2053 if (event->event->other) {
2055 while (event->event->other [n])
2057 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2059 for (i = 0; i < n; i++)
2060 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2066 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2071 mono_class_setup_interfaces (klass, error);
2072 if (!mono_error_ok (error))
2075 for (i = 0; i < klass->interface_count; i++) {
2076 ic = klass->interfaces [i];
2077 g_hash_table_insert (ifaces, ic, ic);
2079 collect_interfaces (ic, ifaces, error);
2080 if (!mono_error_ok (error))
2086 MonoArray *iface_array;
2087 MonoGenericContext *context;
2091 } FillIfaceArrayData;
2094 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2096 FillIfaceArrayData *data = user_data;
2097 MonoClass *ic = key;
2098 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2100 if (!mono_error_ok (data->error))
2103 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2104 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2105 if (!mono_error_ok (data->error))
2109 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2112 mono_metadata_free_type (inflated);
2115 ICALL_EXPORT MonoArray*
2116 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2119 MonoClass *class = mono_class_from_mono_type (type->type);
2121 FillIfaceArrayData data = { 0 };
2124 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2126 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2127 data.context = mono_class_get_context (class);
2128 class = class->generic_class->container_class;
2131 for (parent = class; parent; parent = parent->parent) {
2132 mono_class_setup_interfaces (parent, &error);
2133 if (!mono_error_ok (&error))
2135 collect_interfaces (parent, iface_hash, &error);
2136 if (!mono_error_ok (&error))
2140 data.error = &error;
2141 data.domain = mono_object_domain (type);
2143 len = g_hash_table_size (iface_hash);
2145 g_hash_table_destroy (iface_hash);
2146 if (!data.domain->empty_types)
2147 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2148 return data.domain->empty_types;
2151 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2152 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2153 if (!mono_error_ok (&error))
2156 g_hash_table_destroy (iface_hash);
2157 return data.iface_array;
2160 g_hash_table_destroy (iface_hash);
2161 mono_error_raise_exception (&error);
2166 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2168 gboolean variance_used;
2169 MonoClass *class = mono_class_from_mono_type (type->type);
2170 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2171 MonoReflectionMethod *member;
2174 int i = 0, len, ioffset;
2177 MONO_ARCH_SAVE_REGS;
2178 mono_class_init_or_throw (class);
2179 mono_class_init_or_throw (iclass);
2181 mono_class_setup_vtable (class);
2183 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2187 len = mono_class_num_methods (iclass);
2188 domain = mono_object_domain (type);
2189 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2190 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2192 while ((method = mono_class_get_methods (iclass, &iter))) {
2193 member = mono_method_get_object (domain, method, iclass);
2194 mono_array_setref (*methods, i, member);
2195 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2196 mono_array_setref (*targets, i, member);
2203 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2205 MonoClass *klass = mono_class_from_mono_type (type->type);
2206 mono_class_init_or_throw (klass);
2208 if (klass->image->dynamic) {
2209 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2210 *packing = tb->packing_size;
2211 *size = tb->class_size;
2213 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2217 ICALL_EXPORT MonoReflectionType*
2218 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2222 MONO_ARCH_SAVE_REGS;
2224 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2225 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2227 class = mono_class_from_mono_type (type->type);
2228 mono_class_init_or_throw (class);
2230 // GetElementType should only return a type for:
2231 // Array Pointer PassedByRef
2232 if (type->type->byref)
2233 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2234 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2235 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2236 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2237 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2242 ICALL_EXPORT MonoReflectionType*
2243 ves_icall_get_type_parent (MonoReflectionType *type)
2245 MonoClass *class = mono_class_from_mono_type (type->type);
2246 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2249 ICALL_EXPORT MonoBoolean
2250 ves_icall_type_ispointer (MonoReflectionType *type)
2252 MONO_ARCH_SAVE_REGS;
2254 return type->type->type == MONO_TYPE_PTR;
2257 ICALL_EXPORT MonoBoolean
2258 ves_icall_type_isprimitive (MonoReflectionType *type)
2260 MONO_ARCH_SAVE_REGS;
2262 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)));
2265 ICALL_EXPORT MonoBoolean
2266 ves_icall_type_isbyref (MonoReflectionType *type)
2268 MONO_ARCH_SAVE_REGS;
2270 return type->type->byref;
2273 ICALL_EXPORT MonoBoolean
2274 ves_icall_type_iscomobject (MonoReflectionType *type)
2276 MonoClass *klass = mono_class_from_mono_type (type->type);
2277 mono_class_init_or_throw (klass);
2279 return (klass && klass->is_com_object);
2282 ICALL_EXPORT MonoReflectionModule*
2283 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2285 MonoClass *class = mono_class_from_mono_type (type->type);
2286 return mono_module_get_object (mono_object_domain (type), class->image);
2289 ICALL_EXPORT MonoReflectionAssembly*
2290 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2292 MonoDomain *domain = mono_domain_get ();
2293 MonoClass *class = mono_class_from_mono_type (type->type);
2294 return mono_assembly_get_object (domain, class->image->assembly);
2297 ICALL_EXPORT MonoReflectionType*
2298 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2300 MonoDomain *domain = mono_domain_get ();
2303 MONO_ARCH_SAVE_REGS;
2305 if (type->type->byref)
2307 if (type->type->type == MONO_TYPE_VAR)
2308 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2309 else if (type->type->type == MONO_TYPE_MVAR)
2310 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2312 class = mono_class_from_mono_type (type->type)->nested_in;
2314 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2317 ICALL_EXPORT MonoString*
2318 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2320 MonoDomain *domain = mono_domain_get ();
2321 MonoClass *class = mono_class_from_mono_type (type->type);
2323 if (type->type->byref) {
2324 char *n = g_strdup_printf ("%s&", class->name);
2325 MonoString *res = mono_string_new (domain, n);
2331 return mono_string_new (domain, class->name);
2335 ICALL_EXPORT MonoString*
2336 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2338 MonoDomain *domain = mono_domain_get ();
2339 MonoClass *class = mono_class_from_mono_type (type->type);
2341 while (class->nested_in)
2342 class = class->nested_in;
2344 if (class->name_space [0] == '\0')
2347 return mono_string_new (domain, class->name_space);
2351 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2355 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2356 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2358 class = mono_class_from_mono_type (type->type);
2363 ICALL_EXPORT MonoArray*
2364 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2367 MonoClass *klass, *pklass;
2368 MonoDomain *domain = mono_object_domain (type);
2369 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2371 MONO_ARCH_SAVE_REGS;
2373 klass = mono_class_from_mono_type (type->type);
2375 if (klass->generic_container) {
2376 MonoGenericContainer *container = klass->generic_container;
2377 res = mono_array_new_specific (array_vtable, container->type_argc);
2378 for (i = 0; i < container->type_argc; ++i) {
2379 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2380 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2382 } else if (klass->generic_class) {
2383 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2384 res = mono_array_new_specific (array_vtable, inst->type_argc);
2385 for (i = 0; i < inst->type_argc; ++i)
2386 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2388 res = mono_array_new_specific (array_vtable, 0);
2393 ICALL_EXPORT gboolean
2394 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2397 MONO_ARCH_SAVE_REGS;
2399 if (!IS_MONOTYPE (type))
2402 if (type->type->byref)
2405 klass = mono_class_from_mono_type (type->type);
2406 return klass->generic_container != NULL;
2409 ICALL_EXPORT MonoReflectionType*
2410 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2413 MONO_ARCH_SAVE_REGS;
2415 if (type->type->byref)
2418 klass = mono_class_from_mono_type (type->type);
2420 if (klass->generic_container) {
2421 return type; /* check this one */
2423 if (klass->generic_class) {
2424 MonoClass *generic_class = klass->generic_class->container_class;
2427 tb = mono_class_get_ref_info (generic_class);
2429 if (generic_class->wastypebuilder && tb)
2432 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2437 ICALL_EXPORT MonoReflectionType*
2438 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2441 MonoType *geninst, **types;
2444 g_assert (IS_MONOTYPE (type));
2445 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2447 count = mono_array_length (type_array);
2448 types = g_new0 (MonoType *, count);
2450 for (i = 0; i < count; i++) {
2451 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2452 types [i] = t->type;
2455 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2460 class = mono_class_from_mono_type (geninst);
2462 /*we might inflate to the GTD*/
2463 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2464 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2466 return mono_type_get_object (mono_object_domain (type), geninst);
2469 ICALL_EXPORT gboolean
2470 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2473 MONO_ARCH_SAVE_REGS;
2475 if (type->type->byref)
2478 klass = mono_class_from_mono_type (type->type);
2480 return klass->generic_class != NULL;
2483 ICALL_EXPORT gboolean
2484 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2487 MONO_ARCH_SAVE_REGS;
2489 if (!IS_MONOTYPE (type))
2492 if (type->type->byref)
2495 klass = mono_class_from_mono_type (type->type);
2496 return klass->generic_class != NULL || klass->generic_container != NULL;
2500 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2502 MONO_ARCH_SAVE_REGS;
2504 if (!IS_MONOTYPE (type))
2507 if (is_generic_parameter (type->type))
2508 return mono_type_get_generic_param_num (type->type);
2512 ICALL_EXPORT GenericParameterAttributes
2513 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2515 MONO_ARCH_SAVE_REGS;
2517 g_assert (IS_MONOTYPE (type));
2518 g_assert (is_generic_parameter (type->type));
2519 return mono_generic_param_info (type->type->data.generic_param)->flags;
2522 ICALL_EXPORT MonoArray *
2523 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2525 MonoGenericParamInfo *param_info;
2531 MONO_ARCH_SAVE_REGS;
2533 g_assert (IS_MONOTYPE (type));
2535 domain = mono_object_domain (type);
2536 param_info = mono_generic_param_info (type->type->data.generic_param);
2537 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2540 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2541 for (i = 0; i < count; i++)
2542 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2548 ICALL_EXPORT MonoBoolean
2549 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2551 MONO_ARCH_SAVE_REGS;
2552 return is_generic_parameter (type->type);
2555 ICALL_EXPORT MonoBoolean
2556 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2558 MONO_ARCH_SAVE_REGS;
2559 return is_generic_parameter (tb->type.type);
2563 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2564 MonoReflectionType *t)
2566 enumtype->type = t->type;
2569 ICALL_EXPORT MonoReflectionMethod*
2570 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2571 MonoReflectionMethod* generic)
2578 MONO_ARCH_SAVE_REGS;
2580 domain = ((MonoObject *)type)->vtable->domain;
2582 klass = mono_class_from_mono_type (type->type);
2583 mono_class_init_or_throw (klass);
2586 while ((method = mono_class_get_methods (klass, &iter))) {
2587 if (method->token == generic->method->token)
2588 return mono_method_get_object (domain, method, klass);
2596 ICALL_EXPORT MonoReflectionMethod *
2597 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2600 MonoType *type = ref_type->type;
2602 MONO_ARCH_SAVE_REGS;
2604 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2605 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2606 if (type->type == MONO_TYPE_VAR)
2609 method = mono_type_get_generic_param_owner (type)->owner.method;
2611 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2614 ICALL_EXPORT MonoReflectionDllImportAttribute*
2615 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2617 static MonoClass *DllImportAttributeClass = NULL;
2618 MonoDomain *domain = mono_domain_get ();
2619 MonoReflectionDllImportAttribute *attr;
2620 MonoImage *image = method->klass->image;
2621 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2622 MonoTableInfo *tables = image->tables;
2623 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2624 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2625 guint32 im_cols [MONO_IMPLMAP_SIZE];
2626 guint32 scope_token;
2627 const char *import = NULL;
2628 const char *scope = NULL;
2631 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2634 if (!DllImportAttributeClass) {
2635 DllImportAttributeClass =
2636 mono_class_from_name (mono_defaults.corlib,
2637 "System.Runtime.InteropServices", "DllImportAttribute");
2638 g_assert (DllImportAttributeClass);
2641 if (method->klass->image->dynamic) {
2642 MonoReflectionMethodAux *method_aux =
2643 g_hash_table_lookup (
2644 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2646 import = method_aux->dllentry;
2647 scope = method_aux->dll;
2650 if (!import || !scope) {
2651 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2656 if (piinfo->implmap_idx) {
2657 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2659 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2660 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2661 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2662 scope = mono_metadata_string_heap (image, scope_token);
2665 flags = piinfo->piflags;
2667 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2669 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2670 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2671 attr->call_conv = (flags & 0x700) >> 8;
2672 attr->charset = ((flags & 0x6) >> 1) + 1;
2673 if (attr->charset == 1)
2675 attr->exact_spelling = (flags & 0x1) != 0;
2676 attr->set_last_error = (flags & 0x40) != 0;
2677 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2678 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2679 attr->preserve_sig = FALSE;
2684 ICALL_EXPORT MonoReflectionMethod *
2685 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2687 MonoMethodInflated *imethod;
2690 MONO_ARCH_SAVE_REGS;
2692 if (method->method->is_generic)
2695 if (!method->method->is_inflated)
2698 imethod = (MonoMethodInflated *) method->method;
2700 result = imethod->declaring;
2701 /* Not a generic method. */
2702 if (!result->is_generic)
2705 if (method->method->klass->image->dynamic) {
2706 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2707 MonoReflectionMethod *res;
2710 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2711 * the dynamic case as well ?
2713 mono_loader_lock ();
2714 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2715 mono_loader_unlock ();
2721 if (imethod->context.class_inst) {
2722 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2723 /*Generic methods gets the context of the GTD.*/
2724 if (mono_class_get_context (klass))
2725 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2728 return mono_method_get_object (mono_object_domain (method), result, NULL);
2731 ICALL_EXPORT gboolean
2732 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2734 MONO_ARCH_SAVE_REGS;
2736 return mono_method_signature (method->method)->generic_param_count != 0;
2739 ICALL_EXPORT gboolean
2740 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2742 MONO_ARCH_SAVE_REGS;
2744 return method->method->is_generic;
2747 ICALL_EXPORT MonoArray*
2748 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2753 MONO_ARCH_SAVE_REGS;
2755 domain = mono_object_domain (method);
2757 if (method->method->is_inflated) {
2758 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2761 count = inst->type_argc;
2762 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2764 for (i = 0; i < count; i++)
2765 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2771 count = mono_method_signature (method->method)->generic_param_count;
2772 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2774 for (i = 0; i < count; i++) {
2775 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2776 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2777 MonoClass *pklass = mono_class_from_generic_parameter (
2778 param, method->method->klass->image, TRUE);
2779 mono_array_setref (res, i,
2780 mono_type_get_object (domain, &pklass->byval_arg));
2786 ICALL_EXPORT MonoObject *
2787 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2790 * Invoke from reflection is supposed to always be a virtual call (the API
2791 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2792 * greater flexibility.
2794 MonoMethod *m = method->method;
2795 MonoMethodSignature *sig = mono_method_signature (m);
2799 MONO_ARCH_SAVE_REGS;
2803 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2804 mono_security_core_clr_ensure_reflection_access_method (m);
2806 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2807 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2808 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2813 if (!mono_object_isinst (this, m->klass)) {
2814 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2815 char *target_name = mono_type_get_full_name (m->klass);
2816 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2817 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2819 g_free (target_name);
2823 m = mono_object_get_virtual_method (this, m);
2824 /* must pass the pointer to the value for valuetype methods */
2825 if (m->klass->valuetype)
2826 obj = mono_object_unbox (this);
2827 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2828 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2833 if (sig->ret->byref) {
2834 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
2838 pcount = params? mono_array_length (params): 0;
2839 if (pcount != sig->param_count) {
2840 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2844 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2845 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."));
2849 if (m->klass->image->assembly->ref_only) {
2850 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."));
2854 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2857 intptr_t *lower_bounds;
2858 pcount = mono_array_length (params);
2859 lengths = alloca (sizeof (uintptr_t) * pcount);
2860 /* Note: the synthetized array .ctors have int32 as argument type */
2861 for (i = 0; i < pcount; ++i)
2862 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2864 if (m->klass->rank == pcount) {
2865 /* Only lengths provided. */
2866 lower_bounds = NULL;
2868 g_assert (pcount == (m->klass->rank * 2));
2869 /* lower bounds are first. */
2870 lower_bounds = (intptr_t*)lengths;
2871 lengths += m->klass->rank;
2874 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2876 return mono_runtime_invoke_array (m, obj, params, NULL);
2879 ICALL_EXPORT MonoObject *
2880 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2882 MonoDomain *domain = mono_object_domain (method);
2883 MonoMethod *m = method->method;
2884 MonoMethodSignature *sig = mono_method_signature (m);
2885 MonoArray *out_args;
2887 int i, j, outarg_count = 0;
2889 MONO_ARCH_SAVE_REGS;
2891 if (m->klass == mono_defaults.object_class) {
2893 if (!strcmp (m->name, "FieldGetter")) {
2894 MonoClass *k = this->vtable->klass;
2898 /* If this is a proxy, then it must be a CBO */
2899 if (k == mono_defaults.transparent_proxy_class) {
2900 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2901 this = tp->rp->unwrapped_server;
2903 k = this->vtable->klass;
2906 name = mono_array_get (params, MonoString *, 1);
2907 str = mono_string_to_utf8 (name);
2910 MonoClassField* field = mono_class_get_field_from_name (k, str);
2912 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2913 if (field_klass->valuetype)
2914 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2916 result = *((gpointer *)((char *)this + field->offset));
2918 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2919 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2920 mono_array_setref (out_args, 0, result);
2928 g_assert_not_reached ();
2930 } else if (!strcmp (m->name, "FieldSetter")) {
2931 MonoClass *k = this->vtable->klass;
2937 /* If this is a proxy, then it must be a CBO */
2938 if (k == mono_defaults.transparent_proxy_class) {
2939 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2940 this = tp->rp->unwrapped_server;
2942 k = this->vtable->klass;
2945 name = mono_array_get (params, MonoString *, 1);
2946 str = mono_string_to_utf8 (name);
2949 MonoClassField* field = mono_class_get_field_from_name (k, str);
2951 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2952 MonoObject *val = mono_array_get (params, gpointer, 2);
2954 if (field_klass->valuetype) {
2955 size = mono_type_size (field->type, &align);
2956 g_assert (size == mono_class_value_size (field_klass, NULL));
2957 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2959 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2962 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2963 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2973 g_assert_not_reached ();
2978 for (i = 0; i < mono_array_length (params); i++) {
2979 if (sig->params [i]->byref)
2983 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2985 /* handle constructors only for objects already allocated */
2986 if (!strcmp (method->method->name, ".ctor"))
2989 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2990 g_assert (!method->method->klass->valuetype);
2991 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2993 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2994 if (sig->params [i]->byref) {
2996 arg = mono_array_get (params, gpointer, i);
2997 mono_array_setref (out_args, j, arg);
3002 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3008 read_enum_value (char *mem, int type)
3012 return *(guint8*)mem;
3014 return *(gint8*)mem;
3016 return *(guint16*)mem;
3018 return *(gint16*)mem;
3020 return *(guint32*)mem;
3022 return *(gint32*)mem;
3024 return *(guint64*)mem;
3026 return *(gint64*)mem;
3028 g_assert_not_reached ();
3034 write_enum_value (char *mem, int type, guint64 value)
3038 case MONO_TYPE_I1: {
3039 guint8 *p = (guint8*)mem;
3044 case MONO_TYPE_I2: {
3045 guint16 *p = (void*)mem;
3050 case MONO_TYPE_I4: {
3051 guint32 *p = (void*)mem;
3056 case MONO_TYPE_I8: {
3057 guint64 *p = (void*)mem;
3062 g_assert_not_reached ();
3067 ICALL_EXPORT MonoObject *
3068 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3071 MonoClass *enumc, *objc;
3076 MONO_ARCH_SAVE_REGS;
3078 MONO_CHECK_ARG_NULL (enumType);
3079 MONO_CHECK_ARG_NULL (value);
3081 domain = mono_object_domain (enumType);
3082 enumc = mono_class_from_mono_type (enumType->type);
3084 mono_class_init_or_throw (enumc);
3086 objc = value->vtable->klass;
3088 if (!enumc->enumtype)
3089 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3090 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3091 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."));
3093 etype = mono_class_enum_basetype (enumc);
3095 /* MS throws this for typebuilders */
3096 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3098 res = mono_object_new (domain, enumc);
3099 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3100 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3105 ICALL_EXPORT MonoObject *
3106 ves_icall_System_Enum_get_value (MonoObject *this)
3114 MONO_ARCH_SAVE_REGS;
3119 g_assert (this->vtable->klass->enumtype);
3121 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3122 res = mono_object_new (mono_object_domain (this), enumc);
3123 dst = (char *)res + sizeof (MonoObject);
3124 src = (char *)this + sizeof (MonoObject);
3125 size = mono_class_value_size (enumc, NULL);
3127 memcpy (dst, src, size);
3132 ICALL_EXPORT MonoReflectionType *
3133 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3138 MONO_ARCH_SAVE_REGS;
3140 klass = mono_class_from_mono_type (type->type);
3141 mono_class_init_or_throw (klass);
3143 etype = mono_class_enum_basetype (klass);
3145 /* MS throws this for typebuilders */
3146 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3148 return mono_type_get_object (mono_object_domain (type), etype);
3152 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3154 gpointer tdata = (char *)this + sizeof (MonoObject);
3155 gpointer odata = (char *)other + sizeof (MonoObject);
3156 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3157 g_assert (basetype);
3159 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3160 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3161 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3164 return me > other ? 1 : -1; \
3167 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3168 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3169 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3172 return me - other; \
3175 switch (basetype->type) {
3177 COMPARE_ENUM_VALUES (guint8);
3179 COMPARE_ENUM_VALUES (gint8);
3180 case MONO_TYPE_CHAR:
3182 COMPARE_ENUM_VALUES_RANGE (guint16);
3184 COMPARE_ENUM_VALUES (gint16);
3186 COMPARE_ENUM_VALUES (guint32);
3188 COMPARE_ENUM_VALUES (gint32);
3190 COMPARE_ENUM_VALUES (guint64);
3192 COMPARE_ENUM_VALUES (gint64);
3194 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3196 #undef COMPARE_ENUM_VALUES_RANGE
3197 #undef COMPARE_ENUM_VALUES
3202 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3204 gpointer data = (char *)this + sizeof (MonoObject);
3205 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3206 g_assert (basetype);
3208 switch (basetype->type) {
3210 return *((gint8*)data);
3212 return *((guint8*)data);
3213 case MONO_TYPE_CHAR:
3215 return *((guint16*)data);
3218 return *((gint16*)data);
3220 return *((guint32*)data);
3222 return *((gint32*)data);
3224 case MONO_TYPE_I8: {
3225 gint64 value = *((gint64*)data);
3226 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3229 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3235 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3237 MonoDomain *domain = mono_object_domain (type);
3238 MonoClass *enumc = mono_class_from_mono_type (type->type);
3239 guint j = 0, nvalues, crow;
3241 MonoClassField *field;
3243 MONO_ARCH_SAVE_REGS;
3245 mono_class_init_or_throw (enumc);
3247 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3248 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3249 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3250 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3254 while ((field = mono_class_get_fields (enumc, &iter))) {
3257 MonoTypeEnum def_type;
3259 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3261 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3263 if (mono_field_is_deleted (field))
3265 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3267 p = mono_class_get_field_default_value (field, &def_type);
3268 len = mono_metadata_decode_blob_size (p, &p);
3269 switch (mono_class_enum_basetype (enumc)->type) {
3272 mono_array_set (info->values, gchar, j, *p);
3274 case MONO_TYPE_CHAR:
3277 mono_array_set (info->values, gint16, j, read16 (p));
3281 mono_array_set (info->values, gint32, j, read32 (p));
3285 mono_array_set (info->values, gint64, j, read64 (p));
3288 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3295 BFLAGS_IgnoreCase = 1,
3296 BFLAGS_DeclaredOnly = 2,
3297 BFLAGS_Instance = 4,
3299 BFLAGS_Public = 0x10,
3300 BFLAGS_NonPublic = 0x20,
3301 BFLAGS_FlattenHierarchy = 0x40,
3302 BFLAGS_InvokeMethod = 0x100,
3303 BFLAGS_CreateInstance = 0x200,
3304 BFLAGS_GetField = 0x400,
3305 BFLAGS_SetField = 0x800,
3306 BFLAGS_GetProperty = 0x1000,
3307 BFLAGS_SetProperty = 0x2000,
3308 BFLAGS_ExactBinding = 0x10000,
3309 BFLAGS_SuppressChangeType = 0x20000,
3310 BFLAGS_OptionalParamBinding = 0x40000
3313 ICALL_EXPORT MonoReflectionField *
3314 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3317 MonoClass *startklass, *klass;
3319 MonoClassField *field;
3322 int (*compare_func) (const char *s1, const char *s2) = NULL;
3323 domain = ((MonoObject *)type)->vtable->domain;
3324 klass = startklass = mono_class_from_mono_type (type->type);
3327 mono_raise_exception (mono_get_exception_argument_null ("name"));
3328 if (type->type->byref)
3331 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3334 if (klass->exception_type != MONO_EXCEPTION_NONE)
3335 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3338 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3339 guint32 flags = mono_field_get_flags (field);
3342 if (mono_field_is_deleted_with_flags (field, flags))
3344 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3345 if (bflags & BFLAGS_Public)
3347 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3348 if (bflags & BFLAGS_NonPublic) {
3355 if (flags & FIELD_ATTRIBUTE_STATIC) {
3356 if (bflags & BFLAGS_Static)
3357 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3360 if (bflags & BFLAGS_Instance)
3367 utf8_name = mono_string_to_utf8 (name);
3369 if (compare_func (mono_field_get_name (field), utf8_name)) {
3375 return mono_field_get_object (domain, klass, field);
3377 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3383 ICALL_EXPORT MonoArray*
3384 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3387 MonoClass *startklass, *klass, *refklass;
3392 MonoClassField *field;
3393 MonoPtrArray tmp_array;
3395 MONO_ARCH_SAVE_REGS;
3397 domain = ((MonoObject *)type)->vtable->domain;
3398 if (type->type->byref)
3399 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3400 klass = startklass = mono_class_from_mono_type (type->type);
3401 refklass = mono_class_from_mono_type (reftype->type);
3403 mono_ptr_array_init (tmp_array, 2);
3406 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3407 mono_ptr_array_destroy (tmp_array);
3408 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3412 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3413 guint32 flags = mono_field_get_flags (field);
3415 if (mono_field_is_deleted_with_flags (field, flags))
3417 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3418 if (bflags & BFLAGS_Public)
3420 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3421 if (bflags & BFLAGS_NonPublic) {
3428 if (flags & FIELD_ATTRIBUTE_STATIC) {
3429 if (bflags & BFLAGS_Static)
3430 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3433 if (bflags & BFLAGS_Instance)
3439 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3440 mono_ptr_array_append (tmp_array, member);
3442 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3445 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3447 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3448 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3450 mono_ptr_array_destroy (tmp_array);
3456 method_nonpublic (MonoMethod* method, gboolean start_klass)
3458 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3459 case METHOD_ATTRIBUTE_ASSEM:
3460 return (start_klass || mono_defaults.generic_ilist_class);
3461 case METHOD_ATTRIBUTE_PRIVATE:
3463 case METHOD_ATTRIBUTE_PUBLIC:
3471 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3474 MonoClass *startklass;
3477 int len, match, nslots;
3478 /*FIXME, use MonoBitSet*/
3479 guint32 method_slots_default [8];
3480 guint32 *method_slots = NULL;
3481 int (*compare_func) (const char *s1, const char *s2) = NULL;
3483 array = g_ptr_array_new ();
3489 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3491 /* An optimization for calls made from Delegate:CreateDelegate () */
3492 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3493 method = mono_get_delegate_invoke (klass);
3494 if (mono_loader_get_last_error ())
3497 g_ptr_array_add (array, method);
3501 mono_class_setup_vtable (klass);
3502 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3505 if (is_generic_parameter (&klass->byval_arg))
3506 nslots = mono_class_get_vtable_size (klass->parent);
3508 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3509 if (nslots >= sizeof (method_slots_default) * 8) {
3510 method_slots = g_new0 (guint32, nslots / 32 + 1);
3512 method_slots = method_slots_default;
3513 memset (method_slots, 0, sizeof (method_slots_default));
3516 mono_class_setup_vtable (klass);
3517 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3521 while ((method = mono_class_get_methods (klass, &iter))) {
3523 if (method->slot != -1) {
3524 g_assert (method->slot < nslots);
3525 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3527 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3528 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3531 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3533 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3534 if (bflags & BFLAGS_Public)
3536 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3542 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3543 if (bflags & BFLAGS_Static)
3544 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3547 if (bflags & BFLAGS_Instance)
3555 if (compare_func (name, method->name))
3560 g_ptr_array_add (array, method);
3562 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3564 if (method_slots != method_slots_default)
3565 g_free (method_slots);
3570 if (method_slots != method_slots_default)
3571 g_free (method_slots);
3572 g_ptr_array_free (array, TRUE);
3574 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3575 *ex = mono_class_get_exception_for_failure (klass);
3577 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3578 mono_loader_clear_error ();
3583 ICALL_EXPORT MonoArray*
3584 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3586 static MonoClass *MethodInfo_array;
3589 MonoVTable *array_vtable;
3590 MonoException *ex = NULL;
3591 const char *mname = NULL;
3592 GPtrArray *method_array;
3593 MonoClass *klass, *refklass;
3596 if (!MethodInfo_array) {
3597 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3598 mono_memory_barrier ();
3599 MethodInfo_array = klass;
3602 klass = mono_class_from_mono_type (type->type);
3603 refklass = mono_class_from_mono_type (reftype->type);
3604 domain = ((MonoObject *)type)->vtable->domain;
3605 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3606 if (type->type->byref)
3607 return mono_array_new_specific (array_vtable, 0);
3610 mname = mono_string_to_utf8 (name);
3612 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3613 g_free ((char*)mname);
3615 mono_raise_exception (ex);
3617 res = mono_array_new_specific (array_vtable, method_array->len);
3620 for (i = 0; i < method_array->len; ++i) {
3621 MonoMethod *method = g_ptr_array_index (method_array, i);
3622 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3625 g_ptr_array_free (method_array, TRUE);
3629 ICALL_EXPORT MonoArray*
3630 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3633 static MonoClass *System_Reflection_ConstructorInfo;
3634 MonoClass *startklass, *klass, *refklass;
3639 gpointer iter = NULL;
3640 MonoPtrArray tmp_array;
3642 MONO_ARCH_SAVE_REGS;
3644 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3646 domain = ((MonoObject *)type)->vtable->domain;
3647 if (type->type->byref)
3648 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3649 klass = startklass = mono_class_from_mono_type (type->type);
3650 refklass = mono_class_from_mono_type (reftype->type);
3652 if (!System_Reflection_ConstructorInfo)
3653 System_Reflection_ConstructorInfo = mono_class_from_name (
3654 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3657 while ((method = mono_class_get_methods (klass, &iter))) {
3659 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3661 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3662 if (bflags & BFLAGS_Public)
3665 if (bflags & BFLAGS_NonPublic)
3671 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3672 if (bflags & BFLAGS_Static)
3673 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3676 if (bflags & BFLAGS_Instance)
3682 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3684 mono_ptr_array_append (tmp_array, member);
3687 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3689 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3690 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3692 mono_ptr_array_destroy (tmp_array);
3698 property_hash (gconstpointer data)
3700 MonoProperty *prop = (MonoProperty*)data;
3702 return g_str_hash (prop->name);
3706 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3708 // Properties are hide-by-name-and-signature
3709 if (!g_str_equal (prop1->name, prop2->name))
3712 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3714 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3720 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3725 return method_nonpublic (accessor, start_klass);
3728 ICALL_EXPORT MonoArray*
3729 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3733 static MonoClass *System_Reflection_PropertyInfo;
3734 MonoClass *startklass, *klass;
3740 gchar *propname = NULL;
3741 int (*compare_func) (const char *s1, const char *s2) = NULL;
3743 GHashTable *properties = NULL;
3744 MonoPtrArray tmp_array;
3746 MONO_ARCH_SAVE_REGS;
3748 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3750 if (!System_Reflection_PropertyInfo)
3751 System_Reflection_PropertyInfo = mono_class_from_name (
3752 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3754 domain = ((MonoObject *)type)->vtable->domain;
3755 if (type->type->byref)
3756 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3757 klass = startklass = mono_class_from_mono_type (type->type);
3760 propname = mono_string_to_utf8 (name);
3761 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3764 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3766 mono_class_setup_vtable (klass);
3767 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3771 while ((prop = mono_class_get_properties (klass, &iter))) {
3777 flags = method->flags;
3780 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3781 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3782 if (bflags & BFLAGS_Public)
3784 } else if (bflags & BFLAGS_NonPublic) {
3785 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3786 property_accessor_nonpublic(prop->set, startklass == klass)) {
3793 if (flags & METHOD_ATTRIBUTE_STATIC) {
3794 if (bflags & BFLAGS_Static)
3795 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3798 if (bflags & BFLAGS_Instance)
3807 if (compare_func (propname, prop->name))
3811 if (g_hash_table_lookup (properties, prop))
3814 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3816 g_hash_table_insert (properties, prop, prop);
3818 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3821 g_hash_table_destroy (properties);
3824 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3825 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3826 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3828 mono_ptr_array_destroy (tmp_array);
3834 g_hash_table_destroy (properties);
3837 mono_ptr_array_destroy (tmp_array);
3839 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3840 ex = mono_class_get_exception_for_failure (klass);
3842 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3843 mono_loader_clear_error ();
3845 mono_raise_exception (ex);
3849 ICALL_EXPORT MonoReflectionEvent *
3850 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3853 MonoClass *klass, *startklass;
3858 int (*compare_func) (const char *s1, const char *s2);
3860 MONO_ARCH_SAVE_REGS;
3862 event_name = mono_string_to_utf8 (name);
3863 if (type->type->byref)
3865 klass = startklass = mono_class_from_mono_type (type->type);
3866 domain = mono_object_domain (type);
3868 mono_class_init_or_throw (klass);
3870 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3872 if (klass->exception_type != MONO_EXCEPTION_NONE)
3873 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3876 while ((event = mono_class_get_events (klass, &iter))) {
3877 if (compare_func (event->name, event_name))
3880 method = event->add;
3882 method = event->remove;
3884 method = event->raise;
3886 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3887 if (!(bflags & BFLAGS_Public))
3890 if (!(bflags & BFLAGS_NonPublic))
3892 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3896 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3897 if (!(bflags & BFLAGS_Static))
3899 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3902 if (!(bflags & BFLAGS_Instance))
3906 if (!(bflags & BFLAGS_NonPublic))
3909 g_free (event_name);
3910 return mono_event_get_object (domain, startklass, event);
3913 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3916 g_free (event_name);
3920 ICALL_EXPORT MonoArray*
3921 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3925 static MonoClass *System_Reflection_EventInfo;
3926 MonoClass *startklass, *klass;
3933 MonoPtrArray tmp_array;
3935 MONO_ARCH_SAVE_REGS;
3937 mono_ptr_array_init (tmp_array, 4);
3939 if (!System_Reflection_EventInfo)
3940 System_Reflection_EventInfo = mono_class_from_name (
3941 mono_defaults.corlib, "System.Reflection", "EventInfo");
3943 domain = mono_object_domain (type);
3944 if (type->type->byref)
3945 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3946 klass = startklass = mono_class_from_mono_type (type->type);
3949 mono_class_setup_vtable (klass);
3950 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3954 while ((event = mono_class_get_events (klass, &iter))) {
3956 method = event->add;
3958 method = event->remove;
3960 method = event->raise;
3962 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3963 if (bflags & BFLAGS_Public)
3965 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3966 if (bflags & BFLAGS_NonPublic)
3971 if (bflags & BFLAGS_NonPublic)
3977 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3978 if (bflags & BFLAGS_Static)
3979 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3982 if (bflags & BFLAGS_Instance)
3987 if (bflags & BFLAGS_Instance)
3991 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3993 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3996 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
3998 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3999 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4001 mono_ptr_array_destroy (tmp_array);
4006 mono_ptr_array_destroy (tmp_array);
4007 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4008 ex = mono_class_get_exception_for_failure (klass);
4010 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4011 mono_loader_clear_error ();
4013 mono_raise_exception (ex);
4017 ICALL_EXPORT MonoReflectionType *
4018 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4026 MONO_ARCH_SAVE_REGS;
4029 mono_raise_exception (mono_get_exception_argument_null ("name"));
4031 domain = ((MonoObject *)type)->vtable->domain;
4032 if (type->type->byref)
4034 klass = mono_class_from_mono_type (type->type);
4036 str = mono_string_to_utf8 (name);
4039 if (klass->exception_type != MONO_EXCEPTION_NONE)
4040 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4043 * If a nested type is generic, return its generic type definition.
4044 * Note that this means that the return value is essentially a
4045 * nested type of the generic type definition of @klass.
4047 * A note in MSDN claims that a generic type definition can have
4048 * nested types that aren't generic. In any case, the container of that
4049 * nested type would be the generic type definition.
4051 if (klass->generic_class)
4052 klass = klass->generic_class->container_class;
4055 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4057 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4058 if (bflags & BFLAGS_Public)
4061 if (bflags & BFLAGS_NonPublic)
4066 if (strcmp (nested->name, str) == 0){
4068 return mono_type_get_object (domain, &nested->byval_arg);
4071 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4077 ICALL_EXPORT MonoArray*
4078 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4087 MonoPtrArray tmp_array;
4089 MONO_ARCH_SAVE_REGS;
4091 domain = ((MonoObject *)type)->vtable->domain;
4092 if (type->type->byref)
4093 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4094 klass = mono_class_from_mono_type (type->type);
4097 * If a nested type is generic, return its generic type definition.
4098 * Note that this means that the return value is essentially the set
4099 * of nested types of the generic type definition of @klass.
4101 * A note in MSDN claims that a generic type definition can have
4102 * nested types that aren't generic. In any case, the container of that
4103 * nested type would be the generic type definition.
4105 if (klass->generic_class)
4106 klass = klass->generic_class->container_class;
4108 mono_ptr_array_init (tmp_array, 1);
4110 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4112 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4113 if (bflags & BFLAGS_Public)
4116 if (bflags & BFLAGS_NonPublic)
4121 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4122 mono_ptr_array_append (tmp_array, member);
4125 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4127 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4128 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4130 mono_ptr_array_destroy (tmp_array);
4135 ICALL_EXPORT MonoReflectionType*
4136 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4139 MonoType *type = NULL;
4140 MonoTypeNameParse info;
4141 gboolean type_resolve;
4143 MONO_ARCH_SAVE_REGS;
4145 /* On MS.NET, this does not fire a TypeResolve event */
4146 type_resolve = TRUE;
4147 str = mono_string_to_utf8 (name);
4148 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4149 if (!mono_reflection_parse_type (str, &info)) {
4151 mono_reflection_free_type_info (&info);
4152 if (throwOnError) /* uhm: this is a parse error, though... */
4153 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4154 /*g_print ("failed parse\n");*/
4158 if (info.assembly.name) {
4160 mono_reflection_free_type_info (&info);
4162 /* 1.0 and 2.0 throw different exceptions */
4163 if (mono_defaults.generic_ilist_class)
4164 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4166 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4171 if (module != NULL) {
4173 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4178 if (assembly->assembly->dynamic) {
4179 /* Enumerate all modules */
4180 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4184 if (abuilder->modules) {
4185 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4186 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4187 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4193 if (!type && abuilder->loaded_modules) {
4194 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4195 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4196 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4203 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4205 mono_reflection_free_type_info (&info);
4207 MonoException *e = NULL;
4210 e = mono_get_exception_type_load (name, NULL);
4212 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4213 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4215 mono_loader_clear_error ();
4218 mono_raise_exception (e);
4221 } else if (mono_loader_get_last_error ()) {
4223 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4224 mono_loader_clear_error ();
4227 if (type->type == MONO_TYPE_CLASS) {
4228 MonoClass *klass = mono_type_get_class (type);
4230 if (mono_is_security_manager_active () && !klass->exception_type)
4231 /* Some security problems are detected during generic vtable construction */
4232 mono_class_setup_vtable (klass);
4233 /* need to report exceptions ? */
4234 if (throwOnError && klass->exception_type) {
4235 /* report SecurityException (or others) that occured when loading the assembly */
4236 MonoException *exc = mono_class_get_exception_for_failure (klass);
4237 mono_loader_clear_error ();
4238 mono_raise_exception (exc);
4239 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4244 /* g_print ("got it\n"); */
4245 return mono_type_get_object (mono_object_domain (assembly), type);
4249 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4252 gchar *shadow_ini_file;
4255 /* Check for shadow-copied assembly */
4256 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4257 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4259 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4260 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4266 g_free (shadow_ini_file);
4267 if (content != NULL) {
4270 *filename = content;
4277 ICALL_EXPORT MonoString *
4278 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4280 MonoDomain *domain = mono_object_domain (assembly);
4281 MonoAssembly *mass = assembly->assembly;
4282 MonoString *res = NULL;
4287 MONO_ARCH_SAVE_REGS;
4289 if (g_path_is_absolute (mass->image->name)) {
4290 absolute = g_strdup (mass->image->name);
4291 dirname = g_path_get_dirname (absolute);
4293 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4294 dirname = g_strdup (mass->basedir);
4297 replace_shadow_path (domain, dirname, &absolute);
4302 for (i = strlen (absolute) - 1; i >= 0; i--)
4303 if (absolute [i] == '\\')
4308 uri = g_filename_to_uri (absolute, NULL, NULL);
4310 const char *prepend = "file://";
4312 if (*absolute == '/' && *(absolute + 1) == '/') {
4315 prepend = "file:///";
4318 uri = g_strconcat (prepend, absolute, NULL);
4322 res = mono_string_new (domain, uri);
4329 ICALL_EXPORT MonoBoolean
4330 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4332 MonoAssembly *mass = assembly->assembly;
4334 MONO_ARCH_SAVE_REGS;
4336 return mass->in_gac;
4339 ICALL_EXPORT MonoReflectionAssembly*
4340 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4344 MonoImageOpenStatus status;
4346 MONO_ARCH_SAVE_REGS;
4348 name = mono_string_to_utf8 (mname);
4349 res = mono_assembly_load_with_partial_name (name, &status);
4355 return mono_assembly_get_object (mono_domain_get (), res);
4358 ICALL_EXPORT MonoString *
4359 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4361 MonoDomain *domain = mono_object_domain (assembly);
4364 MONO_ARCH_SAVE_REGS;
4366 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4371 ICALL_EXPORT MonoBoolean
4372 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4374 MONO_ARCH_SAVE_REGS;
4376 return assembly->assembly->ref_only;
4379 ICALL_EXPORT MonoString *
4380 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4382 MonoDomain *domain = mono_object_domain (assembly);
4384 MONO_ARCH_SAVE_REGS;
4386 return mono_string_new (domain, assembly->assembly->image->version);
4389 ICALL_EXPORT MonoReflectionMethod*
4390 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4392 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4394 MONO_ARCH_SAVE_REGS;
4398 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4401 ICALL_EXPORT MonoReflectionModule*
4402 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4404 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4407 ICALL_EXPORT MonoArray*
4408 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4410 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4411 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4415 MONO_ARCH_SAVE_REGS;
4417 for (i = 0; i < table->rows; ++i) {
4418 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4419 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4425 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4427 static MonoClass *System_Version = NULL;
4428 static MonoMethod *create_version = NULL;
4432 if (!System_Version) {
4433 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4434 g_assert (System_Version);
4437 if (!create_version) {
4438 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4439 create_version = mono_method_desc_search_in_class (desc, System_Version);
4440 g_assert (create_version);
4441 mono_method_desc_free (desc);
4447 args [3] = &revision;
4448 result = mono_object_new (domain, System_Version);
4449 mono_runtime_invoke (create_version, result, args, NULL);
4454 ICALL_EXPORT MonoArray*
4455 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4457 static MonoClass *System_Reflection_AssemblyName;
4459 MonoDomain *domain = mono_object_domain (assembly);
4461 static MonoMethod *create_culture = NULL;
4462 MonoImage *image = assembly->assembly->image;
4465 MONO_ARCH_SAVE_REGS;
4467 if (!System_Reflection_AssemblyName)
4468 System_Reflection_AssemblyName = mono_class_from_name (
4469 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4471 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4474 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4476 if (count > 0 && !create_culture) {
4477 MonoMethodDesc *desc = mono_method_desc_new (
4478 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4479 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4480 g_assert (create_culture);
4481 mono_method_desc_free (desc);
4484 for (i = 0; i < count; i++) {
4485 MonoReflectionAssemblyName *aname;
4486 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4488 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4490 aname = (MonoReflectionAssemblyName *) mono_object_new (
4491 domain, System_Reflection_AssemblyName);
4493 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4495 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4496 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4497 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4498 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4499 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4500 aname->versioncompat = 1; /* SameMachine (default) */
4501 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4502 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4504 if (create_culture) {
4506 MonoBoolean assembly_ref = 1;
4507 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4508 args [1] = &assembly_ref;
4509 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4512 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4513 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4514 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4516 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4517 /* public key token isn't copied - the class library will
4518 automatically generate it from the public key if required */
4519 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4520 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4522 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4523 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4526 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4529 /* note: this function doesn't return the codebase on purpose (i.e. it can
4530 be used under partial trust as path information isn't present). */
4532 mono_array_setref (result, i, aname);
4543 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4545 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4547 mono_array_setref (info->res, info->idx, name);
4551 ICALL_EXPORT MonoArray*
4552 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4554 MonoImage *img = assembly->assembly->image;
4559 MONO_ARCH_SAVE_REGS;
4561 mono_image_lock (img);
4562 mono_image_init_name_cache (img);
4565 len = g_hash_table_size (img->name_cache);
4566 mono_image_unlock (img);
4568 /*we can't create objects holding the image lock */
4569 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4571 mono_image_lock (img);
4572 /*len might have changed, create a new array*/
4573 if (len != g_hash_table_size (img->name_cache))
4578 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4579 mono_image_unlock (img);
4584 /* move this in some file in mono/util/ */
4586 g_concat_dir_and_file (const char *dir, const char *file)
4588 g_return_val_if_fail (dir != NULL, NULL);
4589 g_return_val_if_fail (file != NULL, NULL);
4592 * If the directory name doesn't have a / on the end, we need
4593 * to add one so we get a proper path to the file
4595 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4596 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4598 return g_strconcat (dir, file, NULL);
4602 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4604 char *n = mono_string_to_utf8 (name);
4605 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4607 guint32 cols [MONO_MANIFEST_SIZE];
4608 guint32 impl, file_idx;
4612 MONO_ARCH_SAVE_REGS;
4614 for (i = 0; i < table->rows; ++i) {
4615 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4616 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4617 if (strcmp (val, n) == 0)
4621 if (i == table->rows)
4624 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4627 * this code should only be called after obtaining the
4628 * ResourceInfo and handling the other cases.
4630 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4631 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4633 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4638 module = assembly->assembly->image;
4640 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4642 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4645 ICALL_EXPORT gboolean
4646 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4648 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4650 guint32 cols [MONO_MANIFEST_SIZE];
4651 guint32 file_cols [MONO_FILE_SIZE];
4655 MONO_ARCH_SAVE_REGS;
4657 n = mono_string_to_utf8 (name);
4658 for (i = 0; i < table->rows; ++i) {
4659 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4660 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4661 if (strcmp (val, n) == 0)
4665 if (i == table->rows)
4668 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4669 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4672 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4673 case MONO_IMPLEMENTATION_FILE:
4674 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4675 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4676 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4677 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4678 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4679 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4682 info->location = RESOURCE_LOCATION_EMBEDDED;
4685 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4686 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4687 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4688 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4689 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4690 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4692 mono_raise_exception (ex);
4694 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4696 /* Obtain info recursively */
4697 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4698 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4701 case MONO_IMPLEMENTATION_EXP_TYPE:
4702 g_assert_not_reached ();
4710 ICALL_EXPORT MonoObject*
4711 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4713 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4714 MonoArray *result = NULL;
4719 MONO_ARCH_SAVE_REGS;
4721 /* check hash if needed */
4723 n = mono_string_to_utf8 (name);
4724 for (i = 0; i < table->rows; ++i) {
4725 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4726 if (strcmp (val, n) == 0) {
4729 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4730 fn = mono_string_new (mono_object_domain (assembly), n);
4732 return (MonoObject*)fn;
4740 for (i = 0; i < table->rows; ++i) {
4741 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4745 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4748 for (i = 0; i < table->rows; ++i) {
4749 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4750 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4751 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4752 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4757 return (MonoObject*)result;
4760 ICALL_EXPORT MonoArray*
4761 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4763 MonoDomain *domain = mono_domain_get();
4766 int i, j, file_count = 0;
4767 MonoImage **modules;
4768 guint32 module_count, real_module_count;
4769 MonoTableInfo *table;
4770 guint32 cols [MONO_FILE_SIZE];
4771 MonoImage *image = assembly->assembly->image;
4773 g_assert (image != NULL);
4774 g_assert (!assembly->assembly->dynamic);
4776 table = &image->tables [MONO_TABLE_FILE];
4777 file_count = table->rows;
4779 modules = image->modules;
4780 module_count = image->module_count;
4782 real_module_count = 0;
4783 for (i = 0; i < module_count; ++i)
4785 real_module_count ++;
4787 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4788 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4790 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4792 for (i = 0; i < module_count; ++i)
4794 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4798 for (i = 0; i < file_count; ++i, ++j) {
4799 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4800 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4801 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4803 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4805 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4806 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4808 mono_array_setref (res, j, mono_module_get_object (domain, m));
4815 ICALL_EXPORT MonoReflectionMethod*
4816 ves_icall_GetCurrentMethod (void)
4818 MonoMethod *m = mono_method_get_last_managed ();
4820 while (m->is_inflated)
4821 m = ((MonoMethodInflated*)m)->declaring;
4823 return mono_method_get_object (mono_domain_get (), m, NULL);
4828 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4831 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4832 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4833 //method is inflated, we should inflate it on the other class
4834 MonoGenericContext ctx;
4835 ctx.method_inst = inflated->context.method_inst;
4836 ctx.class_inst = inflated->context.class_inst;
4837 if (klass->generic_class)
4838 ctx.class_inst = klass->generic_class->context.class_inst;
4839 else if (klass->generic_container)
4840 ctx.class_inst = klass->generic_container->context.class_inst;
4841 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4844 mono_class_setup_methods (method->klass);
4845 if (method->klass->exception_type)
4847 for (i = 0; i < method->klass->method.count; ++i) {
4848 if (method->klass->methods [i] == method) {
4853 mono_class_setup_methods (klass);
4854 if (klass->exception_type)
4856 g_assert (offset >= 0 && offset < klass->method.count);
4857 return klass->methods [offset];
4860 ICALL_EXPORT MonoReflectionMethod*
4861 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4865 klass = mono_class_from_mono_type (type);
4866 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4868 if (method->klass != klass) {
4869 method = mono_method_get_equivalent_method (method, klass);
4874 klass = method->klass;
4875 return mono_method_get_object (mono_domain_get (), method, klass);
4878 ICALL_EXPORT MonoReflectionMethod*
4879 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4881 return mono_method_get_object (mono_domain_get (), method, NULL);
4884 ICALL_EXPORT MonoReflectionMethodBody*
4885 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4887 return mono_method_body_get_object (mono_domain_get (), method);
4890 ICALL_EXPORT MonoReflectionAssembly*
4891 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4893 MonoMethod *dest = NULL;
4895 MONO_ARCH_SAVE_REGS;
4897 mono_stack_walk_no_il (get_executing, &dest);
4898 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4902 ICALL_EXPORT MonoReflectionAssembly*
4903 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4905 MonoDomain* domain = mono_domain_get ();
4907 MONO_ARCH_SAVE_REGS;
4909 if (!domain->entry_assembly)
4912 return mono_assembly_get_object (domain, domain->entry_assembly);
4915 ICALL_EXPORT MonoReflectionAssembly*
4916 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4921 MONO_ARCH_SAVE_REGS;
4924 mono_stack_walk_no_il (get_executing, &dest);
4926 mono_stack_walk_no_il (get_caller, &dest);
4929 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4932 ICALL_EXPORT MonoString *
4933 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4934 gboolean assembly_qualified)
4936 MonoDomain *domain = mono_object_domain (object);
4937 MonoTypeNameFormat format;
4942 format = assembly_qualified ?
4943 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4944 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4946 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4948 name = mono_type_get_name_full (object->type, format);
4952 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4957 res = mono_string_new (domain, name);
4964 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4966 MonoClass *klass = mono_class_from_mono_type (this->type);
4967 mono_class_init_or_throw (klass);
4968 return mono_security_core_clr_class_level (klass);
4972 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4974 static MonoMethod *create_culture = NULL;
4977 const char *pkey_ptr;
4979 MonoBoolean assembly_ref = 0;
4981 MONO_ARCH_SAVE_REGS;
4983 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4984 aname->major = name->major;
4985 aname->minor = name->minor;
4986 aname->build = name->build;
4987 aname->flags = name->flags;
4988 aname->revision = name->revision;
4989 aname->hashalg = name->hash_alg;
4990 aname->versioncompat = 1; /* SameMachine (default) */
4991 aname->processor_architecture = name->arch;
4993 if (by_default_version)
4994 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4997 if (absolute != NULL && *absolute != '\0') {
4998 const gchar *prepend = "file://";
5001 codebase = g_strdup (absolute);
5006 for (i = strlen (codebase) - 1; i >= 0; i--)
5007 if (codebase [i] == '\\')
5010 if (*codebase == '/' && *(codebase + 1) == '/') {
5013 prepend = "file:///";
5017 result = g_strconcat (prepend, codebase, NULL);
5023 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5027 if (!create_culture) {
5028 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5029 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5030 g_assert (create_culture);
5031 mono_method_desc_free (desc);
5034 if (name->culture) {
5035 args [0] = mono_string_new (domain, name->culture);
5036 args [1] = &assembly_ref;
5037 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5040 if (name->public_key) {
5041 pkey_ptr = (char*)name->public_key;
5042 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5044 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5045 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5046 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5047 } else if (default_publickey) {
5048 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5049 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5052 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5053 if (name->public_key_token [0]) {
5057 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5058 p = mono_array_addr (aname->keyToken, char, 0);
5060 for (i = 0, j = 0; i < 8; i++) {
5061 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5062 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5065 } else if (default_token) {
5066 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5070 ICALL_EXPORT MonoString *
5071 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5073 MonoDomain *domain = mono_object_domain (assembly);
5074 MonoAssembly *mass = assembly->assembly;
5078 name = mono_stringify_assembly_name (&mass->aname);
5079 res = mono_string_new (domain, name);
5086 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5089 MonoAssembly *mass = assembly->assembly;
5091 MONO_ARCH_SAVE_REGS;
5093 if (g_path_is_absolute (mass->image->name)) {
5094 fill_reflection_assembly_name (mono_object_domain (assembly),
5095 aname, &mass->aname, mass->image->name, TRUE,
5099 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5101 fill_reflection_assembly_name (mono_object_domain (assembly),
5102 aname, &mass->aname, absolute, TRUE, TRUE,
5109 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5112 MonoImageOpenStatus status = MONO_IMAGE_OK;
5115 MonoAssemblyName name;
5118 MONO_ARCH_SAVE_REGS;
5120 filename = mono_string_to_utf8 (fname);
5122 dirname = g_path_get_dirname (filename);
5123 replace_shadow_path (mono_domain_get (), dirname, &filename);
5126 image = mono_image_open (filename, &status);
5132 if (status == MONO_IMAGE_IMAGE_INVALID)
5133 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5135 exc = mono_get_exception_file_not_found2 (NULL, fname);
5136 mono_raise_exception (exc);
5139 res = mono_assembly_fill_assembly_name (image, &name);
5141 mono_image_close (image);
5143 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5146 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5150 mono_image_close (image);
5153 ICALL_EXPORT MonoBoolean
5154 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5155 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5157 MonoBoolean result = FALSE;
5158 MonoDeclSecurityEntry entry;
5160 /* SecurityAction.RequestMinimum */
5161 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5162 *minimum = entry.blob;
5163 *minLength = entry.size;
5166 /* SecurityAction.RequestOptional */
5167 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5168 *optional = entry.blob;
5169 *optLength = entry.size;
5172 /* SecurityAction.RequestRefuse */
5173 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5174 *refused = entry.blob;
5175 *refLength = entry.size;
5183 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5187 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5189 guint32 attrs, visibility;
5191 /* we start the count from 1 because we skip the special type <Module> */
5194 for (i = 1; i < tdef->rows; ++i) {
5195 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5196 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5197 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5201 count = tdef->rows - 1;
5203 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5204 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5206 for (i = 1; i < tdef->rows; ++i) {
5207 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5208 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5209 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5210 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5212 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5214 MonoLoaderError *error;
5217 error = mono_loader_get_last_error ();
5218 g_assert (error != NULL);
5220 ex = mono_loader_error_prepare_exception (error);
5221 mono_array_setref (*exceptions, count, ex);
5223 if (mono_loader_get_last_error ())
5224 mono_loader_clear_error ();
5232 ICALL_EXPORT MonoArray*
5233 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5235 MonoArray *res = NULL;
5236 MonoArray *exceptions = NULL;
5237 MonoImage *image = NULL;
5238 MonoTableInfo *table = NULL;
5241 int i, len, ex_count;
5243 MONO_ARCH_SAVE_REGS;
5245 domain = mono_object_domain (assembly);
5247 g_assert (!assembly->assembly->dynamic);
5248 image = assembly->assembly->image;
5249 table = &image->tables [MONO_TABLE_FILE];
5250 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5252 /* Append data from all modules in the assembly */
5253 for (i = 0; i < table->rows; ++i) {
5254 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5255 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5258 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5259 /* Append the new types to the end of the array */
5260 if (mono_array_length (res2) > 0) {
5262 MonoArray *res3, *ex3;
5264 len1 = mono_array_length (res);
5265 len2 = mono_array_length (res2);
5267 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5268 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5269 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5272 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5273 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5274 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5281 /* the ReflectionTypeLoadException must have all the types (Types property),
5282 * NULL replacing types which throws an exception. The LoaderException must
5283 * contain all exceptions for NULL items.
5286 len = mono_array_length (res);
5289 for (i = 0; i < len; i++) {
5290 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5294 klass = mono_type_get_class (t->type);
5295 if ((klass != NULL) && klass->exception_type) {
5296 /* keep the class in the list */
5297 list = g_list_append (list, klass);
5298 /* and replace Type with NULL */
5299 mono_array_setref (res, i, NULL);
5306 if (list || ex_count) {
5308 MonoException *exc = NULL;
5309 MonoArray *exl = NULL;
5310 int j, length = g_list_length (list) + ex_count;
5312 mono_loader_clear_error ();
5314 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5315 /* Types for which mono_class_get () succeeded */
5316 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5317 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5318 mono_array_setref (exl, i, exc);
5320 /* Types for which it don't */
5321 for (j = 0; j < mono_array_length (exceptions); ++j) {
5322 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5324 g_assert (i < length);
5325 mono_array_setref (exl, i, exc);
5332 exc = mono_get_exception_reflection_type_load (res, exl);
5333 mono_loader_clear_error ();
5334 mono_raise_exception (exc);
5340 ICALL_EXPORT gboolean
5341 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5343 MonoAssemblyName aname;
5344 MonoDomain *domain = mono_object_domain (name);
5346 gboolean is_version_defined;
5347 gboolean is_token_defined;
5349 aname.public_key = NULL;
5350 val = mono_string_to_utf8 (assname);
5351 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5352 g_free ((guint8*) aname.public_key);
5357 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5358 FALSE, is_token_defined);
5360 mono_assembly_name_free (&aname);
5361 g_free ((guint8*) aname.public_key);
5367 ICALL_EXPORT MonoReflectionType*
5368 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5370 MonoDomain *domain = mono_object_domain (module);
5373 MONO_ARCH_SAVE_REGS;
5375 g_assert (module->image);
5377 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5378 /* These images do not have a global type */
5381 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5382 return mono_type_get_object (domain, &klass->byval_arg);
5386 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5388 /*if (module->image)
5389 mono_image_close (module->image);*/
5392 ICALL_EXPORT MonoString*
5393 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5395 MonoDomain *domain = mono_object_domain (module);
5397 MONO_ARCH_SAVE_REGS;
5399 g_assert (module->image);
5400 return mono_string_new (domain, module->image->guid);
5403 ICALL_EXPORT gpointer
5404 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5407 if (module->image && module->image->is_module_handle)
5408 return module->image->raw_data;
5411 return (gpointer) (-1);
5415 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5417 if (image->dynamic) {
5418 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5419 *pe_kind = dyn->pe_kind;
5420 *machine = dyn->machine;
5423 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5424 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5429 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5431 return (image->md_version_major << 16) | (image->md_version_minor);
5434 ICALL_EXPORT MonoArray*
5435 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5437 MonoArray *exceptions;
5440 MONO_ARCH_SAVE_REGS;
5443 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5445 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5446 for (i = 0; i < mono_array_length (exceptions); ++i) {
5447 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5449 mono_raise_exception (ex);
5456 mono_memberref_is_method (MonoImage *image, guint32 token)
5458 if (!image->dynamic) {
5459 guint32 cols [MONO_MEMBERREF_SIZE];
5461 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5462 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5463 mono_metadata_decode_blob_size (sig, &sig);
5464 return (*sig != 0x6);
5466 MonoClass *handle_class;
5468 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5471 return mono_defaults.methodhandle_class == handle_class;
5476 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5479 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5480 mono_array_addr (type_args, MonoType*, 0));
5482 context->class_inst = NULL;
5484 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5485 mono_array_addr (method_args, MonoType*, 0));
5487 context->method_inst = NULL;
5490 ICALL_EXPORT MonoType*
5491 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5494 int table = mono_metadata_token_table (token);
5495 int index = mono_metadata_token_index (token);
5496 MonoGenericContext context;
5498 *error = ResolveTokenError_Other;
5500 /* Validate token */
5501 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5502 (table != MONO_TABLE_TYPESPEC)) {
5503 *error = ResolveTokenError_BadTable;
5507 if (image->dynamic) {
5508 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5509 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5510 return klass ? &klass->byval_arg : NULL;
5513 init_generic_context_from_args (&context, type_args, method_args);
5514 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5515 return klass ? &klass->byval_arg : NULL;
5518 if ((index <= 0) || (index > image->tables [table].rows)) {
5519 *error = ResolveTokenError_OutOfRange;
5523 init_generic_context_from_args (&context, type_args, method_args);
5524 klass = mono_class_get_full (image, token, &context);
5526 if (mono_loader_get_last_error ())
5527 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5530 return &klass->byval_arg;
5535 ICALL_EXPORT MonoMethod*
5536 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5538 int table = mono_metadata_token_table (token);
5539 int index = mono_metadata_token_index (token);
5540 MonoGenericContext context;
5543 *error = ResolveTokenError_Other;
5545 /* Validate token */
5546 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5547 (table != MONO_TABLE_MEMBERREF)) {
5548 *error = ResolveTokenError_BadTable;
5552 if (image->dynamic) {
5553 if (table == MONO_TABLE_METHOD)
5554 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5556 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5557 *error = ResolveTokenError_BadTable;
5561 init_generic_context_from_args (&context, type_args, method_args);
5562 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5565 if ((index <= 0) || (index > image->tables [table].rows)) {
5566 *error = ResolveTokenError_OutOfRange;
5569 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5570 *error = ResolveTokenError_BadTable;
5574 init_generic_context_from_args (&context, type_args, method_args);
5575 method = mono_get_method_full (image, token, NULL, &context);
5577 if (mono_loader_get_last_error ())
5578 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5583 ICALL_EXPORT MonoString*
5584 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5586 int index = mono_metadata_token_index (token);
5588 *error = ResolveTokenError_Other;
5590 /* Validate token */
5591 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5592 *error = ResolveTokenError_BadTable;
5597 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5599 if ((index <= 0) || (index >= image->heap_us.size)) {
5600 *error = ResolveTokenError_OutOfRange;
5604 /* FIXME: What to do if the index points into the middle of a string ? */
5606 return mono_ldstr (mono_domain_get (), image, index);
5609 ICALL_EXPORT MonoClassField*
5610 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5613 int table = mono_metadata_token_table (token);
5614 int index = mono_metadata_token_index (token);
5615 MonoGenericContext context;
5616 MonoClassField *field;
5618 *error = ResolveTokenError_Other;
5620 /* Validate token */
5621 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5622 *error = ResolveTokenError_BadTable;
5626 if (image->dynamic) {
5627 if (table == MONO_TABLE_FIELD)
5628 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5630 if (mono_memberref_is_method (image, token)) {
5631 *error = ResolveTokenError_BadTable;
5635 init_generic_context_from_args (&context, type_args, method_args);
5636 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5639 if ((index <= 0) || (index > image->tables [table].rows)) {
5640 *error = ResolveTokenError_OutOfRange;
5643 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5644 *error = ResolveTokenError_BadTable;
5648 init_generic_context_from_args (&context, type_args, method_args);
5649 field = mono_field_from_token (image, token, &klass, &context);
5651 if (mono_loader_get_last_error ())
5652 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5658 ICALL_EXPORT MonoObject*
5659 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5661 int table = mono_metadata_token_table (token);
5663 *error = ResolveTokenError_Other;
5666 case MONO_TABLE_TYPEDEF:
5667 case MONO_TABLE_TYPEREF:
5668 case MONO_TABLE_TYPESPEC: {
5669 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5671 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5675 case MONO_TABLE_METHOD:
5676 case MONO_TABLE_METHODSPEC: {
5677 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5679 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5683 case MONO_TABLE_FIELD: {
5684 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5686 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5690 case MONO_TABLE_MEMBERREF:
5691 if (mono_memberref_is_method (image, token)) {
5692 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5694 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5699 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5701 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5708 *error = ResolveTokenError_BadTable;
5714 ICALL_EXPORT MonoArray*
5715 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5717 int table = mono_metadata_token_table (token);
5718 int idx = mono_metadata_token_index (token);
5719 MonoTableInfo *tables = image->tables;
5724 *error = ResolveTokenError_OutOfRange;
5726 /* FIXME: Support other tables ? */
5727 if (table != MONO_TABLE_STANDALONESIG)
5733 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5736 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5738 ptr = mono_metadata_blob_heap (image, sig);
5739 len = mono_metadata_decode_blob_size (ptr, &ptr);
5741 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5742 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5746 ICALL_EXPORT MonoReflectionType*
5747 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5750 int isbyref = 0, rank;
5751 char *str = mono_string_to_utf8 (smodifiers);
5754 MONO_ARCH_SAVE_REGS;
5756 klass = mono_class_from_mono_type (tb->type.type);
5758 /* logic taken from mono_reflection_parse_type(): keep in sync */
5762 if (isbyref) { /* only one level allowed by the spec */
5769 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5772 klass = mono_ptr_class_get (&klass->byval_arg);
5773 mono_class_init (klass);
5784 else if (*p != '*') { /* '*' means unknown lower bound */
5795 klass = mono_array_class_get (klass, rank);
5796 mono_class_init (klass);
5803 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5806 ICALL_EXPORT MonoBoolean
5807 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5812 MONO_ARCH_SAVE_REGS;
5815 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5821 check_for_invalid_type (MonoClass *klass)
5825 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5828 name = mono_type_get_full_name (klass);
5829 str = mono_string_new (mono_domain_get (), name);
5831 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5834 ICALL_EXPORT MonoReflectionType *
5835 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5837 MonoClass *klass, *aklass;
5839 MONO_ARCH_SAVE_REGS;
5841 klass = mono_class_from_mono_type (type->type);
5842 check_for_invalid_type (klass);
5844 if (rank == 0) //single dimentional array
5845 aklass = mono_array_class_get (klass, 1);
5847 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5849 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5852 ICALL_EXPORT MonoReflectionType *
5853 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5857 MONO_ARCH_SAVE_REGS;
5859 klass = mono_class_from_mono_type (type->type);
5860 mono_class_init_or_throw (klass);
5861 check_for_invalid_type (klass);
5863 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5866 ICALL_EXPORT MonoReflectionType *
5867 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5869 MonoClass *klass, *pklass;
5871 klass = mono_class_from_mono_type (type->type);
5872 mono_class_init_or_throw (klass);
5873 check_for_invalid_type (klass);
5875 pklass = mono_ptr_class_get (type->type);
5877 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5880 ICALL_EXPORT MonoObject *
5881 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5882 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5884 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5885 MonoObject *delegate;
5887 MonoMethod *method = info->method;
5889 MONO_ARCH_SAVE_REGS;
5891 mono_class_init_or_throw (delegate_class);
5893 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5895 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5896 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5900 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5902 if (method->dynamic) {
5903 /* Creating a trampoline would leak memory */
5904 func = mono_compile_method (method);
5906 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5907 method = mono_object_get_virtual_method (target, method);
5908 func = mono_create_ftnptr (mono_domain_get (),
5909 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5912 mono_delegate_ctor_with_method (delegate, target, func, method);
5918 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5920 /* Reset the invoke impl to the default one */
5921 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5925 * Magic number to convert a time which is relative to
5926 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5928 #define EPOCH_ADJUST ((guint64)62135596800LL)
5931 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5933 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5936 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5938 convert_to_absolute_date(SYSTEMTIME *date)
5940 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5941 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5942 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5943 /* from the calendar FAQ */
5944 int a = (14 - date->wMonth) / 12;
5945 int y = date->wYear - a;
5946 int m = date->wMonth + 12 * a - 2;
5947 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5949 /* d is now the day of the week for the first of the month (0 == Sunday) */
5951 int day_of_week = date->wDayOfWeek;
5953 /* set day_in_month to the first day in the month which falls on day_of_week */
5954 int day_in_month = 1 + (day_of_week - d);
5955 if (day_in_month <= 0)
5958 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5959 date->wDay = day_in_month + (date->wDay - 1) * 7;
5960 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5967 * Return's the offset from GMT of a local time.
5969 * tm is a local time
5970 * t is the same local time as seconds.
5973 gmt_offset(struct tm *tm, time_t t)
5975 #if defined (HAVE_TM_GMTOFF)
5976 return tm->tm_gmtoff;
5981 g.tm_isdst = tm->tm_isdst;
5983 return (int)difftime(t, t2);
5988 * This is heavily based on zdump.c from glibc 2.2.
5990 * * data[0]: start of daylight saving time (in DateTime ticks).
5991 * * data[1]: end of daylight saving time (in DateTime ticks).
5992 * * data[2]: utcoffset (in TimeSpan ticks).
5993 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5994 * * name[0]: name of this timezone when not daylight saving.
5995 * * name[1]: name of this timezone when daylight saving.
5997 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5998 * the class library allows years between 1 and 9999.
6000 * Returns true on success and zero on failure.
6002 ICALL_EXPORT guint32
6003 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6006 MonoDomain *domain = mono_domain_get ();
6007 struct tm start, tt;
6011 int is_daylight = 0, day;
6014 MONO_ARCH_SAVE_REGS;
6016 MONO_CHECK_ARG_NULL (data);
6017 MONO_CHECK_ARG_NULL (names);
6019 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
6020 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6023 * no info is better than crashing: we'll need our own tz data
6024 * to make this work properly, anyway. The range is probably
6025 * reduced to 1970 .. 2037 because that is what mktime is
6026 * guaranteed to support (we get into an infinite loop
6030 memset (&start, 0, sizeof (start));
6033 start.tm_year = year-1900;
6035 t = mktime (&start);
6037 if ((year < 1970) || (year > 2037) || (t == -1)) {
6039 tt = *localtime (&t);
6040 strftime (tzone, sizeof (tzone), "%Z", &tt);
6041 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6042 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6046 gmtoff = gmt_offset (&start, t);
6048 /* For each day of the year, calculate the tm_gmtoff. */
6049 for (day = 0; day < 365; day++) {
6052 tt = *localtime (&t);
6054 /* Daylight saving starts or ends here. */
6055 if (gmt_offset (&tt, t) != gmtoff) {
6059 /* Try to find the exact hour when daylight saving starts/ends. */
6063 tt1 = *localtime (&t1);
6064 } while (gmt_offset (&tt1, t1) != gmtoff);
6066 /* Try to find the exact minute when daylight saving starts/ends. */
6069 tt1 = *localtime (&t1);
6070 } while (gmt_offset (&tt1, t1) == gmtoff);
6072 strftime (tzone, sizeof (tzone), "%Z", &tt);
6074 /* Write data, if we're already in daylight saving, we're done. */
6076 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6077 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6083 memset (&end, 0, sizeof (end));
6084 end.tm_year = year-1900 + 1;
6089 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6090 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6091 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6092 mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
6096 /* This is only set once when we enter daylight saving. */
6097 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6098 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6100 gmtoff = gmt_offset (&tt, t);
6105 strftime (tzone, sizeof (tzone), "%Z", &tt);
6106 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6107 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6108 mono_array_set ((*data), gint64, 0, 0);
6109 mono_array_set ((*data), gint64, 1, 0);
6110 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6111 mono_array_set ((*data), gint64, 3, 0);
6116 MonoDomain *domain = mono_domain_get ();
6117 TIME_ZONE_INFORMATION tz_info;
6122 tz_id = GetTimeZoneInformation (&tz_info);
6123 if (tz_id == TIME_ZONE_ID_INVALID)
6126 MONO_CHECK_ARG_NULL (data);
6127 MONO_CHECK_ARG_NULL (names);
6129 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6130 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6132 for (i = 0; i < 32; ++i)
6133 if (!tz_info.DaylightName [i])
6135 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6136 for (i = 0; i < 32; ++i)
6137 if (!tz_info.StandardName [i])
6139 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6141 if ((year <= 1601) || (year > 30827)) {
6143 * According to MSDN, the MS time functions can't handle dates outside
6149 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6150 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6151 tz_info.StandardDate.wYear = year;
6152 convert_to_absolute_date(&tz_info.StandardDate);
6153 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6158 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6159 tz_info.DaylightDate.wYear = year;
6160 convert_to_absolute_date(&tz_info.DaylightDate);
6161 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6166 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6168 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6169 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6175 ICALL_EXPORT gpointer
6176 ves_icall_System_Object_obj_address (MonoObject *this)
6178 MONO_ARCH_SAVE_REGS;
6185 static inline gint32
6186 mono_array_get_byte_length (MonoArray *array)
6192 klass = array->obj.vtable->klass;
6194 if (array->bounds == NULL)
6195 length = array->max_length;
6198 for (i = 0; i < klass->rank; ++ i)
6199 length *= array->bounds [i].length;
6202 switch (klass->element_class->byval_arg.type) {
6205 case MONO_TYPE_BOOLEAN:
6209 case MONO_TYPE_CHAR:
6217 return length * sizeof (gpointer);
6228 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6230 MONO_ARCH_SAVE_REGS;
6232 return mono_array_get_byte_length (array);
6236 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6238 MONO_ARCH_SAVE_REGS;
6240 return mono_array_get (array, gint8, idx);
6244 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6246 MONO_ARCH_SAVE_REGS;
6248 mono_array_set (array, gint8, idx, value);
6251 ICALL_EXPORT MonoBoolean
6252 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6254 guint8 *src_buf, *dest_buf;
6256 MONO_ARCH_SAVE_REGS;
6258 /* This is called directly from the class libraries without going through the managed wrapper */
6259 MONO_CHECK_ARG_NULL (src);
6260 MONO_CHECK_ARG_NULL (dest);
6262 /* watch out for integer overflow */
6263 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6266 src_buf = (guint8 *)src->vector + src_offset;
6267 dest_buf = (guint8 *)dest->vector + dest_offset;
6270 memcpy (dest_buf, src_buf, count);
6272 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6277 ICALL_EXPORT MonoObject *
6278 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6280 MonoDomain *domain = mono_object_domain (this);
6282 MonoRealProxy *rp = ((MonoRealProxy *)this);
6283 MonoTransparentProxy *tp;
6287 MONO_ARCH_SAVE_REGS;
6289 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6290 tp = (MonoTransparentProxy*) res;
6292 MONO_OBJECT_SETREF (tp, rp, rp);
6293 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6294 klass = mono_class_from_mono_type (type);
6296 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6297 tp->remote_class = mono_remote_class (domain, class_name, klass);
6299 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6303 ICALL_EXPORT MonoReflectionType *
6304 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6306 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6309 /* System.Environment */
6312 ves_icall_System_Environment_get_UserName (void)
6314 MONO_ARCH_SAVE_REGS;
6316 /* using glib is more portable */
6317 return mono_string_new (mono_domain_get (), g_get_user_name ());
6321 ICALL_EXPORT MonoString *
6322 ves_icall_System_Environment_get_MachineName (void)
6324 #if defined (HOST_WIN32)
6329 len = MAX_COMPUTERNAME_LENGTH + 1;
6330 buf = g_new (gunichar2, len);
6333 if (GetComputerName (buf, (PDWORD) &len))
6334 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6338 #elif !defined(DISABLE_SOCKETS)
6342 if (gethostname (buf, sizeof (buf)) == 0)
6343 result = mono_string_new (mono_domain_get (), buf);
6349 return mono_string_new (mono_domain_get (), "mono");
6354 ves_icall_System_Environment_get_Platform (void)
6356 #if defined (TARGET_WIN32)
6359 #elif defined(__MACH__)
6362 // Notice that the value is hidden from user code, and only exposed
6363 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6364 // define and making assumptions based on Unix/128/4 values before there
6365 // was a MacOS define. Lots of code would assume that not-Unix meant
6366 // Windows, but in this case, it would be OSX.
6375 ICALL_EXPORT MonoString *
6376 ves_icall_System_Environment_get_NewLine (void)
6378 MONO_ARCH_SAVE_REGS;
6380 #if defined (HOST_WIN32)
6381 return mono_string_new (mono_domain_get (), "\r\n");
6383 return mono_string_new (mono_domain_get (), "\n");
6387 ICALL_EXPORT MonoString *
6388 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6393 MONO_ARCH_SAVE_REGS;
6398 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6399 value = g_getenv (utf8_name);
6406 return mono_string_new (mono_domain_get (), value);
6410 * There is no standard way to get at environ.
6413 #ifndef __MINGW32_VERSION
6414 #if defined(__APPLE__) && !defined (__arm__)
6415 /* Apple defines this in crt_externs.h but doesn't provide that header for
6416 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6417 * in fact exist on all implementations (so far)
6419 gchar ***_NSGetEnviron(void);
6420 #define environ (*_NSGetEnviron())
6428 ICALL_EXPORT MonoArray *
6429 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6440 env_strings = GetEnvironmentStrings();
6443 env_string = env_strings;
6444 while (*env_string != '\0') {
6445 /* weird case that MS seems to skip */
6446 if (*env_string != '=')
6448 while (*env_string != '\0')
6454 domain = mono_domain_get ();
6455 names = mono_array_new (domain, mono_defaults.string_class, n);
6459 env_string = env_strings;
6460 while (*env_string != '\0') {
6461 /* weird case that MS seems to skip */
6462 if (*env_string != '=') {
6463 equal_str = wcschr(env_string, '=');
6464 g_assert(equal_str);
6465 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6466 mono_array_setref (names, n, str);
6469 while (*env_string != '\0')
6474 FreeEnvironmentStrings (env_strings);
6486 MONO_ARCH_SAVE_REGS;
6489 for (e = environ; *e != 0; ++ e)
6492 domain = mono_domain_get ();
6493 names = mono_array_new (domain, mono_defaults.string_class, n);
6496 for (e = environ; *e != 0; ++ e) {
6497 parts = g_strsplit (*e, "=", 2);
6499 str = mono_string_new (domain, *parts);
6500 mono_array_setref (names, n, str);
6513 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6515 #if !GLIB_CHECK_VERSION(2,4,0)
6516 #define g_setenv(a,b,c) setenv(a,b,c)
6517 #define g_unsetenv(a) unsetenv(a)
6521 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6526 gunichar2 *utf16_name, *utf16_value;
6528 gchar *utf8_name, *utf8_value;
6531 MONO_ARCH_SAVE_REGS;
6534 utf16_name = mono_string_to_utf16 (name);
6535 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6536 SetEnvironmentVariable (utf16_name, NULL);
6537 g_free (utf16_name);
6541 utf16_value = mono_string_to_utf16 (value);
6543 SetEnvironmentVariable (utf16_name, utf16_value);
6545 g_free (utf16_name);
6546 g_free (utf16_value);
6548 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6550 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6551 g_unsetenv (utf8_name);
6556 utf8_value = mono_string_to_utf8_checked (value, &error);
6557 if (!mono_error_ok (&error)) {
6559 mono_error_raise_exception (&error);
6561 g_setenv (utf8_name, utf8_value, TRUE);
6564 g_free (utf8_value);
6569 ves_icall_System_Environment_Exit (int result)
6571 MONO_ARCH_SAVE_REGS;
6573 mono_threads_set_shutting_down ();
6575 mono_runtime_set_shutting_down ();
6577 /* This will kill the tp threads which cannot be suspended */
6578 mono_thread_pool_cleanup ();
6580 /* Suspend all managed threads since the runtime is going away */
6581 mono_thread_suspend_all_other_threads ();
6583 mono_runtime_quit ();
6585 /* we may need to do some cleanup here... */
6589 ICALL_EXPORT MonoString*
6590 ves_icall_System_Environment_GetGacPath (void)
6592 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6595 ICALL_EXPORT MonoString*
6596 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6598 #if defined (HOST_WIN32)
6599 #ifndef CSIDL_FLAG_CREATE
6600 #define CSIDL_FLAG_CREATE 0x8000
6603 WCHAR path [MAX_PATH];
6604 /* Create directory if no existing */
6605 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6609 return mono_string_new_utf16 (mono_domain_get (), path, len);
6612 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6614 return mono_string_new (mono_domain_get (), "");
6617 ICALL_EXPORT MonoArray *
6618 ves_icall_System_Environment_GetLogicalDrives (void)
6620 gunichar2 buf [256], *ptr, *dname;
6622 guint initial_size = 127, size = 128;
6625 MonoString *drivestr;
6626 MonoDomain *domain = mono_domain_get ();
6629 MONO_ARCH_SAVE_REGS;
6634 while (size > initial_size) {
6635 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6636 if (size > initial_size) {
6639 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6640 initial_size = size;
6654 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6659 while (*u16) { u16++; len ++; }
6660 drivestr = mono_string_new_utf16 (domain, dname, len);
6661 mono_array_setref (result, ndrives++, drivestr);
6671 ICALL_EXPORT MonoString *
6672 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6674 gunichar2 volume_name [MAX_PATH + 1];
6676 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6678 return mono_string_from_utf16 (volume_name);
6681 ICALL_EXPORT MonoString *
6682 ves_icall_System_Environment_InternalGetHome (void)
6684 MONO_ARCH_SAVE_REGS;
6686 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6689 static const char *encodings [] = {
6691 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6692 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6693 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6695 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6696 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6697 "x_unicode_2_0_utf_7",
6699 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6700 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6702 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6705 "unicodefffe", "utf_16be",
6712 * Returns the internal codepage, if the value of "int_code_page" is
6713 * 1 at entry, and we can not compute a suitable code page number,
6714 * returns the code page as a string
6716 ICALL_EXPORT MonoString*
6717 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6722 char *codepage = NULL;
6724 int want_name = *int_code_page;
6727 *int_code_page = -1;
6728 MONO_ARCH_SAVE_REGS;
6730 g_get_charset (&cset);
6731 c = codepage = strdup (cset);
6732 for (c = codepage; *c; c++){
6733 if (isascii (*c) && isalpha (*c))
6738 /* g_print ("charset: %s\n", cset); */
6740 /* handle some common aliases */
6743 for (i = 0; p != 0; ){
6744 if ((gssize) p < 7){
6746 p = encodings [++i];
6749 if (strcmp (p, codepage) == 0){
6750 *int_code_page = code;
6753 p = encodings [++i];
6756 if (strstr (codepage, "utf_8") != NULL)
6757 *int_code_page |= 0x10000000;
6760 if (want_name && *int_code_page == -1)
6761 return mono_string_new (mono_domain_get (), cset);
6766 ICALL_EXPORT MonoBoolean
6767 ves_icall_System_Environment_get_HasShutdownStarted (void)
6769 if (mono_runtime_is_shutting_down ())
6772 if (mono_domain_is_unloading (mono_domain_get ()))
6779 ves_icall_System_Environment_BroadcastSettingChange (void)
6782 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6787 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6788 MonoReflectionMethod *method,
6789 MonoArray *out_args)
6791 MONO_ARCH_SAVE_REGS;
6793 mono_message_init (mono_object_domain (this), this, method, out_args);
6796 ICALL_EXPORT MonoBoolean
6797 ves_icall_IsTransparentProxy (MonoObject *proxy)
6799 MONO_ARCH_SAVE_REGS;
6804 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6810 ICALL_EXPORT MonoReflectionMethod *
6811 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6812 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6816 MonoMethod **vtable;
6817 MonoMethod *res = NULL;
6819 MONO_CHECK_ARG_NULL (rtype);
6820 MONO_CHECK_ARG_NULL (rmethod);
6822 method = rmethod->method;
6823 klass = mono_class_from_mono_type (rtype->type);
6824 mono_class_init_or_throw (klass);
6826 if (MONO_CLASS_IS_INTERFACE (klass))
6829 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6832 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6833 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6839 mono_class_setup_vtable (klass);
6840 vtable = klass->vtable;
6842 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6843 gboolean variance_used = FALSE;
6844 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6845 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6847 res = vtable [offs + method->slot];
6849 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6852 if (method->slot != -1)
6853 res = vtable [method->slot];
6859 return mono_method_get_object (mono_domain_get (), res, NULL);
6863 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6868 MONO_ARCH_SAVE_REGS;
6870 klass = mono_class_from_mono_type (type->type);
6871 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6873 if (enable) vtable->remote = 1;
6874 else vtable->remote = 0;
6877 ICALL_EXPORT MonoObject *
6878 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6883 MONO_ARCH_SAVE_REGS;
6885 domain = mono_object_domain (type);
6886 klass = mono_class_from_mono_type (type->type);
6887 mono_class_init_or_throw (klass);
6889 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6890 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6892 if (klass->rank >= 1) {
6893 g_assert (klass->rank == 1);
6894 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6896 /* Bypass remoting object creation check */
6897 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6901 ICALL_EXPORT MonoString *
6902 ves_icall_System_IO_get_temp_path (void)
6904 MONO_ARCH_SAVE_REGS;
6906 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6909 #ifndef PLATFORM_NO_DRIVEINFO
6910 ICALL_EXPORT MonoBoolean
6911 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6912 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6916 ULARGE_INTEGER wapi_free_bytes_avail;
6917 ULARGE_INTEGER wapi_total_number_of_bytes;
6918 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6920 MONO_ARCH_SAVE_REGS;
6922 *error = ERROR_SUCCESS;
6923 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6924 &wapi_total_number_of_free_bytes);
6927 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6928 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6929 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6931 *free_bytes_avail = 0;
6932 *total_number_of_bytes = 0;
6933 *total_number_of_free_bytes = 0;
6934 *error = GetLastError ();
6940 ICALL_EXPORT guint32
6941 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6943 MONO_ARCH_SAVE_REGS;
6945 return GetDriveType (mono_string_chars (root_path_name));
6949 ICALL_EXPORT gpointer
6950 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6952 MONO_ARCH_SAVE_REGS;
6954 return mono_compile_method (method);
6957 ICALL_EXPORT MonoString *
6958 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6963 MONO_ARCH_SAVE_REGS;
6965 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6967 #if defined (HOST_WIN32)
6968 /* Avoid mixing '/' and '\\' */
6971 for (i = strlen (path) - 1; i >= 0; i--)
6972 if (path [i] == '/')
6976 mcpath = mono_string_new (mono_domain_get (), path);
6983 get_bundled_app_config (void)
6985 const gchar *app_config;
6988 gchar *config_file_name, *config_file_path;
6992 MONO_ARCH_SAVE_REGS;
6994 domain = mono_domain_get ();
6995 file = domain->setup->configuration_file;
6999 // Retrieve config file and remove the extension
7000 config_file_name = mono_string_to_utf8 (file);
7001 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7002 if (!config_file_path)
7003 config_file_path = config_file_name;
7004 len = strlen (config_file_path) - strlen (".config");
7005 module = g_malloc0 (len + 1);
7006 memcpy (module, config_file_path, len);
7007 // Get the config file from the module name
7008 app_config = mono_config_string_for_assembly_file (module);
7011 if (config_file_name != config_file_path)
7012 g_free (config_file_name);
7013 g_free (config_file_path);
7018 return mono_string_new (mono_domain_get (), app_config);
7022 get_bundled_machine_config (void)
7024 const gchar *machine_config;
7026 MONO_ARCH_SAVE_REGS;
7028 machine_config = mono_get_machine_config ();
7030 if (!machine_config)
7033 return mono_string_new (mono_domain_get (), machine_config);
7036 ICALL_EXPORT MonoString *
7037 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7042 MONO_ARCH_SAVE_REGS;
7044 path = g_path_get_dirname (mono_get_config_dir ());
7046 #if defined (HOST_WIN32)
7047 /* Avoid mixing '/' and '\\' */
7050 for (i = strlen (path) - 1; i >= 0; i--)
7051 if (path [i] == '/')
7055 ipath = mono_string_new (mono_domain_get (), path);
7061 ICALL_EXPORT gboolean
7062 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7064 MonoPEResourceDataEntry *entry;
7067 MONO_ARCH_SAVE_REGS;
7069 if (!assembly || !result || !size)
7074 image = assembly->assembly->image;
7075 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7079 *result = mono_image_rva_map (image, entry->rde_data_offset);
7084 *size = entry->rde_size;
7089 ICALL_EXPORT MonoBoolean
7090 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7092 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7095 ICALL_EXPORT MonoBoolean
7096 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7098 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7099 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7105 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7107 if (mono_get_runtime_callbacks ()->debug_log)
7108 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7112 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7114 #if defined (HOST_WIN32)
7115 OutputDebugString (mono_string_chars (message));
7117 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7121 /* Only used for value types */
7122 ICALL_EXPORT MonoObject *
7123 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7128 MONO_ARCH_SAVE_REGS;
7130 domain = mono_object_domain (type);
7131 klass = mono_class_from_mono_type (type->type);
7132 mono_class_init_or_throw (klass);
7134 if (mono_class_is_nullable (klass))
7135 /* No arguments -> null */
7138 return mono_object_new (domain, klass);
7141 ICALL_EXPORT MonoReflectionMethod *
7142 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7144 MonoClass *klass, *parent;
7145 MonoMethod *method = m->method;
7146 MonoMethod *result = NULL;
7149 MONO_ARCH_SAVE_REGS;
7151 if (method->klass == NULL)
7154 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7155 MONO_CLASS_IS_INTERFACE (method->klass) ||
7156 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7159 slot = mono_method_get_vtable_slot (method);
7163 klass = method->klass;
7164 if (klass->generic_class)
7165 klass = klass->generic_class->container_class;
7168 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7169 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7170 mono_class_setup_vtable (parent);
7171 if (parent->vtable_size <= slot)
7176 klass = klass->parent;
7181 if (klass == method->klass)
7184 /*This is possible if definition == FALSE.
7185 * Do it here to be really sure we don't read invalid memory.
7187 if (slot >= klass->vtable_size)
7190 mono_class_setup_vtable (klass);
7192 result = klass->vtable [slot];
7193 if (result == NULL) {
7194 /* It is an abstract method */
7195 gpointer iter = NULL;
7196 while ((result = mono_class_get_methods (klass, &iter)))
7197 if (result->slot == slot)
7204 return mono_method_get_object (mono_domain_get (), result, NULL);
7207 ICALL_EXPORT MonoString*
7208 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7210 MonoMethod *method = m->method;
7212 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7217 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7219 MONO_ARCH_SAVE_REGS;
7221 iter->sig = *(MonoMethodSignature**)argsp;
7223 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7224 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7227 /* FIXME: it's not documented what start is exactly... */
7231 iter->args = argsp + sizeof (gpointer);
7233 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7235 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7238 ICALL_EXPORT MonoTypedRef
7239 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7241 guint32 i, arg_size;
7244 MONO_ARCH_SAVE_REGS;
7246 i = iter->sig->sentinelpos + iter->next_arg;
7248 g_assert (i < iter->sig->param_count);
7250 res.type = iter->sig->params [i];
7251 res.klass = mono_class_from_mono_type (res.type);
7252 arg_size = mono_type_stack_size (res.type, &align);
7253 #if defined(__arm__) || defined(__mips__)
7254 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7256 res.value = iter->args;
7257 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7258 if (arg_size <= sizeof (gpointer)) {
7260 int padding = arg_size - mono_type_size (res.type, &dummy);
7261 res.value = (guint8*)res.value + padding;
7264 iter->args = (char*)iter->args + arg_size;
7267 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7272 ICALL_EXPORT MonoTypedRef
7273 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7275 guint32 i, arg_size;
7278 MONO_ARCH_SAVE_REGS;
7280 i = iter->sig->sentinelpos + iter->next_arg;
7282 g_assert (i < iter->sig->param_count);
7284 while (i < iter->sig->param_count) {
7285 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7287 res.type = iter->sig->params [i];
7288 res.klass = mono_class_from_mono_type (res.type);
7289 /* FIXME: endianess issue... */
7290 arg_size = mono_type_stack_size (res.type, &align);
7291 #if defined(__arm__) || defined(__mips__)
7292 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7294 res.value = iter->args;
7295 iter->args = (char*)iter->args + arg_size;
7297 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7300 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7308 ICALL_EXPORT MonoType*
7309 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7312 MONO_ARCH_SAVE_REGS;
7314 i = iter->sig->sentinelpos + iter->next_arg;
7316 g_assert (i < iter->sig->param_count);
7318 return iter->sig->params [i];
7321 ICALL_EXPORT MonoObject*
7322 mono_TypedReference_ToObject (MonoTypedRef tref)
7324 MONO_ARCH_SAVE_REGS;
7326 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7327 MonoObject** objp = tref.value;
7331 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7334 ICALL_EXPORT MonoObject*
7335 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7337 MONO_ARCH_SAVE_REGS;
7339 if (MONO_TYPE_IS_REFERENCE (type)) {
7340 MonoObject** objp = value;
7344 return mono_value_box (mono_domain_get (), klass, value);
7348 prelink_method (MonoMethod *method)
7350 const char *exc_class, *exc_arg;
7351 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7353 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7355 mono_raise_exception(
7356 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7358 /* create the wrapper, too? */
7362 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7364 MONO_ARCH_SAVE_REGS;
7365 prelink_method (method->method);
7369 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7371 MonoClass *klass = mono_class_from_mono_type (type->type);
7373 gpointer iter = NULL;
7374 MONO_ARCH_SAVE_REGS;
7376 mono_class_init_or_throw (klass);
7378 while ((m = mono_class_get_methods (klass, &iter)))
7382 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7384 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7385 gint32 const **exponents,
7386 gunichar2 const **digitLowerTable,
7387 gunichar2 const **digitUpperTable,
7388 gint64 const **tenPowersList,
7389 gint32 const **decHexDigits)
7391 *mantissas = Formatter_MantissaBitsTable;
7392 *exponents = Formatter_TensExponentTable;
7393 *digitLowerTable = Formatter_DigitLowerTable;
7394 *digitUpperTable = Formatter_DigitUpperTable;
7395 *tenPowersList = Formatter_TenPowersList;
7396 *decHexDigits = Formatter_DecHexDigits;
7400 get_category_data (int version,
7401 guint8 const **category_data,
7402 guint16 const **category_astral_index)
7404 *category_astral_index = NULL;
7406 #ifndef DISABLE_NET_4_0
7408 *category_data = CategoryData_v4;
7409 #ifndef DISABLE_ASTRAL
7410 *category_astral_index = CategoryData_v4_astral_index;
7416 *category_data = CategoryData_v2;
7417 #ifndef DISABLE_ASTRAL
7418 *category_astral_index = CategoryData_v2_astral_index;
7422 /* These parameters are "readonly" in corlib/System/Char.cs */
7424 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7425 guint8 const **category_data,
7426 guint16 const **category_astral_index,
7427 guint8 const **numeric_data,
7428 gdouble const **numeric_data_values,
7429 guint16 const **to_lower_data_low,
7430 guint16 const **to_lower_data_high,
7431 guint16 const **to_upper_data_low,
7432 guint16 const **to_upper_data_high)
7434 get_category_data (category_data_version, category_data, category_astral_index);
7435 *numeric_data = NumericData;
7436 *numeric_data_values = NumericDataValues;
7437 *to_lower_data_low = ToLowerDataLow;
7438 *to_lower_data_high = ToLowerDataHigh;
7439 *to_upper_data_low = ToUpperDataLow;
7440 *to_upper_data_high = ToUpperDataHigh;
7444 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7446 return method->method->token;
7450 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7451 * and avoid useless allocations.
7454 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7458 for (i = 0; i < type->num_mods; ++i) {
7459 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7464 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7466 for (i = 0; i < type->num_mods; ++i) {
7467 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7468 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7469 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7476 ICALL_EXPORT MonoArray*
7477 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7479 MonoType *type = param->ClassImpl->type;
7480 MonoClass *member_class = mono_object_class (param->MemberImpl);
7481 MonoMethod *method = NULL;
7484 MonoMethodSignature *sig;
7486 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7487 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7488 method = rmethod->method;
7489 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7490 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7491 if (!(method = prop->property->get))
7492 method = prop->property->set;
7495 char *type_name = mono_type_get_full_name (member_class);
7496 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7497 MonoException *ex = mono_get_exception_not_supported (msg);
7500 mono_raise_exception (ex);
7503 image = method->klass->image;
7504 pos = param->PositionImpl;
7505 sig = mono_method_signature (method);
7509 type = sig->params [pos];
7511 return type_array_from_modifiers (image, type, optional);
7515 get_property_type (MonoProperty *prop)
7517 MonoMethodSignature *sig;
7519 sig = mono_method_signature (prop->get);
7521 } else if (prop->set) {
7522 sig = mono_method_signature (prop->set);
7523 return sig->params [sig->param_count - 1];
7528 ICALL_EXPORT MonoArray*
7529 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7531 MonoType *type = get_property_type (property->property);
7532 MonoImage *image = property->klass->image;
7536 return type_array_from_modifiers (image, type, optional);
7540 *Construct a MonoType suited to be used to decode a constant blob object.
7542 * @type is the target type which will be constructed
7543 * @blob_type is the blob type, for example, that comes from the constant table
7544 * @real_type is the expected constructed type.
7547 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7549 type->type = blob_type;
7550 type->data.klass = NULL;
7551 if (blob_type == MONO_TYPE_CLASS)
7552 type->data.klass = mono_defaults.object_class;
7553 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7554 /* For enums, we need to use the base type */
7555 type->type = MONO_TYPE_VALUETYPE;
7556 type->data.klass = mono_class_from_mono_type (real_type);
7558 type->data.klass = mono_class_from_mono_type (real_type);
7561 ICALL_EXPORT MonoObject*
7562 property_info_get_default_value (MonoReflectionProperty *property)
7565 MonoProperty *prop = property->property;
7566 MonoType *type = get_property_type (prop);
7567 MonoDomain *domain = mono_object_domain (property);
7568 MonoTypeEnum def_type;
7569 const char *def_value;
7572 mono_class_init (prop->parent);
7574 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7575 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7577 def_value = mono_class_get_property_default_value (prop, &def_type);
7579 mono_type_from_blob_type (&blob_type, def_type, type);
7580 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7585 ICALL_EXPORT MonoBoolean
7586 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7588 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7589 MonoCustomAttrInfo *cinfo;
7592 mono_class_init_or_throw (attr_class);
7594 cinfo = mono_reflection_get_custom_attrs_info (obj);
7597 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7599 mono_custom_attrs_free (cinfo);
7603 ICALL_EXPORT MonoArray*
7604 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7606 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7611 mono_class_init_or_throw (attr_class);
7613 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7614 if (!mono_error_ok (&error))
7615 mono_error_raise_exception (&error);
7616 if (mono_loader_get_last_error ()) {
7617 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7618 g_assert_not_reached ();
7626 ICALL_EXPORT MonoString*
7627 ves_icall_Mono_Runtime_GetDisplayName (void)
7630 MonoString *display_name;
7632 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7633 display_name = mono_string_new (mono_domain_get (), info);
7635 return display_name;
7638 ICALL_EXPORT MonoString*
7639 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7641 MonoString *message;
7645 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7646 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7649 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7651 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7659 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7660 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7661 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7662 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7663 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7664 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7665 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7666 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7670 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7675 gunichar2 last, prev_last, prev2_last;
7682 int havePadding = 0;
7684 last = prev_last = 0, prev2_last = 0;
7685 for (i = 0; i < ilength; i++) {
7687 if (c >= sizeof (dbase64)) {
7688 exc = mono_exception_from_name_msg (mono_get_corlib (),
7689 "System", "FormatException",
7690 "Invalid character found.");
7691 mono_raise_exception (exc);
7692 } else if (isspace (c)) {
7694 } else if (havePadding && c != '=') {
7695 exc = mono_exception_from_name_msg (mono_get_corlib (),
7696 "System", "FormatException",
7697 "Invalid character found.");
7698 mono_raise_exception (exc);
7700 if (c == '=') havePadding = 1;
7701 prev2_last = prev_last;
7707 olength = ilength - ignored;
7709 if (allowWhitespaceOnly && olength == 0) {
7710 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7713 if ((olength & 3) != 0 || olength <= 0) {
7714 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7715 "FormatException", "Invalid length.");
7716 mono_raise_exception (exc);
7719 if (prev2_last == '=') {
7720 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7721 mono_raise_exception (exc);
7724 olength = (olength * 3) / 4;
7728 if (prev_last == '=')
7731 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7732 res_ptr = mono_array_addr (result, guchar, 0);
7733 for (i = 0; i < ilength; ) {
7736 for (k = 0; k < 4 && i < ilength;) {
7742 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7743 exc = mono_exception_from_name_msg (mono_get_corlib (),
7744 "System", "FormatException",
7745 "Invalid character found.");
7746 mono_raise_exception (exc);
7751 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7753 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7755 *res_ptr++ = (b [2] << 6) | b [3];
7757 while (i < ilength && isspace (start [i]))
7764 ICALL_EXPORT MonoArray *
7765 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7767 MONO_ARCH_SAVE_REGS;
7769 return base64_to_byte_array (mono_string_chars (str),
7770 mono_string_length (str), allowWhitespaceOnly);
7773 ICALL_EXPORT MonoArray *
7774 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7776 MONO_ARCH_SAVE_REGS;
7778 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7782 #ifndef DISABLE_ICALL_TABLES
7784 #define ICALL_TYPE(id,name,first)
7785 #define ICALL(id,name,func) Icall_ ## id,
7788 #include "metadata/icall-def.h"
7794 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7795 #define ICALL(id,name,func)
7797 #include "metadata/icall-def.h"
7803 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7804 #define ICALL(id,name,func)
7806 guint16 first_icall;
7809 static const IcallTypeDesc
7810 icall_type_descs [] = {
7811 #include "metadata/icall-def.h"
7815 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7818 #define ICALL_TYPE(id,name,first)
7821 #ifdef HAVE_ARRAY_ELEM_INIT
7822 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7823 #define MSGSTRFIELD1(line) str##line
7825 static const struct msgstrtn_t {
7826 #define ICALL(id,name,func)
7828 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7829 #include "metadata/icall-def.h"
7831 } icall_type_names_str = {
7832 #define ICALL_TYPE(id,name,first) (name),
7833 #include "metadata/icall-def.h"
7836 static const guint16 icall_type_names_idx [] = {
7837 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7838 #include "metadata/icall-def.h"
7841 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7843 static const struct msgstr_t {
7845 #define ICALL_TYPE(id,name,first)
7846 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7847 #include "metadata/icall-def.h"
7849 } icall_names_str = {
7850 #define ICALL(id,name,func) (name),
7851 #include "metadata/icall-def.h"
7854 static const guint16 icall_names_idx [] = {
7855 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7856 #include "metadata/icall-def.h"
7859 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7865 #define ICALL_TYPE(id,name,first) name,
7866 #define ICALL(id,name,func)
7867 static const char* const
7868 icall_type_names [] = {
7869 #include "metadata/icall-def.h"
7873 #define icall_type_name_get(id) (icall_type_names [(id)])
7877 #define ICALL_TYPE(id,name,first)
7878 #define ICALL(id,name,func) name,
7879 static const char* const
7881 #include "metadata/icall-def.h"
7884 #define icall_name_get(id) icall_names [(id)]
7886 #endif /* !HAVE_ARRAY_ELEM_INIT */
7890 #define ICALL_TYPE(id,name,first)
7891 #define ICALL(id,name,func) func,
7892 static const gconstpointer
7893 icall_functions [] = {
7894 #include "metadata/icall-def.h"
7898 #ifdef ENABLE_ICALL_SYMBOL_MAP
7901 #define ICALL_TYPE(id,name,first)
7902 #define ICALL(id,name,func) #func,
7903 static const gconstpointer
7904 icall_symbols [] = {
7905 #include "metadata/icall-def.h"
7910 #endif /* DISABLE_ICALL_TABLES */
7912 static GHashTable *icall_hash = NULL;
7913 static GHashTable *jit_icall_hash_name = NULL;
7914 static GHashTable *jit_icall_hash_addr = NULL;
7917 mono_icall_init (void)
7919 #ifndef DISABLE_ICALL_TABLES
7922 /* check that tables are sorted: disable in release */
7925 const char *prev_class = NULL;
7926 const char *prev_method;
7928 for (i = 0; i < Icall_type_num; ++i) {
7929 const IcallTypeDesc *desc;
7932 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7933 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7934 prev_class = icall_type_name_get (i);
7935 desc = &icall_type_descs [i];
7936 num_icalls = icall_desc_num_icalls (desc);
7937 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7938 for (j = 0; j < num_icalls; ++j) {
7939 const char *methodn = icall_name_get (desc->first_icall + j);
7940 if (prev_method && strcmp (prev_method, methodn) >= 0)
7941 g_print ("method %s should come before method %s\n", methodn, prev_method);
7942 prev_method = methodn;
7948 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7952 mono_icall_cleanup (void)
7954 g_hash_table_destroy (icall_hash);
7955 g_hash_table_destroy (jit_icall_hash_name);
7956 g_hash_table_destroy (jit_icall_hash_addr);
7960 mono_add_internal_call (const char *name, gconstpointer method)
7962 mono_loader_lock ();
7964 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7966 mono_loader_unlock ();
7969 #ifndef DISABLE_ICALL_TABLES
7971 #ifdef HAVE_ARRAY_ELEM_INIT
7973 compare_method_imap (const void *key, const void *elem)
7975 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7976 return strcmp (key, method_name);
7980 find_method_icall (const IcallTypeDesc *imap, const char *name)
7982 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7985 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7989 compare_class_imap (const void *key, const void *elem)
7991 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7992 return strcmp (key, class_name);
7995 static const IcallTypeDesc*
7996 find_class_icalls (const char *name)
7998 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8001 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8004 #else /* HAVE_ARRAY_ELEM_INIT */
8007 compare_method_imap (const void *key, const void *elem)
8009 const char** method_name = (const char**)elem;
8010 return strcmp (key, *method_name);
8014 find_method_icall (const IcallTypeDesc *imap, const char *name)
8016 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8019 return (gpointer)icall_functions [(nameslot - icall_names)];
8023 compare_class_imap (const void *key, const void *elem)
8025 const char** class_name = (const char**)elem;
8026 return strcmp (key, *class_name);
8029 static const IcallTypeDesc*
8030 find_class_icalls (const char *name)
8032 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8035 return &icall_type_descs [nameslot - icall_type_names];
8038 #endif /* HAVE_ARRAY_ELEM_INIT */
8040 #endif /* DISABLE_ICALL_TABLES */
8043 * we should probably export this as an helper (handle nested types).
8044 * Returns the number of chars written in buf.
8047 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8049 int nspacelen, cnamelen;
8050 nspacelen = strlen (klass->name_space);
8051 cnamelen = strlen (klass->name);
8052 if (nspacelen + cnamelen + 2 > bufsize)
8055 memcpy (buf, klass->name_space, nspacelen);
8056 buf [nspacelen ++] = '.';
8058 memcpy (buf + nspacelen, klass->name, cnamelen);
8059 buf [nspacelen + cnamelen] = 0;
8060 return nspacelen + cnamelen;
8063 #ifdef DISABLE_ICALL_TABLES
8065 no_icall_table (void)
8067 g_assert_not_reached ();
8072 mono_lookup_internal_call (MonoMethod *method)
8077 int typelen = 0, mlen, siglen;
8079 #ifndef DISABLE_ICALL_TABLES
8080 const IcallTypeDesc *imap = NULL;
8083 g_assert (method != NULL);
8085 if (method->is_inflated)
8086 method = ((MonoMethodInflated *) method)->declaring;
8088 if (method->klass->nested_in) {
8089 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8093 mname [pos++] = '/';
8096 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8102 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8107 #ifndef DISABLE_ICALL_TABLES
8108 imap = find_class_icalls (mname);
8111 mname [typelen] = ':';
8112 mname [typelen + 1] = ':';
8114 mlen = strlen (method->name);
8115 memcpy (mname + typelen + 2, method->name, mlen);
8116 sigstart = mname + typelen + 2 + mlen;
8119 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8120 siglen = strlen (tmpsig);
8121 if (typelen + mlen + siglen + 6 > sizeof (mname))
8124 memcpy (sigstart + 1, tmpsig, siglen);
8125 sigstart [siglen + 1] = ')';
8126 sigstart [siglen + 2] = 0;
8129 mono_loader_lock ();
8131 res = g_hash_table_lookup (icall_hash, mname);
8133 mono_loader_unlock ();
8136 /* try without signature */
8138 res = g_hash_table_lookup (icall_hash, mname);
8140 mono_loader_unlock ();
8144 #ifdef DISABLE_ICALL_TABLES
8145 mono_loader_unlock ();
8146 /* Fail only when the result is actually used */
8147 /* mono_marshal_get_native_wrapper () depends on this */
8148 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8149 return ves_icall_System_String_ctor_RedirectToCreateString;
8151 return no_icall_table;
8153 /* it wasn't found in the static call tables */
8155 mono_loader_unlock ();
8158 res = find_method_icall (imap, sigstart - mlen);
8160 mono_loader_unlock ();
8163 /* try _with_ signature */
8165 res = find_method_icall (imap, sigstart - mlen);
8167 mono_loader_unlock ();
8171 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8172 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8173 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8174 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8175 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");
8176 g_print ("If you see other errors or faults after this message they are probably related\n");
8177 g_print ("and you need to fix your mono install first.\n");
8179 mono_loader_unlock ();
8185 #ifdef ENABLE_ICALL_SYMBOL_MAP
8187 func_cmp (gconstpointer key, gconstpointer p)
8189 return (gsize)key - (gsize)*(gsize*)p;
8194 * mono_lookup_icall_symbol:
8196 * Given the icall METHOD, returns its C symbol.
8199 mono_lookup_icall_symbol (MonoMethod *m)
8201 #ifdef DISABLE_ICALL_TABLES
8202 g_assert_not_reached ();
8205 #ifdef ENABLE_ICALL_SYMBOL_MAP
8209 static gconstpointer *functions_sorted;
8210 static const char**symbols_sorted;
8211 static gboolean inited;
8216 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8217 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8218 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8219 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8220 /* Bubble sort the two arrays */
8224 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8225 if (functions_sorted [i] > functions_sorted [i + 1]) {
8228 tmp = functions_sorted [i];
8229 functions_sorted [i] = functions_sorted [i + 1];
8230 functions_sorted [i + 1] = tmp;
8231 tmp = symbols_sorted [i];
8232 symbols_sorted [i] = symbols_sorted [i + 1];
8233 symbols_sorted [i + 1] = tmp;
8240 func = mono_lookup_internal_call (m);
8243 slot = bsearch (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8247 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8249 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8250 g_assert_not_reached ();
8257 type_from_typename (char *typename)
8259 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8261 if (!strcmp (typename, "int"))
8262 klass = mono_defaults.int_class;
8263 else if (!strcmp (typename, "ptr"))
8264 klass = mono_defaults.int_class;
8265 else if (!strcmp (typename, "void"))
8266 klass = mono_defaults.void_class;
8267 else if (!strcmp (typename, "int32"))
8268 klass = mono_defaults.int32_class;
8269 else if (!strcmp (typename, "uint32"))
8270 klass = mono_defaults.uint32_class;
8271 else if (!strcmp (typename, "int8"))
8272 klass = mono_defaults.sbyte_class;
8273 else if (!strcmp (typename, "uint8"))
8274 klass = mono_defaults.byte_class;
8275 else if (!strcmp (typename, "int16"))
8276 klass = mono_defaults.int16_class;
8277 else if (!strcmp (typename, "uint16"))
8278 klass = mono_defaults.uint16_class;
8279 else if (!strcmp (typename, "long"))
8280 klass = mono_defaults.int64_class;
8281 else if (!strcmp (typename, "ulong"))
8282 klass = mono_defaults.uint64_class;
8283 else if (!strcmp (typename, "float"))
8284 klass = mono_defaults.single_class;
8285 else if (!strcmp (typename, "double"))
8286 klass = mono_defaults.double_class;
8287 else if (!strcmp (typename, "object"))
8288 klass = mono_defaults.object_class;
8289 else if (!strcmp (typename, "obj"))
8290 klass = mono_defaults.object_class;
8291 else if (!strcmp (typename, "string"))
8292 klass = mono_defaults.string_class;
8293 else if (!strcmp (typename, "bool"))
8294 klass = mono_defaults.boolean_class;
8295 else if (!strcmp (typename, "boolean"))
8296 klass = mono_defaults.boolean_class;
8298 g_error ("%s", typename);
8299 g_assert_not_reached ();
8301 return &klass->byval_arg;
8304 MonoMethodSignature*
8305 mono_create_icall_signature (const char *sigstr)
8310 MonoMethodSignature *res;
8312 mono_loader_lock ();
8313 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8315 mono_loader_unlock ();
8319 parts = g_strsplit (sigstr, " ", 256);
8328 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8333 * Under windows, the default pinvoke calling convention is STDCALL but
8336 res->call_convention = MONO_CALL_C;
8339 res->ret = type_from_typename (parts [0]);
8340 for (i = 1; i < len; ++i) {
8341 res->params [i - 1] = type_from_typename (parts [i]);
8346 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8348 mono_loader_unlock ();
8354 mono_find_jit_icall_by_name (const char *name)
8356 MonoJitICallInfo *info;
8357 g_assert (jit_icall_hash_name);
8359 mono_loader_lock ();
8360 info = g_hash_table_lookup (jit_icall_hash_name, name);
8361 mono_loader_unlock ();
8366 mono_find_jit_icall_by_addr (gconstpointer addr)
8368 MonoJitICallInfo *info;
8369 g_assert (jit_icall_hash_addr);
8371 mono_loader_lock ();
8372 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8373 mono_loader_unlock ();
8379 * mono_get_jit_icall_info:
8381 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8382 * caller should access it while holding the loader lock.
8385 mono_get_jit_icall_info (void)
8387 return jit_icall_hash_name;
8391 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8393 mono_loader_lock ();
8394 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8395 mono_loader_unlock ();
8399 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8401 MonoJitICallInfo *info;
8406 mono_loader_lock ();
8408 if (!jit_icall_hash_name) {
8409 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8410 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8413 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8414 g_warning ("jit icall already defined \"%s\"\n", name);
8415 g_assert_not_reached ();
8418 info = g_new0 (MonoJitICallInfo, 1);
8425 info->wrapper = func;
8427 info->wrapper = NULL;
8430 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8431 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8433 mono_loader_unlock ();