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 #ifndef DISABLE_REMOTING
1173 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1174 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1177 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1181 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1183 MONO_ARCH_SAVE_REGS;
1185 mtype->type = &obj->vtable->klass->byval_arg;
1186 g_assert (mtype->type->type);
1190 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1192 MONO_ARCH_SAVE_REGS;
1194 MONO_CHECK_ARG_NULL (obj);
1196 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1200 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1201 MonoReflectionMethod *method,
1202 MonoArray *opt_param_types)
1204 MONO_ARCH_SAVE_REGS;
1206 MONO_CHECK_ARG_NULL (method);
1208 return mono_image_create_method_token (
1209 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1213 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1215 MONO_ARCH_SAVE_REGS;
1217 mono_image_create_pefile (mb, file);
1221 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1223 MONO_ARCH_SAVE_REGS;
1225 mono_image_build_metadata (mb);
1229 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1231 MONO_ARCH_SAVE_REGS;
1233 mono_image_register_token (mb->dynamic_image, token, obj);
1237 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1239 MonoMethod **dest = data;
1241 /* skip unmanaged frames */
1257 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1259 MonoMethod **dest = data;
1261 /* skip unmanaged frames */
1266 if (!strcmp (m->klass->name_space, "System.Reflection"))
1275 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1277 MonoMethod **dest = data;
1279 /* skip unmanaged frames */
1283 if (m->wrapper_type != MONO_WRAPPER_NONE)
1286 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1300 static MonoReflectionType *
1301 type_from_name (const char *str, MonoBoolean ignoreCase)
1303 MonoType *type = NULL;
1304 MonoAssembly *assembly = NULL;
1305 MonoTypeNameParse info;
1306 char *temp_str = g_strdup (str);
1307 gboolean type_resolve = FALSE;
1309 MONO_ARCH_SAVE_REGS;
1311 /* mono_reflection_parse_type() mangles the string */
1312 if (!mono_reflection_parse_type (temp_str, &info)) {
1313 mono_reflection_free_type_info (&info);
1318 if (info.assembly.name) {
1319 assembly = mono_assembly_load (&info.assembly, NULL, NULL);
1321 MonoMethod *m = mono_method_get_last_managed ();
1322 MonoMethod *dest = m;
1324 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1329 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1330 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1331 * to crash. This only seems to happen in some strange remoting
1332 * scenarios and I was unable to figure out what's happening there.
1333 * Dec 10, 2005 - Martin.
1337 assembly = dest->klass->image->assembly;
1338 type_resolve = TRUE;
1340 g_warning (G_STRLOC);
1345 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1346 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1349 if (!info.assembly.name && !type) /* try mscorlib */
1350 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1352 if (assembly && !type && type_resolve) {
1353 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1354 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1357 mono_reflection_free_type_info (&info);
1363 return mono_type_get_object (mono_domain_get (), type);
1367 MonoReflectionType *
1368 mono_type_get (const char *str)
1370 char *copy = g_strdup (str);
1371 MonoReflectionType *type = type_from_name (copy, FALSE);
1378 ICALL_EXPORT MonoReflectionType*
1379 ves_icall_type_from_name (MonoString *name,
1380 MonoBoolean throwOnError,
1381 MonoBoolean ignoreCase)
1383 char *str = mono_string_to_utf8 (name);
1384 MonoReflectionType *type;
1386 type = type_from_name (str, ignoreCase);
1389 MonoException *e = NULL;
1392 e = mono_get_exception_type_load (name, NULL);
1394 mono_loader_clear_error ();
1396 mono_raise_exception (e);
1403 ICALL_EXPORT MonoReflectionType*
1404 ves_icall_type_from_handle (MonoType *handle)
1406 MonoDomain *domain = mono_domain_get ();
1408 MONO_ARCH_SAVE_REGS;
1410 return mono_type_get_object (domain, handle);
1413 ICALL_EXPORT MonoBoolean
1414 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1416 MONO_ARCH_SAVE_REGS;
1418 if (c && type->type && c->type)
1419 return mono_metadata_type_equal (type->type, c->type);
1421 return (type == c) ? TRUE : FALSE;
1424 /* System.TypeCode */
1443 TYPECODE_STRING = 18
1446 ICALL_EXPORT guint32
1447 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1449 int t = type->type->type;
1451 MONO_ARCH_SAVE_REGS;
1453 if (type->type->byref)
1454 return TYPECODE_OBJECT;
1458 case MONO_TYPE_VOID:
1459 return TYPECODE_OBJECT;
1460 case MONO_TYPE_BOOLEAN:
1461 return TYPECODE_BOOLEAN;
1463 return TYPECODE_BYTE;
1465 return TYPECODE_SBYTE;
1467 return TYPECODE_UINT16;
1469 return TYPECODE_INT16;
1470 case MONO_TYPE_CHAR:
1471 return TYPECODE_CHAR;
1475 return TYPECODE_OBJECT;
1477 return TYPECODE_UINT32;
1479 return TYPECODE_INT32;
1481 return TYPECODE_UINT64;
1483 return TYPECODE_INT64;
1485 return TYPECODE_SINGLE;
1487 return TYPECODE_DOUBLE;
1488 case MONO_TYPE_VALUETYPE: {
1489 MonoClass *klass = type->type->data.klass;
1491 if (klass->enumtype) {
1492 t = mono_class_enum_basetype (klass)->type;
1494 } else if (mono_is_corlib_image (klass->image)) {
1495 if (strcmp (klass->name_space, "System") == 0) {
1496 if (strcmp (klass->name, "Decimal") == 0)
1497 return TYPECODE_DECIMAL;
1498 else if (strcmp (klass->name, "DateTime") == 0)
1499 return TYPECODE_DATETIME;
1502 return TYPECODE_OBJECT;
1504 case MONO_TYPE_STRING:
1505 return TYPECODE_STRING;
1506 case MONO_TYPE_SZARRAY:
1507 case MONO_TYPE_ARRAY:
1508 case MONO_TYPE_OBJECT:
1510 case MONO_TYPE_MVAR:
1511 case MONO_TYPE_TYPEDBYREF:
1512 return TYPECODE_OBJECT;
1513 case MONO_TYPE_CLASS:
1515 MonoClass *klass = type->type->data.klass;
1516 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1517 if (strcmp (klass->name, "DBNull") == 0)
1518 return TYPECODE_DBNULL;
1521 return TYPECODE_OBJECT;
1522 case MONO_TYPE_GENERICINST:
1523 return TYPECODE_OBJECT;
1525 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1530 ICALL_EXPORT guint32
1531 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1537 MONO_ARCH_SAVE_REGS;
1539 g_assert (type != NULL);
1541 domain = ((MonoObject *)type)->vtable->domain;
1543 if (!c) /* FIXME: dont know what do do here */
1546 klass = mono_class_from_mono_type (type->type);
1547 klassc = mono_class_from_mono_type (c->type);
1549 /* Interface check requires a more complex setup so we
1550 * only do for them. Otherwise we simply avoid mono_class_init.
1552 if (check_interfaces) {
1553 mono_class_init_or_throw (klass);
1554 mono_class_init_or_throw (klassc);
1555 } else if (!klass->supertypes || !klassc->supertypes) {
1556 mono_loader_lock ();
1557 mono_class_setup_supertypes (klass);
1558 mono_class_setup_supertypes (klassc);
1559 mono_loader_unlock ();
1562 if (type->type->byref)
1563 return klassc == mono_defaults.object_class;
1565 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1569 mono_type_is_primitive (MonoType *type)
1571 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1572 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1576 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1578 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1579 return mono_class_enum_basetype (type->data.klass);
1580 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1581 return mono_class_enum_basetype (type->data.generic_class->container_class);
1585 ICALL_EXPORT guint32
1586 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1592 MONO_ARCH_SAVE_REGS;
1594 g_assert (type != NULL);
1596 domain = ((MonoObject *)type)->vtable->domain;
1598 klass = mono_class_from_mono_type (type->type);
1599 klassc = mono_class_from_mono_type (c->type);
1601 mono_class_init_or_throw (klass);
1602 mono_class_init_or_throw (klassc);
1604 if (type->type->byref ^ c->type->byref)
1607 if (type->type->byref) {
1608 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1609 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1611 klass = mono_class_from_mono_type (t);
1612 klassc = mono_class_from_mono_type (ot);
1614 if (mono_type_is_primitive (t)) {
1615 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1616 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1617 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1618 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1619 return t->type == ot->type;
1621 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1624 if (klass->valuetype)
1625 return klass == klassc;
1626 return klass->valuetype == klassc->valuetype;
1629 return mono_class_is_assignable_from (klass, klassc);
1632 ICALL_EXPORT guint32
1633 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1635 MonoClass *klass = mono_class_from_mono_type (type->type);
1636 mono_class_init_or_throw (klass);
1637 return mono_object_isinst (obj, klass) != NULL;
1640 ICALL_EXPORT guint32
1641 ves_icall_get_attributes (MonoReflectionType *type)
1643 MonoClass *klass = mono_class_from_mono_type (type->type);
1644 return klass->flags;
1647 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1648 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1650 MonoClass *klass = field->field->parent;
1651 MonoMarshalType *info;
1654 if (klass->generic_container ||
1655 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1658 info = mono_marshal_load_type_info (klass);
1660 for (i = 0; i < info->num_fields; ++i) {
1661 if (info->fields [i].field == field->field) {
1662 if (!info->fields [i].mspec)
1665 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1672 ICALL_EXPORT MonoReflectionField*
1673 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1675 gboolean found = FALSE;
1682 klass = handle->parent;
1684 klass = mono_class_from_mono_type (type);
1686 /* Check that the field belongs to the class */
1687 for (k = klass; k; k = k->parent) {
1688 if (k == handle->parent) {
1695 /* The managed code will throw the exception */
1699 return mono_field_get_object (mono_domain_get (), klass, handle);
1702 ICALL_EXPORT MonoArray*
1703 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1706 MonoType *type = mono_field_get_type_checked (field->field, &error);
1707 if (!mono_error_ok (&error))
1708 mono_error_raise_exception (&error);
1710 return type_array_from_modifiers (field->field->parent->image, type, optional);
1714 vell_icall_get_method_attributes (MonoMethod *method)
1716 return method->flags;
1720 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1723 MonoDomain *domain = mono_domain_get ();
1724 MonoMethodSignature* sig;
1725 MONO_ARCH_SAVE_REGS;
1727 sig = mono_method_signature_checked (method, &error);
1728 if (!mono_error_ok (&error))
1729 mono_error_raise_exception (&error);
1732 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1733 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1734 info->attrs = method->flags;
1735 info->implattrs = method->iflags;
1736 if (sig->call_convention == MONO_CALL_DEFAULT)
1737 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1739 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1744 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1747 ICALL_EXPORT MonoArray*
1748 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1750 MonoDomain *domain = mono_domain_get ();
1752 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1755 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1756 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1758 MonoDomain *domain = mono_domain_get ();
1759 MonoReflectionMarshalAsAttribute* res = NULL;
1760 MonoMarshalSpec **mspecs;
1763 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1764 mono_method_get_marshal_info (method, mspecs);
1767 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1769 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1771 mono_metadata_free_marshal_spec (mspecs [i]);
1778 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1780 MonoClass *parent = field->field->parent;
1781 if (!parent->size_inited)
1782 mono_class_init (parent);
1784 return field->field->offset - sizeof (MonoObject);
1787 ICALL_EXPORT MonoReflectionType*
1788 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1791 MONO_ARCH_SAVE_REGS;
1793 parent = declaring? field->field->parent: field->klass;
1795 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1798 ICALL_EXPORT MonoObject *
1799 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1801 MonoClass *fklass = field->klass;
1802 MonoClassField *cf = field->field;
1803 MonoDomain *domain = mono_object_domain (field);
1805 if (fklass->image->assembly->ref_only)
1806 mono_raise_exception (mono_get_exception_invalid_operation (
1807 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1809 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1810 mono_security_core_clr_ensure_reflection_access_field (cf);
1812 return mono_field_get_value_object (domain, cf, obj);
1816 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1819 MonoClassField *cf = field->field;
1823 MONO_ARCH_SAVE_REGS;
1825 if (field->klass->image->assembly->ref_only)
1826 mono_raise_exception (mono_get_exception_invalid_operation (
1827 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1829 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
1830 mono_security_core_clr_ensure_reflection_access_field (cf);
1832 type = mono_field_get_type_checked (cf, &error);
1833 if (!mono_error_ok (&error))
1834 mono_error_raise_exception (&error);
1836 v = (gchar *) value;
1838 switch (type->type) {
1841 case MONO_TYPE_BOOLEAN:
1844 case MONO_TYPE_CHAR:
1853 case MONO_TYPE_VALUETYPE:
1856 v += sizeof (MonoObject);
1858 case MONO_TYPE_STRING:
1859 case MONO_TYPE_OBJECT:
1860 case MONO_TYPE_CLASS:
1861 case MONO_TYPE_ARRAY:
1862 case MONO_TYPE_SZARRAY:
1865 case MONO_TYPE_GENERICINST: {
1866 MonoGenericClass *gclass = type->data.generic_class;
1867 g_assert (!gclass->context.class_inst->is_open);
1869 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1870 MonoClass *nklass = mono_class_from_mono_type (type);
1871 MonoObject *nullable;
1874 * Convert the boxed vtype into a Nullable structure.
1875 * This is complicated by the fact that Nullables have
1876 * a variable structure.
1878 nullable = mono_object_new (mono_domain_get (), nklass);
1880 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1882 v = mono_object_unbox (nullable);
1885 if (gclass->container_class->valuetype && (v != NULL))
1886 v += sizeof (MonoObject);
1890 g_error ("type 0x%x not handled in "
1891 "ves_icall_FieldInfo_SetValueInternal", type->type);
1896 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1897 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1898 if (!vtable->initialized)
1899 mono_runtime_class_init (vtable);
1900 mono_field_static_set_value (vtable, cf, v);
1902 mono_field_set_value (obj, cf, v);
1906 ICALL_EXPORT MonoObject *
1907 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1909 MonoObject *o = NULL;
1910 MonoClassField *field = this->field;
1912 MonoDomain *domain = mono_object_domain (this);
1914 MonoTypeEnum def_type;
1915 const char *def_value;
1919 MONO_ARCH_SAVE_REGS;
1921 mono_class_init (field->parent);
1923 t = mono_field_get_type_checked (field, &error);
1924 if (!mono_error_ok (&error))
1925 mono_error_raise_exception (&error);
1927 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1928 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1930 if (field->parent->image->dynamic) {
1932 g_assert_not_reached ();
1935 def_value = mono_class_get_field_default_value (field, &def_type);
1936 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1937 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1939 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1943 case MONO_TYPE_BOOLEAN:
1946 case MONO_TYPE_CHAR:
1954 case MONO_TYPE_R8: {
1957 /* boxed value type */
1958 t = g_new0 (MonoType, 1);
1960 klass = mono_class_from_mono_type (t);
1962 o = mono_object_new (domain, klass);
1963 v = ((gchar *) o) + sizeof (MonoObject);
1964 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1967 case MONO_TYPE_STRING:
1968 case MONO_TYPE_CLASS:
1969 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1972 g_assert_not_reached ();
1978 ICALL_EXPORT MonoReflectionType*
1979 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1982 MonoClassField *field = ref_field->field;
1983 MonoType *type = mono_field_get_type_checked (field, &error);
1984 if (!mono_error_ok (&error))
1985 mono_error_raise_exception (&error);
1986 return mono_type_get_object (mono_object_domain (ref_field), type);
1989 ICALL_EXPORT MonoReflectionType*
1990 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1992 MonoMethod *method = rmethod->method.method;
1994 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1997 /* From MonoProperty.cs */
1999 PInfo_Attributes = 1,
2000 PInfo_GetMethod = 1 << 1,
2001 PInfo_SetMethod = 1 << 2,
2002 PInfo_ReflectedType = 1 << 3,
2003 PInfo_DeclaringType = 1 << 4,
2008 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
2010 MonoDomain *domain = mono_object_domain (property);
2012 MONO_ARCH_SAVE_REGS;
2014 if ((req_info & PInfo_ReflectedType) != 0)
2015 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
2016 if ((req_info & PInfo_DeclaringType) != 0)
2017 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
2019 if ((req_info & PInfo_Name) != 0)
2020 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2022 if ((req_info & PInfo_Attributes) != 0)
2023 info->attrs = property->property->attrs;
2025 if ((req_info & PInfo_GetMethod) != 0)
2026 MONO_STRUCT_SETREF (info, get, property->property->get ?
2027 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2029 if ((req_info & PInfo_SetMethod) != 0)
2030 MONO_STRUCT_SETREF (info, set, property->property->set ?
2031 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2033 * There may be other methods defined for properties, though, it seems they are not exposed
2034 * in the reflection API
2039 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2041 MonoDomain *domain = mono_object_domain (event);
2043 MONO_ARCH_SAVE_REGS;
2045 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2046 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2048 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2049 info->attrs = event->event->attrs;
2050 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2051 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2052 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2054 #ifndef MONO_SMALL_CONFIG
2055 if (event->event->other) {
2057 while (event->event->other [n])
2059 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2061 for (i = 0; i < n; i++)
2062 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2068 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2073 mono_class_setup_interfaces (klass, error);
2074 if (!mono_error_ok (error))
2077 for (i = 0; i < klass->interface_count; i++) {
2078 ic = klass->interfaces [i];
2079 g_hash_table_insert (ifaces, ic, ic);
2081 collect_interfaces (ic, ifaces, error);
2082 if (!mono_error_ok (error))
2088 MonoArray *iface_array;
2089 MonoGenericContext *context;
2093 } FillIfaceArrayData;
2096 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2098 FillIfaceArrayData *data = user_data;
2099 MonoClass *ic = key;
2100 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2102 if (!mono_error_ok (data->error))
2105 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2106 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2107 if (!mono_error_ok (data->error))
2111 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2114 mono_metadata_free_type (inflated);
2117 ICALL_EXPORT MonoArray*
2118 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2121 MonoClass *class = mono_class_from_mono_type (type->type);
2123 FillIfaceArrayData data = { 0 };
2126 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2128 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2129 data.context = mono_class_get_context (class);
2130 class = class->generic_class->container_class;
2133 for (parent = class; parent; parent = parent->parent) {
2134 mono_class_setup_interfaces (parent, &error);
2135 if (!mono_error_ok (&error))
2137 collect_interfaces (parent, iface_hash, &error);
2138 if (!mono_error_ok (&error))
2142 data.error = &error;
2143 data.domain = mono_object_domain (type);
2145 len = g_hash_table_size (iface_hash);
2147 g_hash_table_destroy (iface_hash);
2148 if (!data.domain->empty_types)
2149 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2150 return data.domain->empty_types;
2153 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2154 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2155 if (!mono_error_ok (&error))
2158 g_hash_table_destroy (iface_hash);
2159 return data.iface_array;
2162 g_hash_table_destroy (iface_hash);
2163 mono_error_raise_exception (&error);
2168 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2170 gboolean variance_used;
2171 MonoClass *class = mono_class_from_mono_type (type->type);
2172 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2173 MonoReflectionMethod *member;
2176 int i = 0, len, ioffset;
2179 MONO_ARCH_SAVE_REGS;
2180 mono_class_init_or_throw (class);
2181 mono_class_init_or_throw (iclass);
2183 mono_class_setup_vtable (class);
2185 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2189 len = mono_class_num_methods (iclass);
2190 domain = mono_object_domain (type);
2191 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2192 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2194 while ((method = mono_class_get_methods (iclass, &iter))) {
2195 member = mono_method_get_object (domain, method, iclass);
2196 mono_array_setref (*methods, i, member);
2197 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2198 mono_array_setref (*targets, i, member);
2205 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2207 MonoClass *klass = mono_class_from_mono_type (type->type);
2208 mono_class_init_or_throw (klass);
2210 if (klass->image->dynamic) {
2211 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2212 *packing = tb->packing_size;
2213 *size = tb->class_size;
2215 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2219 ICALL_EXPORT MonoReflectionType*
2220 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2224 MONO_ARCH_SAVE_REGS;
2226 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2227 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2229 class = mono_class_from_mono_type (type->type);
2230 mono_class_init_or_throw (class);
2232 // GetElementType should only return a type for:
2233 // Array Pointer PassedByRef
2234 if (type->type->byref)
2235 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2236 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2237 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2238 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2239 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2244 ICALL_EXPORT MonoReflectionType*
2245 ves_icall_get_type_parent (MonoReflectionType *type)
2247 MonoClass *class = mono_class_from_mono_type (type->type);
2248 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2251 ICALL_EXPORT MonoBoolean
2252 ves_icall_type_ispointer (MonoReflectionType *type)
2254 MONO_ARCH_SAVE_REGS;
2256 return type->type->type == MONO_TYPE_PTR;
2259 ICALL_EXPORT MonoBoolean
2260 ves_icall_type_isprimitive (MonoReflectionType *type)
2262 MONO_ARCH_SAVE_REGS;
2264 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)));
2267 ICALL_EXPORT MonoBoolean
2268 ves_icall_type_isbyref (MonoReflectionType *type)
2270 MONO_ARCH_SAVE_REGS;
2272 return type->type->byref;
2275 ICALL_EXPORT MonoBoolean
2276 ves_icall_type_iscomobject (MonoReflectionType *type)
2278 MonoClass *klass = mono_class_from_mono_type (type->type);
2279 mono_class_init_or_throw (klass);
2281 return (klass && klass->is_com_object);
2284 ICALL_EXPORT MonoReflectionModule*
2285 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2287 MonoClass *class = mono_class_from_mono_type (type->type);
2288 return mono_module_get_object (mono_object_domain (type), class->image);
2291 ICALL_EXPORT MonoReflectionAssembly*
2292 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2294 MonoDomain *domain = mono_domain_get ();
2295 MonoClass *class = mono_class_from_mono_type (type->type);
2296 return mono_assembly_get_object (domain, class->image->assembly);
2299 ICALL_EXPORT MonoReflectionType*
2300 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2302 MonoDomain *domain = mono_domain_get ();
2305 MONO_ARCH_SAVE_REGS;
2307 if (type->type->byref)
2309 if (type->type->type == MONO_TYPE_VAR)
2310 class = mono_type_get_generic_param_owner (type->type)->owner.klass;
2311 else if (type->type->type == MONO_TYPE_MVAR)
2312 class = mono_type_get_generic_param_owner (type->type)->owner.method->klass;
2314 class = mono_class_from_mono_type (type->type)->nested_in;
2316 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2319 ICALL_EXPORT MonoString*
2320 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2322 MonoDomain *domain = mono_domain_get ();
2323 MonoClass *class = mono_class_from_mono_type (type->type);
2325 if (type->type->byref) {
2326 char *n = g_strdup_printf ("%s&", class->name);
2327 MonoString *res = mono_string_new (domain, n);
2333 return mono_string_new (domain, class->name);
2337 ICALL_EXPORT MonoString*
2338 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2340 MonoDomain *domain = mono_domain_get ();
2341 MonoClass *class = mono_class_from_mono_type (type->type);
2343 while (class->nested_in)
2344 class = class->nested_in;
2346 if (class->name_space [0] == '\0')
2349 return mono_string_new (domain, class->name_space);
2353 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2357 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2358 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2360 class = mono_class_from_mono_type (type->type);
2365 ICALL_EXPORT MonoArray*
2366 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2369 MonoClass *klass, *pklass;
2370 MonoDomain *domain = mono_object_domain (type);
2371 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2373 MONO_ARCH_SAVE_REGS;
2375 klass = mono_class_from_mono_type (type->type);
2377 if (klass->generic_container) {
2378 MonoGenericContainer *container = klass->generic_container;
2379 res = mono_array_new_specific (array_vtable, container->type_argc);
2380 for (i = 0; i < container->type_argc; ++i) {
2381 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2382 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2384 } else if (klass->generic_class) {
2385 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2386 res = mono_array_new_specific (array_vtable, inst->type_argc);
2387 for (i = 0; i < inst->type_argc; ++i)
2388 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2390 res = mono_array_new_specific (array_vtable, 0);
2395 ICALL_EXPORT gboolean
2396 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2399 MONO_ARCH_SAVE_REGS;
2401 if (!IS_MONOTYPE (type))
2404 if (type->type->byref)
2407 klass = mono_class_from_mono_type (type->type);
2408 return klass->generic_container != NULL;
2411 ICALL_EXPORT MonoReflectionType*
2412 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2415 MONO_ARCH_SAVE_REGS;
2417 if (type->type->byref)
2420 klass = mono_class_from_mono_type (type->type);
2422 if (klass->generic_container) {
2423 return type; /* check this one */
2425 if (klass->generic_class) {
2426 MonoClass *generic_class = klass->generic_class->container_class;
2429 tb = mono_class_get_ref_info (generic_class);
2431 if (generic_class->wastypebuilder && tb)
2434 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2439 ICALL_EXPORT MonoReflectionType*
2440 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2443 MonoType *geninst, **types;
2446 g_assert (IS_MONOTYPE (type));
2447 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2449 count = mono_array_length (type_array);
2450 types = g_new0 (MonoType *, count);
2452 for (i = 0; i < count; i++) {
2453 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2454 types [i] = t->type;
2457 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2462 class = mono_class_from_mono_type (geninst);
2464 /*we might inflate to the GTD*/
2465 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2466 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2468 return mono_type_get_object (mono_object_domain (type), geninst);
2471 ICALL_EXPORT gboolean
2472 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2475 MONO_ARCH_SAVE_REGS;
2477 if (type->type->byref)
2480 klass = mono_class_from_mono_type (type->type);
2482 return klass->generic_class != NULL;
2485 ICALL_EXPORT gboolean
2486 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2489 MONO_ARCH_SAVE_REGS;
2491 if (!IS_MONOTYPE (type))
2494 if (type->type->byref)
2497 klass = mono_class_from_mono_type (type->type);
2498 return klass->generic_class != NULL || klass->generic_container != NULL;
2502 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2504 MONO_ARCH_SAVE_REGS;
2506 if (!IS_MONOTYPE (type))
2509 if (is_generic_parameter (type->type))
2510 return mono_type_get_generic_param_num (type->type);
2514 ICALL_EXPORT GenericParameterAttributes
2515 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2517 MONO_ARCH_SAVE_REGS;
2519 g_assert (IS_MONOTYPE (type));
2520 g_assert (is_generic_parameter (type->type));
2521 return mono_generic_param_info (type->type->data.generic_param)->flags;
2524 ICALL_EXPORT MonoArray *
2525 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2527 MonoGenericParamInfo *param_info;
2533 MONO_ARCH_SAVE_REGS;
2535 g_assert (IS_MONOTYPE (type));
2537 domain = mono_object_domain (type);
2538 param_info = mono_generic_param_info (type->type->data.generic_param);
2539 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2542 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2543 for (i = 0; i < count; i++)
2544 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2550 ICALL_EXPORT MonoBoolean
2551 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2553 MONO_ARCH_SAVE_REGS;
2554 return is_generic_parameter (type->type);
2557 ICALL_EXPORT MonoBoolean
2558 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2560 MONO_ARCH_SAVE_REGS;
2561 return is_generic_parameter (tb->type.type);
2565 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2566 MonoReflectionType *t)
2568 enumtype->type = t->type;
2571 ICALL_EXPORT MonoReflectionMethod*
2572 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2573 MonoReflectionMethod* generic)
2580 MONO_ARCH_SAVE_REGS;
2582 domain = ((MonoObject *)type)->vtable->domain;
2584 klass = mono_class_from_mono_type (type->type);
2585 mono_class_init_or_throw (klass);
2588 while ((method = mono_class_get_methods (klass, &iter))) {
2589 if (method->token == generic->method->token)
2590 return mono_method_get_object (domain, method, klass);
2598 ICALL_EXPORT MonoReflectionMethod *
2599 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2602 MonoType *type = ref_type->type;
2604 MONO_ARCH_SAVE_REGS;
2606 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2607 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2608 if (type->type == MONO_TYPE_VAR)
2611 method = mono_type_get_generic_param_owner (type)->owner.method;
2613 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2616 ICALL_EXPORT MonoReflectionDllImportAttribute*
2617 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2619 static MonoClass *DllImportAttributeClass = NULL;
2620 MonoDomain *domain = mono_domain_get ();
2621 MonoReflectionDllImportAttribute *attr;
2622 MonoImage *image = method->klass->image;
2623 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2624 MonoTableInfo *tables = image->tables;
2625 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2626 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2627 guint32 im_cols [MONO_IMPLMAP_SIZE];
2628 guint32 scope_token;
2629 const char *import = NULL;
2630 const char *scope = NULL;
2633 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2636 if (!DllImportAttributeClass) {
2637 DllImportAttributeClass =
2638 mono_class_from_name (mono_defaults.corlib,
2639 "System.Runtime.InteropServices", "DllImportAttribute");
2640 g_assert (DllImportAttributeClass);
2643 if (method->klass->image->dynamic) {
2644 MonoReflectionMethodAux *method_aux =
2645 g_hash_table_lookup (
2646 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2648 import = method_aux->dllentry;
2649 scope = method_aux->dll;
2652 if (!import || !scope) {
2653 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2658 if (piinfo->implmap_idx) {
2659 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2661 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2662 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2663 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2664 scope = mono_metadata_string_heap (image, scope_token);
2667 flags = piinfo->piflags;
2669 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2671 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2672 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2673 attr->call_conv = (flags & 0x700) >> 8;
2674 attr->charset = ((flags & 0x6) >> 1) + 1;
2675 if (attr->charset == 1)
2677 attr->exact_spelling = (flags & 0x1) != 0;
2678 attr->set_last_error = (flags & 0x40) != 0;
2679 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2680 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2681 attr->preserve_sig = FALSE;
2686 ICALL_EXPORT MonoReflectionMethod *
2687 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2689 MonoMethodInflated *imethod;
2692 MONO_ARCH_SAVE_REGS;
2694 if (method->method->is_generic)
2697 if (!method->method->is_inflated)
2700 imethod = (MonoMethodInflated *) method->method;
2702 result = imethod->declaring;
2703 /* Not a generic method. */
2704 if (!result->is_generic)
2707 if (method->method->klass->image->dynamic) {
2708 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2709 MonoReflectionMethod *res;
2712 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2713 * the dynamic case as well ?
2715 mono_loader_lock ();
2716 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2717 mono_loader_unlock ();
2723 if (imethod->context.class_inst) {
2724 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2725 /*Generic methods gets the context of the GTD.*/
2726 if (mono_class_get_context (klass))
2727 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2730 return mono_method_get_object (mono_object_domain (method), result, NULL);
2733 ICALL_EXPORT gboolean
2734 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2736 MONO_ARCH_SAVE_REGS;
2738 return mono_method_signature (method->method)->generic_param_count != 0;
2741 ICALL_EXPORT gboolean
2742 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2744 MONO_ARCH_SAVE_REGS;
2746 return method->method->is_generic;
2749 ICALL_EXPORT MonoArray*
2750 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2755 MONO_ARCH_SAVE_REGS;
2757 domain = mono_object_domain (method);
2759 if (method->method->is_inflated) {
2760 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2763 count = inst->type_argc;
2764 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2766 for (i = 0; i < count; i++)
2767 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2773 count = mono_method_signature (method->method)->generic_param_count;
2774 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2776 for (i = 0; i < count; i++) {
2777 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2778 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2779 MonoClass *pklass = mono_class_from_generic_parameter (
2780 param, method->method->klass->image, TRUE);
2781 mono_array_setref (res, i,
2782 mono_type_get_object (domain, &pklass->byval_arg));
2788 ICALL_EXPORT MonoObject *
2789 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2792 * Invoke from reflection is supposed to always be a virtual call (the API
2793 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2794 * greater flexibility.
2796 MonoMethod *m = method->method;
2797 MonoMethodSignature *sig = mono_method_signature (m);
2801 MONO_ARCH_SAVE_REGS;
2805 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR)
2806 mono_security_core_clr_ensure_reflection_access_method (m);
2808 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2809 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2810 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2815 if (!mono_object_isinst (this, m->klass)) {
2816 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2817 char *target_name = mono_type_get_full_name (m->klass);
2818 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2819 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2821 g_free (target_name);
2825 m = mono_object_get_virtual_method (this, m);
2826 /* must pass the pointer to the value for valuetype methods */
2827 if (m->klass->valuetype)
2828 obj = mono_object_unbox (this);
2829 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2830 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2835 if (sig->ret->byref) {
2836 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"));
2840 pcount = params? mono_array_length (params): 0;
2841 if (pcount != sig->param_count) {
2842 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2846 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2847 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."));
2851 if (m->klass->image->assembly->ref_only) {
2852 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."));
2856 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2859 intptr_t *lower_bounds;
2860 pcount = mono_array_length (params);
2861 lengths = alloca (sizeof (uintptr_t) * pcount);
2862 /* Note: the synthetized array .ctors have int32 as argument type */
2863 for (i = 0; i < pcount; ++i)
2864 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2866 if (m->klass->rank == pcount) {
2867 /* Only lengths provided. */
2868 lower_bounds = NULL;
2870 g_assert (pcount == (m->klass->rank * 2));
2871 /* lower bounds are first. */
2872 lower_bounds = (intptr_t*)lengths;
2873 lengths += m->klass->rank;
2876 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2878 return mono_runtime_invoke_array (m, obj, params, NULL);
2881 #ifndef DISABLE_REMOTING
2882 ICALL_EXPORT MonoObject *
2883 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2885 MonoDomain *domain = mono_object_domain (method);
2886 MonoMethod *m = method->method;
2887 MonoMethodSignature *sig = mono_method_signature (m);
2888 MonoArray *out_args;
2890 int i, j, outarg_count = 0;
2892 MONO_ARCH_SAVE_REGS;
2894 if (m->klass == mono_defaults.object_class) {
2896 if (!strcmp (m->name, "FieldGetter")) {
2897 MonoClass *k = this->vtable->klass;
2901 /* If this is a proxy, then it must be a CBO */
2902 if (k == mono_defaults.transparent_proxy_class) {
2903 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2904 this = tp->rp->unwrapped_server;
2906 k = this->vtable->klass;
2909 name = mono_array_get (params, MonoString *, 1);
2910 str = mono_string_to_utf8 (name);
2913 MonoClassField* field = mono_class_get_field_from_name (k, str);
2915 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2916 if (field_klass->valuetype)
2917 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2919 result = *((gpointer *)((char *)this + field->offset));
2921 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2922 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2923 mono_array_setref (out_args, 0, result);
2931 g_assert_not_reached ();
2933 } else if (!strcmp (m->name, "FieldSetter")) {
2934 MonoClass *k = this->vtable->klass;
2940 /* If this is a proxy, then it must be a CBO */
2941 if (k == mono_defaults.transparent_proxy_class) {
2942 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2943 this = tp->rp->unwrapped_server;
2945 k = this->vtable->klass;
2948 name = mono_array_get (params, MonoString *, 1);
2949 str = mono_string_to_utf8 (name);
2952 MonoClassField* field = mono_class_get_field_from_name (k, str);
2954 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2955 MonoObject *val = mono_array_get (params, gpointer, 2);
2957 if (field_klass->valuetype) {
2958 size = mono_type_size (field->type, &align);
2959 g_assert (size == mono_class_value_size (field_klass, NULL));
2960 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2962 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2965 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2966 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2976 g_assert_not_reached ();
2981 for (i = 0; i < mono_array_length (params); i++) {
2982 if (sig->params [i]->byref)
2986 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2988 /* handle constructors only for objects already allocated */
2989 if (!strcmp (method->method->name, ".ctor"))
2992 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2993 g_assert (!method->method->klass->valuetype);
2994 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2996 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2997 if (sig->params [i]->byref) {
2999 arg = mono_array_get (params, gpointer, i);
3000 mono_array_setref (out_args, j, arg);
3005 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3012 read_enum_value (char *mem, int type)
3016 return *(guint8*)mem;
3018 return *(gint8*)mem;
3020 return *(guint16*)mem;
3022 return *(gint16*)mem;
3024 return *(guint32*)mem;
3026 return *(gint32*)mem;
3028 return *(guint64*)mem;
3030 return *(gint64*)mem;
3032 g_assert_not_reached ();
3038 write_enum_value (char *mem, int type, guint64 value)
3042 case MONO_TYPE_I1: {
3043 guint8 *p = (guint8*)mem;
3048 case MONO_TYPE_I2: {
3049 guint16 *p = (void*)mem;
3054 case MONO_TYPE_I4: {
3055 guint32 *p = (void*)mem;
3060 case MONO_TYPE_I8: {
3061 guint64 *p = (void*)mem;
3066 g_assert_not_reached ();
3071 ICALL_EXPORT MonoObject *
3072 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3075 MonoClass *enumc, *objc;
3080 MONO_ARCH_SAVE_REGS;
3082 MONO_CHECK_ARG_NULL (enumType);
3083 MONO_CHECK_ARG_NULL (value);
3085 domain = mono_object_domain (enumType);
3086 enumc = mono_class_from_mono_type (enumType->type);
3088 mono_class_init_or_throw (enumc);
3090 objc = value->vtable->klass;
3092 if (!enumc->enumtype)
3093 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3094 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3095 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."));
3097 etype = mono_class_enum_basetype (enumc);
3099 /* MS throws this for typebuilders */
3100 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3102 res = mono_object_new (domain, enumc);
3103 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3104 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3109 ICALL_EXPORT MonoObject *
3110 ves_icall_System_Enum_get_value (MonoObject *this)
3118 MONO_ARCH_SAVE_REGS;
3123 g_assert (this->vtable->klass->enumtype);
3125 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3126 res = mono_object_new (mono_object_domain (this), enumc);
3127 dst = (char *)res + sizeof (MonoObject);
3128 src = (char *)this + sizeof (MonoObject);
3129 size = mono_class_value_size (enumc, NULL);
3131 memcpy (dst, src, size);
3136 ICALL_EXPORT MonoReflectionType *
3137 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3142 MONO_ARCH_SAVE_REGS;
3144 klass = mono_class_from_mono_type (type->type);
3145 mono_class_init_or_throw (klass);
3147 etype = mono_class_enum_basetype (klass);
3149 /* MS throws this for typebuilders */
3150 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3152 return mono_type_get_object (mono_object_domain (type), etype);
3156 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3158 gpointer tdata = (char *)this + sizeof (MonoObject);
3159 gpointer odata = (char *)other + sizeof (MonoObject);
3160 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3161 g_assert (basetype);
3163 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3164 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3165 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3168 return me > other ? 1 : -1; \
3171 #define COMPARE_ENUM_VALUES_RANGE(ENUM_TYPE) do { \
3172 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3173 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3176 return me - other; \
3179 switch (basetype->type) {
3181 COMPARE_ENUM_VALUES (guint8);
3183 COMPARE_ENUM_VALUES (gint8);
3184 case MONO_TYPE_CHAR:
3186 COMPARE_ENUM_VALUES_RANGE (guint16);
3188 COMPARE_ENUM_VALUES (gint16);
3190 COMPARE_ENUM_VALUES (guint32);
3192 COMPARE_ENUM_VALUES (gint32);
3194 COMPARE_ENUM_VALUES (guint64);
3196 COMPARE_ENUM_VALUES (gint64);
3198 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3200 #undef COMPARE_ENUM_VALUES_RANGE
3201 #undef COMPARE_ENUM_VALUES
3206 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3208 gpointer data = (char *)this + sizeof (MonoObject);
3209 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3210 g_assert (basetype);
3212 switch (basetype->type) {
3214 return *((gint8*)data);
3216 return *((guint8*)data);
3217 case MONO_TYPE_CHAR:
3219 return *((guint16*)data);
3222 return *((gint16*)data);
3224 return *((guint32*)data);
3226 return *((gint32*)data);
3228 case MONO_TYPE_I8: {
3229 gint64 value = *((gint64*)data);
3230 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3233 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3239 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3241 MonoDomain *domain = mono_object_domain (type);
3242 MonoClass *enumc = mono_class_from_mono_type (type->type);
3243 guint j = 0, nvalues, crow;
3245 MonoClassField *field;
3247 MONO_ARCH_SAVE_REGS;
3249 mono_class_init_or_throw (enumc);
3251 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3252 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3253 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3254 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3258 while ((field = mono_class_get_fields (enumc, &iter))) {
3261 MonoTypeEnum def_type;
3263 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3265 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3267 if (mono_field_is_deleted (field))
3269 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3271 p = mono_class_get_field_default_value (field, &def_type);
3272 len = mono_metadata_decode_blob_size (p, &p);
3273 switch (mono_class_enum_basetype (enumc)->type) {
3276 mono_array_set (info->values, gchar, j, *p);
3278 case MONO_TYPE_CHAR:
3281 mono_array_set (info->values, gint16, j, read16 (p));
3285 mono_array_set (info->values, gint32, j, read32 (p));
3289 mono_array_set (info->values, gint64, j, read64 (p));
3292 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3299 BFLAGS_IgnoreCase = 1,
3300 BFLAGS_DeclaredOnly = 2,
3301 BFLAGS_Instance = 4,
3303 BFLAGS_Public = 0x10,
3304 BFLAGS_NonPublic = 0x20,
3305 BFLAGS_FlattenHierarchy = 0x40,
3306 BFLAGS_InvokeMethod = 0x100,
3307 BFLAGS_CreateInstance = 0x200,
3308 BFLAGS_GetField = 0x400,
3309 BFLAGS_SetField = 0x800,
3310 BFLAGS_GetProperty = 0x1000,
3311 BFLAGS_SetProperty = 0x2000,
3312 BFLAGS_ExactBinding = 0x10000,
3313 BFLAGS_SuppressChangeType = 0x20000,
3314 BFLAGS_OptionalParamBinding = 0x40000
3317 ICALL_EXPORT MonoReflectionField *
3318 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3321 MonoClass *startklass, *klass;
3323 MonoClassField *field;
3326 int (*compare_func) (const char *s1, const char *s2) = NULL;
3327 domain = ((MonoObject *)type)->vtable->domain;
3328 klass = startklass = mono_class_from_mono_type (type->type);
3331 mono_raise_exception (mono_get_exception_argument_null ("name"));
3332 if (type->type->byref)
3335 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3338 if (klass->exception_type != MONO_EXCEPTION_NONE)
3339 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3342 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3343 guint32 flags = mono_field_get_flags (field);
3346 if (mono_field_is_deleted_with_flags (field, flags))
3348 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3349 if (bflags & BFLAGS_Public)
3351 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3352 if (bflags & BFLAGS_NonPublic) {
3359 if (flags & FIELD_ATTRIBUTE_STATIC) {
3360 if (bflags & BFLAGS_Static)
3361 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3364 if (bflags & BFLAGS_Instance)
3371 utf8_name = mono_string_to_utf8 (name);
3373 if (compare_func (mono_field_get_name (field), utf8_name)) {
3379 return mono_field_get_object (domain, klass, field);
3381 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3387 ICALL_EXPORT MonoArray*
3388 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3391 MonoClass *startklass, *klass, *refklass;
3396 MonoClassField *field;
3397 MonoPtrArray tmp_array;
3399 MONO_ARCH_SAVE_REGS;
3401 domain = ((MonoObject *)type)->vtable->domain;
3402 if (type->type->byref)
3403 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3404 klass = startklass = mono_class_from_mono_type (type->type);
3405 refklass = mono_class_from_mono_type (reftype->type);
3407 mono_ptr_array_init (tmp_array, 2);
3410 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3411 mono_ptr_array_destroy (tmp_array);
3412 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3416 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3417 guint32 flags = mono_field_get_flags (field);
3419 if (mono_field_is_deleted_with_flags (field, flags))
3421 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3422 if (bflags & BFLAGS_Public)
3424 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3425 if (bflags & BFLAGS_NonPublic) {
3432 if (flags & FIELD_ATTRIBUTE_STATIC) {
3433 if (bflags & BFLAGS_Static)
3434 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3437 if (bflags & BFLAGS_Instance)
3443 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3444 mono_ptr_array_append (tmp_array, member);
3446 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3449 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3451 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3452 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3454 mono_ptr_array_destroy (tmp_array);
3460 method_nonpublic (MonoMethod* method, gboolean start_klass)
3462 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3463 case METHOD_ATTRIBUTE_ASSEM:
3464 return (start_klass || mono_defaults.generic_ilist_class);
3465 case METHOD_ATTRIBUTE_PRIVATE:
3467 case METHOD_ATTRIBUTE_PUBLIC:
3475 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3478 MonoClass *startklass;
3481 int len, match, nslots;
3482 /*FIXME, use MonoBitSet*/
3483 guint32 method_slots_default [8];
3484 guint32 *method_slots = NULL;
3485 int (*compare_func) (const char *s1, const char *s2) = NULL;
3487 array = g_ptr_array_new ();
3493 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3495 /* An optimization for calls made from Delegate:CreateDelegate () */
3496 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3497 method = mono_get_delegate_invoke (klass);
3498 if (mono_loader_get_last_error ())
3501 g_ptr_array_add (array, method);
3505 mono_class_setup_vtable (klass);
3506 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3509 if (is_generic_parameter (&klass->byval_arg))
3510 nslots = mono_class_get_vtable_size (klass->parent);
3512 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3513 if (nslots >= sizeof (method_slots_default) * 8) {
3514 method_slots = g_new0 (guint32, nslots / 32 + 1);
3516 method_slots = method_slots_default;
3517 memset (method_slots, 0, sizeof (method_slots_default));
3520 mono_class_setup_vtable (klass);
3521 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3525 while ((method = mono_class_get_methods (klass, &iter))) {
3527 if (method->slot != -1) {
3528 g_assert (method->slot < nslots);
3529 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3531 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3532 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3535 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3537 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3538 if (bflags & BFLAGS_Public)
3540 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3546 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3547 if (bflags & BFLAGS_Static)
3548 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3551 if (bflags & BFLAGS_Instance)
3559 if (compare_func (name, method->name))
3564 g_ptr_array_add (array, method);
3566 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3568 if (method_slots != method_slots_default)
3569 g_free (method_slots);
3574 if (method_slots != method_slots_default)
3575 g_free (method_slots);
3576 g_ptr_array_free (array, TRUE);
3578 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3579 *ex = mono_class_get_exception_for_failure (klass);
3581 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3582 mono_loader_clear_error ();
3587 ICALL_EXPORT MonoArray*
3588 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3590 static MonoClass *MethodInfo_array;
3593 MonoVTable *array_vtable;
3594 MonoException *ex = NULL;
3595 const char *mname = NULL;
3596 GPtrArray *method_array;
3597 MonoClass *klass, *refklass;
3600 if (!MethodInfo_array) {
3601 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3602 mono_memory_barrier ();
3603 MethodInfo_array = klass;
3606 klass = mono_class_from_mono_type (type->type);
3607 refklass = mono_class_from_mono_type (reftype->type);
3608 domain = ((MonoObject *)type)->vtable->domain;
3609 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3610 if (type->type->byref)
3611 return mono_array_new_specific (array_vtable, 0);
3614 mname = mono_string_to_utf8 (name);
3616 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3617 g_free ((char*)mname);
3619 mono_raise_exception (ex);
3621 res = mono_array_new_specific (array_vtable, method_array->len);
3624 for (i = 0; i < method_array->len; ++i) {
3625 MonoMethod *method = g_ptr_array_index (method_array, i);
3626 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3629 g_ptr_array_free (method_array, TRUE);
3633 ICALL_EXPORT MonoArray*
3634 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3637 static MonoClass *System_Reflection_ConstructorInfo;
3638 MonoClass *startklass, *klass, *refklass;
3643 gpointer iter = NULL;
3644 MonoPtrArray tmp_array;
3646 MONO_ARCH_SAVE_REGS;
3648 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3650 domain = ((MonoObject *)type)->vtable->domain;
3651 if (type->type->byref)
3652 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3653 klass = startklass = mono_class_from_mono_type (type->type);
3654 refklass = mono_class_from_mono_type (reftype->type);
3656 if (!System_Reflection_ConstructorInfo)
3657 System_Reflection_ConstructorInfo = mono_class_from_name (
3658 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3661 while ((method = mono_class_get_methods (klass, &iter))) {
3663 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3665 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3666 if (bflags & BFLAGS_Public)
3669 if (bflags & BFLAGS_NonPublic)
3675 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3676 if (bflags & BFLAGS_Static)
3677 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3680 if (bflags & BFLAGS_Instance)
3686 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3688 mono_ptr_array_append (tmp_array, member);
3691 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3693 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3694 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3696 mono_ptr_array_destroy (tmp_array);
3702 property_hash (gconstpointer data)
3704 MonoProperty *prop = (MonoProperty*)data;
3706 return g_str_hash (prop->name);
3710 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3712 // Properties are hide-by-name-and-signature
3713 if (!g_str_equal (prop1->name, prop2->name))
3716 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3718 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3724 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3729 return method_nonpublic (accessor, start_klass);
3732 ICALL_EXPORT MonoArray*
3733 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3737 static MonoClass *System_Reflection_PropertyInfo;
3738 MonoClass *startklass, *klass;
3744 gchar *propname = NULL;
3745 int (*compare_func) (const char *s1, const char *s2) = NULL;
3747 GHashTable *properties = NULL;
3748 MonoPtrArray tmp_array;
3750 MONO_ARCH_SAVE_REGS;
3752 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3754 if (!System_Reflection_PropertyInfo)
3755 System_Reflection_PropertyInfo = mono_class_from_name (
3756 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3758 domain = ((MonoObject *)type)->vtable->domain;
3759 if (type->type->byref)
3760 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3761 klass = startklass = mono_class_from_mono_type (type->type);
3764 propname = mono_string_to_utf8 (name);
3765 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3768 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3770 mono_class_setup_vtable (klass);
3771 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3775 while ((prop = mono_class_get_properties (klass, &iter))) {
3781 flags = method->flags;
3784 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3785 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3786 if (bflags & BFLAGS_Public)
3788 } else if (bflags & BFLAGS_NonPublic) {
3789 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3790 property_accessor_nonpublic(prop->set, startklass == klass)) {
3797 if (flags & METHOD_ATTRIBUTE_STATIC) {
3798 if (bflags & BFLAGS_Static)
3799 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3802 if (bflags & BFLAGS_Instance)
3811 if (compare_func (propname, prop->name))
3815 if (g_hash_table_lookup (properties, prop))
3818 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3820 g_hash_table_insert (properties, prop, prop);
3822 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3825 g_hash_table_destroy (properties);
3828 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3829 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3830 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3832 mono_ptr_array_destroy (tmp_array);
3838 g_hash_table_destroy (properties);
3841 mono_ptr_array_destroy (tmp_array);
3843 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3844 ex = mono_class_get_exception_for_failure (klass);
3846 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3847 mono_loader_clear_error ();
3849 mono_raise_exception (ex);
3853 ICALL_EXPORT MonoReflectionEvent *
3854 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3857 MonoClass *klass, *startklass;
3862 int (*compare_func) (const char *s1, const char *s2);
3864 MONO_ARCH_SAVE_REGS;
3866 event_name = mono_string_to_utf8 (name);
3867 if (type->type->byref)
3869 klass = startklass = mono_class_from_mono_type (type->type);
3870 domain = mono_object_domain (type);
3872 mono_class_init_or_throw (klass);
3874 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3876 if (klass->exception_type != MONO_EXCEPTION_NONE)
3877 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3880 while ((event = mono_class_get_events (klass, &iter))) {
3881 if (compare_func (event->name, event_name))
3884 method = event->add;
3886 method = event->remove;
3888 method = event->raise;
3890 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3891 if (!(bflags & BFLAGS_Public))
3894 if (!(bflags & BFLAGS_NonPublic))
3896 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3900 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3901 if (!(bflags & BFLAGS_Static))
3903 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3906 if (!(bflags & BFLAGS_Instance))
3910 if (!(bflags & BFLAGS_NonPublic))
3913 g_free (event_name);
3914 return mono_event_get_object (domain, startklass, event);
3917 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3920 g_free (event_name);
3924 ICALL_EXPORT MonoArray*
3925 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3929 static MonoClass *System_Reflection_EventInfo;
3930 MonoClass *startklass, *klass;
3937 MonoPtrArray tmp_array;
3939 MONO_ARCH_SAVE_REGS;
3941 mono_ptr_array_init (tmp_array, 4);
3943 if (!System_Reflection_EventInfo)
3944 System_Reflection_EventInfo = mono_class_from_name (
3945 mono_defaults.corlib, "System.Reflection", "EventInfo");
3947 domain = mono_object_domain (type);
3948 if (type->type->byref)
3949 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3950 klass = startklass = mono_class_from_mono_type (type->type);
3953 mono_class_setup_vtable (klass);
3954 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3958 while ((event = mono_class_get_events (klass, &iter))) {
3960 method = event->add;
3962 method = event->remove;
3964 method = event->raise;
3966 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3967 if (bflags & BFLAGS_Public)
3969 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3970 if (bflags & BFLAGS_NonPublic)
3975 if (bflags & BFLAGS_NonPublic)
3981 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3982 if (bflags & BFLAGS_Static)
3983 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3986 if (bflags & BFLAGS_Instance)
3991 if (bflags & BFLAGS_Instance)
3995 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
3997 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4000 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4002 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4003 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4005 mono_ptr_array_destroy (tmp_array);
4010 mono_ptr_array_destroy (tmp_array);
4011 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4012 ex = mono_class_get_exception_for_failure (klass);
4014 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4015 mono_loader_clear_error ();
4017 mono_raise_exception (ex);
4021 ICALL_EXPORT MonoReflectionType *
4022 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4030 MONO_ARCH_SAVE_REGS;
4033 mono_raise_exception (mono_get_exception_argument_null ("name"));
4035 domain = ((MonoObject *)type)->vtable->domain;
4036 if (type->type->byref)
4038 klass = mono_class_from_mono_type (type->type);
4040 str = mono_string_to_utf8 (name);
4043 if (klass->exception_type != MONO_EXCEPTION_NONE)
4044 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4047 * If a nested type is generic, return its generic type definition.
4048 * Note that this means that the return value is essentially a
4049 * nested type of the generic type definition of @klass.
4051 * A note in MSDN claims that a generic type definition can have
4052 * nested types that aren't generic. In any case, the container of that
4053 * nested type would be the generic type definition.
4055 if (klass->generic_class)
4056 klass = klass->generic_class->container_class;
4059 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4061 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4062 if (bflags & BFLAGS_Public)
4065 if (bflags & BFLAGS_NonPublic)
4070 if (strcmp (nested->name, str) == 0){
4072 return mono_type_get_object (domain, &nested->byval_arg);
4075 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4081 ICALL_EXPORT MonoArray*
4082 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4091 MonoPtrArray tmp_array;
4093 MONO_ARCH_SAVE_REGS;
4095 domain = ((MonoObject *)type)->vtable->domain;
4096 if (type->type->byref)
4097 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4098 klass = mono_class_from_mono_type (type->type);
4101 * If a nested type is generic, return its generic type definition.
4102 * Note that this means that the return value is essentially the set
4103 * of nested types of the generic type definition of @klass.
4105 * A note in MSDN claims that a generic type definition can have
4106 * nested types that aren't generic. In any case, the container of that
4107 * nested type would be the generic type definition.
4109 if (klass->generic_class)
4110 klass = klass->generic_class->container_class;
4112 mono_ptr_array_init (tmp_array, 1);
4114 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4116 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4117 if (bflags & BFLAGS_Public)
4120 if (bflags & BFLAGS_NonPublic)
4125 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4126 mono_ptr_array_append (tmp_array, member);
4129 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4131 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4132 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4134 mono_ptr_array_destroy (tmp_array);
4139 ICALL_EXPORT MonoReflectionType*
4140 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4143 MonoType *type = NULL;
4144 MonoTypeNameParse info;
4145 gboolean type_resolve;
4147 MONO_ARCH_SAVE_REGS;
4149 /* On MS.NET, this does not fire a TypeResolve event */
4150 type_resolve = TRUE;
4151 str = mono_string_to_utf8 (name);
4152 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4153 if (!mono_reflection_parse_type (str, &info)) {
4155 mono_reflection_free_type_info (&info);
4156 if (throwOnError) /* uhm: this is a parse error, though... */
4157 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4158 /*g_print ("failed parse\n");*/
4162 if (info.assembly.name) {
4164 mono_reflection_free_type_info (&info);
4166 /* 1.0 and 2.0 throw different exceptions */
4167 if (mono_defaults.generic_ilist_class)
4168 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4170 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4175 if (module != NULL) {
4177 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4182 if (assembly->assembly->dynamic) {
4183 /* Enumerate all modules */
4184 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4188 if (abuilder->modules) {
4189 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4190 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4191 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4197 if (!type && abuilder->loaded_modules) {
4198 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4199 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4200 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4207 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4209 mono_reflection_free_type_info (&info);
4211 MonoException *e = NULL;
4214 e = mono_get_exception_type_load (name, NULL);
4216 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4217 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4219 mono_loader_clear_error ();
4222 mono_raise_exception (e);
4225 } else if (mono_loader_get_last_error ()) {
4227 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4228 mono_loader_clear_error ();
4231 if (type->type == MONO_TYPE_CLASS) {
4232 MonoClass *klass = mono_type_get_class (type);
4234 if (mono_is_security_manager_active () && !klass->exception_type)
4235 /* Some security problems are detected during generic vtable construction */
4236 mono_class_setup_vtable (klass);
4237 /* need to report exceptions ? */
4238 if (throwOnError && klass->exception_type) {
4239 /* report SecurityException (or others) that occured when loading the assembly */
4240 MonoException *exc = mono_class_get_exception_for_failure (klass);
4241 mono_loader_clear_error ();
4242 mono_raise_exception (exc);
4243 } else if (klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4248 /* g_print ("got it\n"); */
4249 return mono_type_get_object (mono_object_domain (assembly), type);
4253 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4256 gchar *shadow_ini_file;
4259 /* Check for shadow-copied assembly */
4260 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4261 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4263 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4264 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4270 g_free (shadow_ini_file);
4271 if (content != NULL) {
4274 *filename = content;
4281 ICALL_EXPORT MonoString *
4282 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4284 MonoDomain *domain = mono_object_domain (assembly);
4285 MonoAssembly *mass = assembly->assembly;
4286 MonoString *res = NULL;
4291 MONO_ARCH_SAVE_REGS;
4293 if (g_path_is_absolute (mass->image->name)) {
4294 absolute = g_strdup (mass->image->name);
4295 dirname = g_path_get_dirname (absolute);
4297 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4298 dirname = g_strdup (mass->basedir);
4301 replace_shadow_path (domain, dirname, &absolute);
4306 for (i = strlen (absolute) - 1; i >= 0; i--)
4307 if (absolute [i] == '\\')
4312 uri = g_filename_to_uri (absolute, NULL, NULL);
4314 const char *prepend = "file://";
4316 if (*absolute == '/' && *(absolute + 1) == '/') {
4319 prepend = "file:///";
4322 uri = g_strconcat (prepend, absolute, NULL);
4326 res = mono_string_new (domain, uri);
4333 ICALL_EXPORT MonoBoolean
4334 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4336 MonoAssembly *mass = assembly->assembly;
4338 MONO_ARCH_SAVE_REGS;
4340 return mass->in_gac;
4343 ICALL_EXPORT MonoReflectionAssembly*
4344 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4348 MonoImageOpenStatus status;
4350 MONO_ARCH_SAVE_REGS;
4352 name = mono_string_to_utf8 (mname);
4353 res = mono_assembly_load_with_partial_name (name, &status);
4359 return mono_assembly_get_object (mono_domain_get (), res);
4362 ICALL_EXPORT MonoString *
4363 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4365 MonoDomain *domain = mono_object_domain (assembly);
4368 MONO_ARCH_SAVE_REGS;
4370 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4375 ICALL_EXPORT MonoBoolean
4376 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4378 MONO_ARCH_SAVE_REGS;
4380 return assembly->assembly->ref_only;
4383 ICALL_EXPORT MonoString *
4384 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4386 MonoDomain *domain = mono_object_domain (assembly);
4388 MONO_ARCH_SAVE_REGS;
4390 return mono_string_new (domain, assembly->assembly->image->version);
4393 ICALL_EXPORT MonoReflectionMethod*
4394 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4396 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4398 MONO_ARCH_SAVE_REGS;
4402 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4405 ICALL_EXPORT MonoReflectionModule*
4406 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4408 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4411 ICALL_EXPORT MonoArray*
4412 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4414 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4415 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4419 MONO_ARCH_SAVE_REGS;
4421 for (i = 0; i < table->rows; ++i) {
4422 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4423 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4429 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4431 static MonoClass *System_Version = NULL;
4432 static MonoMethod *create_version = NULL;
4436 if (!System_Version) {
4437 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4438 g_assert (System_Version);
4441 if (!create_version) {
4442 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4443 create_version = mono_method_desc_search_in_class (desc, System_Version);
4444 g_assert (create_version);
4445 mono_method_desc_free (desc);
4451 args [3] = &revision;
4452 result = mono_object_new (domain, System_Version);
4453 mono_runtime_invoke (create_version, result, args, NULL);
4458 ICALL_EXPORT MonoArray*
4459 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4461 static MonoClass *System_Reflection_AssemblyName;
4463 MonoDomain *domain = mono_object_domain (assembly);
4465 static MonoMethod *create_culture = NULL;
4466 MonoImage *image = assembly->assembly->image;
4469 MONO_ARCH_SAVE_REGS;
4471 if (!System_Reflection_AssemblyName)
4472 System_Reflection_AssemblyName = mono_class_from_name (
4473 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4475 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4478 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4480 if (count > 0 && !create_culture) {
4481 MonoMethodDesc *desc = mono_method_desc_new (
4482 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4483 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4484 g_assert (create_culture);
4485 mono_method_desc_free (desc);
4488 for (i = 0; i < count; i++) {
4489 MonoReflectionAssemblyName *aname;
4490 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4492 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4494 aname = (MonoReflectionAssemblyName *) mono_object_new (
4495 domain, System_Reflection_AssemblyName);
4497 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4499 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4500 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4501 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4502 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4503 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4504 aname->versioncompat = 1; /* SameMachine (default) */
4505 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4506 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4508 if (create_culture) {
4510 MonoBoolean assembly_ref = 1;
4511 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4512 args [1] = &assembly_ref;
4513 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4516 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4517 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4518 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4520 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4521 /* public key token isn't copied - the class library will
4522 automatically generate it from the public key if required */
4523 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4524 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4526 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4527 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4530 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4533 /* note: this function doesn't return the codebase on purpose (i.e. it can
4534 be used under partial trust as path information isn't present). */
4536 mono_array_setref (result, i, aname);
4547 foreach_namespace (const char* key, gconstpointer val, NameSpaceInfo *info)
4549 MonoString *name = mono_string_new (mono_object_domain (info->res), key);
4551 mono_array_setref (info->res, info->idx, name);
4555 ICALL_EXPORT MonoArray*
4556 ves_icall_System_Reflection_Assembly_GetNamespaces (MonoReflectionAssembly *assembly)
4558 MonoImage *img = assembly->assembly->image;
4563 MONO_ARCH_SAVE_REGS;
4565 mono_image_lock (img);
4566 mono_image_init_name_cache (img);
4569 len = g_hash_table_size (img->name_cache);
4570 mono_image_unlock (img);
4572 /*we can't create objects holding the image lock */
4573 res = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, len);
4575 mono_image_lock (img);
4576 /*len might have changed, create a new array*/
4577 if (len != g_hash_table_size (img->name_cache))
4582 g_hash_table_foreach (img->name_cache, (GHFunc)foreach_namespace, &info);
4583 mono_image_unlock (img);
4588 /* move this in some file in mono/util/ */
4590 g_concat_dir_and_file (const char *dir, const char *file)
4592 g_return_val_if_fail (dir != NULL, NULL);
4593 g_return_val_if_fail (file != NULL, NULL);
4596 * If the directory name doesn't have a / on the end, we need
4597 * to add one so we get a proper path to the file
4599 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4600 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4602 return g_strconcat (dir, file, NULL);
4606 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4608 char *n = mono_string_to_utf8 (name);
4609 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4611 guint32 cols [MONO_MANIFEST_SIZE];
4612 guint32 impl, file_idx;
4616 MONO_ARCH_SAVE_REGS;
4618 for (i = 0; i < table->rows; ++i) {
4619 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4620 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4621 if (strcmp (val, n) == 0)
4625 if (i == table->rows)
4628 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4631 * this code should only be called after obtaining the
4632 * ResourceInfo and handling the other cases.
4634 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4635 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4637 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4642 module = assembly->assembly->image;
4644 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4646 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4649 ICALL_EXPORT gboolean
4650 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4652 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4654 guint32 cols [MONO_MANIFEST_SIZE];
4655 guint32 file_cols [MONO_FILE_SIZE];
4659 MONO_ARCH_SAVE_REGS;
4661 n = mono_string_to_utf8 (name);
4662 for (i = 0; i < table->rows; ++i) {
4663 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4664 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4665 if (strcmp (val, n) == 0)
4669 if (i == table->rows)
4672 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4673 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4676 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4677 case MONO_IMPLEMENTATION_FILE:
4678 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4679 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4680 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4681 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4682 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4683 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4686 info->location = RESOURCE_LOCATION_EMBEDDED;
4689 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4690 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4691 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4692 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4693 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4694 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4696 mono_raise_exception (ex);
4698 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4700 /* Obtain info recursively */
4701 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4702 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4705 case MONO_IMPLEMENTATION_EXP_TYPE:
4706 g_assert_not_reached ();
4714 ICALL_EXPORT MonoObject*
4715 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4717 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4718 MonoArray *result = NULL;
4723 MONO_ARCH_SAVE_REGS;
4725 /* check hash if needed */
4727 n = mono_string_to_utf8 (name);
4728 for (i = 0; i < table->rows; ++i) {
4729 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4730 if (strcmp (val, n) == 0) {
4733 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4734 fn = mono_string_new (mono_object_domain (assembly), n);
4736 return (MonoObject*)fn;
4744 for (i = 0; i < table->rows; ++i) {
4745 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4749 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4752 for (i = 0; i < table->rows; ++i) {
4753 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4754 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4755 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4756 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4761 return (MonoObject*)result;
4764 ICALL_EXPORT MonoArray*
4765 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4767 MonoDomain *domain = mono_domain_get();
4770 int i, j, file_count = 0;
4771 MonoImage **modules;
4772 guint32 module_count, real_module_count;
4773 MonoTableInfo *table;
4774 guint32 cols [MONO_FILE_SIZE];
4775 MonoImage *image = assembly->assembly->image;
4777 g_assert (image != NULL);
4778 g_assert (!assembly->assembly->dynamic);
4780 table = &image->tables [MONO_TABLE_FILE];
4781 file_count = table->rows;
4783 modules = image->modules;
4784 module_count = image->module_count;
4786 real_module_count = 0;
4787 for (i = 0; i < module_count; ++i)
4789 real_module_count ++;
4791 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4792 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4794 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4796 for (i = 0; i < module_count; ++i)
4798 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4802 for (i = 0; i < file_count; ++i, ++j) {
4803 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4804 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4805 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4807 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4809 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4810 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4812 mono_array_setref (res, j, mono_module_get_object (domain, m));
4819 ICALL_EXPORT MonoReflectionMethod*
4820 ves_icall_GetCurrentMethod (void)
4822 MonoMethod *m = mono_method_get_last_managed ();
4824 while (m->is_inflated)
4825 m = ((MonoMethodInflated*)m)->declaring;
4827 return mono_method_get_object (mono_domain_get (), m, NULL);
4832 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4835 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4836 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4837 //method is inflated, we should inflate it on the other class
4838 MonoGenericContext ctx;
4839 ctx.method_inst = inflated->context.method_inst;
4840 ctx.class_inst = inflated->context.class_inst;
4841 if (klass->generic_class)
4842 ctx.class_inst = klass->generic_class->context.class_inst;
4843 else if (klass->generic_container)
4844 ctx.class_inst = klass->generic_container->context.class_inst;
4845 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4848 mono_class_setup_methods (method->klass);
4849 if (method->klass->exception_type)
4851 for (i = 0; i < method->klass->method.count; ++i) {
4852 if (method->klass->methods [i] == method) {
4857 mono_class_setup_methods (klass);
4858 if (klass->exception_type)
4860 g_assert (offset >= 0 && offset < klass->method.count);
4861 return klass->methods [offset];
4864 ICALL_EXPORT MonoReflectionMethod*
4865 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4869 klass = mono_class_from_mono_type (type);
4870 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4872 if (method->klass != klass) {
4873 method = mono_method_get_equivalent_method (method, klass);
4878 klass = method->klass;
4879 return mono_method_get_object (mono_domain_get (), method, klass);
4882 ICALL_EXPORT MonoReflectionMethod*
4883 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4885 return mono_method_get_object (mono_domain_get (), method, NULL);
4888 ICALL_EXPORT MonoReflectionMethodBody*
4889 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4891 return mono_method_body_get_object (mono_domain_get (), method);
4894 ICALL_EXPORT MonoReflectionAssembly*
4895 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4897 MonoMethod *dest = NULL;
4899 MONO_ARCH_SAVE_REGS;
4901 mono_stack_walk_no_il (get_executing, &dest);
4902 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4906 ICALL_EXPORT MonoReflectionAssembly*
4907 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4909 MonoDomain* domain = mono_domain_get ();
4911 MONO_ARCH_SAVE_REGS;
4913 if (!domain->entry_assembly)
4916 return mono_assembly_get_object (domain, domain->entry_assembly);
4919 ICALL_EXPORT MonoReflectionAssembly*
4920 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4925 MONO_ARCH_SAVE_REGS;
4928 mono_stack_walk_no_il (get_executing, &dest);
4930 mono_stack_walk_no_il (get_caller, &dest);
4933 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4936 ICALL_EXPORT MonoString *
4937 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4938 gboolean assembly_qualified)
4940 MonoDomain *domain = mono_object_domain (object);
4941 MonoTypeNameFormat format;
4946 format = assembly_qualified ?
4947 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4948 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4950 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4952 name = mono_type_get_name_full (object->type, format);
4956 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4961 res = mono_string_new (domain, name);
4968 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4970 MonoClass *klass = mono_class_from_mono_type (this->type);
4971 mono_class_init_or_throw (klass);
4972 return mono_security_core_clr_class_level (klass);
4976 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4978 static MonoMethod *create_culture = NULL;
4981 const char *pkey_ptr;
4983 MonoBoolean assembly_ref = 0;
4985 MONO_ARCH_SAVE_REGS;
4987 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4988 aname->major = name->major;
4989 aname->minor = name->minor;
4990 aname->build = name->build;
4991 aname->flags = name->flags;
4992 aname->revision = name->revision;
4993 aname->hashalg = name->hash_alg;
4994 aname->versioncompat = 1; /* SameMachine (default) */
4995 aname->processor_architecture = name->arch;
4997 if (by_default_version)
4998 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
5001 if (absolute != NULL && *absolute != '\0') {
5002 const gchar *prepend = "file://";
5005 codebase = g_strdup (absolute);
5010 for (i = strlen (codebase) - 1; i >= 0; i--)
5011 if (codebase [i] == '\\')
5014 if (*codebase == '/' && *(codebase + 1) == '/') {
5017 prepend = "file:///";
5021 result = g_strconcat (prepend, codebase, NULL);
5027 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5031 if (!create_culture) {
5032 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5033 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5034 g_assert (create_culture);
5035 mono_method_desc_free (desc);
5038 if (name->culture) {
5039 args [0] = mono_string_new (domain, name->culture);
5040 args [1] = &assembly_ref;
5041 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5044 if (name->public_key) {
5045 pkey_ptr = (char*)name->public_key;
5046 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5048 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5049 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5050 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5051 } else if (default_publickey) {
5052 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5053 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5056 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5057 if (name->public_key_token [0]) {
5061 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5062 p = mono_array_addr (aname->keyToken, char, 0);
5064 for (i = 0, j = 0; i < 8; i++) {
5065 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5066 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5069 } else if (default_token) {
5070 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5074 ICALL_EXPORT MonoString *
5075 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5077 MonoDomain *domain = mono_object_domain (assembly);
5078 MonoAssembly *mass = assembly->assembly;
5082 name = mono_stringify_assembly_name (&mass->aname);
5083 res = mono_string_new (domain, name);
5090 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5093 MonoAssembly *mass = assembly->assembly;
5095 MONO_ARCH_SAVE_REGS;
5097 if (g_path_is_absolute (mass->image->name)) {
5098 fill_reflection_assembly_name (mono_object_domain (assembly),
5099 aname, &mass->aname, mass->image->name, TRUE,
5103 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5105 fill_reflection_assembly_name (mono_object_domain (assembly),
5106 aname, &mass->aname, absolute, TRUE, TRUE,
5113 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5116 MonoImageOpenStatus status = MONO_IMAGE_OK;
5119 MonoAssemblyName name;
5122 MONO_ARCH_SAVE_REGS;
5124 filename = mono_string_to_utf8 (fname);
5126 dirname = g_path_get_dirname (filename);
5127 replace_shadow_path (mono_domain_get (), dirname, &filename);
5130 image = mono_image_open (filename, &status);
5136 if (status == MONO_IMAGE_IMAGE_INVALID)
5137 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5139 exc = mono_get_exception_file_not_found2 (NULL, fname);
5140 mono_raise_exception (exc);
5143 res = mono_assembly_fill_assembly_name (image, &name);
5145 mono_image_close (image);
5147 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5150 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5154 mono_image_close (image);
5157 ICALL_EXPORT MonoBoolean
5158 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5159 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5161 MonoBoolean result = FALSE;
5162 MonoDeclSecurityEntry entry;
5164 /* SecurityAction.RequestMinimum */
5165 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5166 *minimum = entry.blob;
5167 *minLength = entry.size;
5170 /* SecurityAction.RequestOptional */
5171 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5172 *optional = entry.blob;
5173 *optLength = entry.size;
5176 /* SecurityAction.RequestRefuse */
5177 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5178 *refused = entry.blob;
5179 *refLength = entry.size;
5187 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5191 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5193 guint32 attrs, visibility;
5195 /* we start the count from 1 because we skip the special type <Module> */
5198 for (i = 1; i < tdef->rows; ++i) {
5199 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5200 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5201 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5205 count = tdef->rows - 1;
5207 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5208 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5210 for (i = 1; i < tdef->rows; ++i) {
5211 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5212 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5213 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5214 klass = mono_class_get (image, (i + 1) | MONO_TOKEN_TYPE_DEF);
5216 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5218 MonoLoaderError *error;
5221 error = mono_loader_get_last_error ();
5222 g_assert (error != NULL);
5224 ex = mono_loader_error_prepare_exception (error);
5225 mono_array_setref (*exceptions, count, ex);
5227 if (mono_loader_get_last_error ())
5228 mono_loader_clear_error ();
5236 ICALL_EXPORT MonoArray*
5237 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5239 MonoArray *res = NULL;
5240 MonoArray *exceptions = NULL;
5241 MonoImage *image = NULL;
5242 MonoTableInfo *table = NULL;
5245 int i, len, ex_count;
5247 MONO_ARCH_SAVE_REGS;
5249 domain = mono_object_domain (assembly);
5251 g_assert (!assembly->assembly->dynamic);
5252 image = assembly->assembly->image;
5253 table = &image->tables [MONO_TABLE_FILE];
5254 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5256 /* Append data from all modules in the assembly */
5257 for (i = 0; i < table->rows; ++i) {
5258 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5259 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5262 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5263 /* Append the new types to the end of the array */
5264 if (mono_array_length (res2) > 0) {
5266 MonoArray *res3, *ex3;
5268 len1 = mono_array_length (res);
5269 len2 = mono_array_length (res2);
5271 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5272 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5273 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5276 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5277 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5278 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5285 /* the ReflectionTypeLoadException must have all the types (Types property),
5286 * NULL replacing types which throws an exception. The LoaderException must
5287 * contain all exceptions for NULL items.
5290 len = mono_array_length (res);
5293 for (i = 0; i < len; i++) {
5294 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5298 klass = mono_type_get_class (t->type);
5299 if ((klass != NULL) && klass->exception_type) {
5300 /* keep the class in the list */
5301 list = g_list_append (list, klass);
5302 /* and replace Type with NULL */
5303 mono_array_setref (res, i, NULL);
5310 if (list || ex_count) {
5312 MonoException *exc = NULL;
5313 MonoArray *exl = NULL;
5314 int j, length = g_list_length (list) + ex_count;
5316 mono_loader_clear_error ();
5318 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5319 /* Types for which mono_class_get () succeeded */
5320 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5321 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5322 mono_array_setref (exl, i, exc);
5324 /* Types for which it don't */
5325 for (j = 0; j < mono_array_length (exceptions); ++j) {
5326 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5328 g_assert (i < length);
5329 mono_array_setref (exl, i, exc);
5336 exc = mono_get_exception_reflection_type_load (res, exl);
5337 mono_loader_clear_error ();
5338 mono_raise_exception (exc);
5344 ICALL_EXPORT gboolean
5345 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5347 MonoAssemblyName aname;
5348 MonoDomain *domain = mono_object_domain (name);
5350 gboolean is_version_defined;
5351 gboolean is_token_defined;
5353 aname.public_key = NULL;
5354 val = mono_string_to_utf8 (assname);
5355 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5356 g_free ((guint8*) aname.public_key);
5361 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5362 FALSE, is_token_defined);
5364 mono_assembly_name_free (&aname);
5365 g_free ((guint8*) aname.public_key);
5371 ICALL_EXPORT MonoReflectionType*
5372 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5374 MonoDomain *domain = mono_object_domain (module);
5377 MONO_ARCH_SAVE_REGS;
5379 g_assert (module->image);
5381 if (module->image->dynamic && ((MonoDynamicImage*)(module->image))->initial_image)
5382 /* These images do not have a global type */
5385 klass = mono_class_get (module->image, 1 | MONO_TOKEN_TYPE_DEF);
5386 return mono_type_get_object (domain, &klass->byval_arg);
5390 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5392 /*if (module->image)
5393 mono_image_close (module->image);*/
5396 ICALL_EXPORT MonoString*
5397 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5399 MonoDomain *domain = mono_object_domain (module);
5401 MONO_ARCH_SAVE_REGS;
5403 g_assert (module->image);
5404 return mono_string_new (domain, module->image->guid);
5407 ICALL_EXPORT gpointer
5408 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5411 if (module->image && module->image->is_module_handle)
5412 return module->image->raw_data;
5415 return (gpointer) (-1);
5419 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5421 if (image->dynamic) {
5422 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5423 *pe_kind = dyn->pe_kind;
5424 *machine = dyn->machine;
5427 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5428 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5433 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5435 return (image->md_version_major << 16) | (image->md_version_minor);
5438 ICALL_EXPORT MonoArray*
5439 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5441 MonoArray *exceptions;
5444 MONO_ARCH_SAVE_REGS;
5447 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5449 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5450 for (i = 0; i < mono_array_length (exceptions); ++i) {
5451 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5453 mono_raise_exception (ex);
5460 mono_memberref_is_method (MonoImage *image, guint32 token)
5462 if (!image->dynamic) {
5463 guint32 cols [MONO_MEMBERREF_SIZE];
5465 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5466 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5467 mono_metadata_decode_blob_size (sig, &sig);
5468 return (*sig != 0x6);
5470 MonoClass *handle_class;
5472 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5475 return mono_defaults.methodhandle_class == handle_class;
5480 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5483 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5484 mono_array_addr (type_args, MonoType*, 0));
5486 context->class_inst = NULL;
5488 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5489 mono_array_addr (method_args, MonoType*, 0));
5491 context->method_inst = NULL;
5494 ICALL_EXPORT MonoType*
5495 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5498 int table = mono_metadata_token_table (token);
5499 int index = mono_metadata_token_index (token);
5500 MonoGenericContext context;
5502 *error = ResolveTokenError_Other;
5504 /* Validate token */
5505 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5506 (table != MONO_TABLE_TYPESPEC)) {
5507 *error = ResolveTokenError_BadTable;
5511 if (image->dynamic) {
5512 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5513 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5514 return klass ? &klass->byval_arg : NULL;
5517 init_generic_context_from_args (&context, type_args, method_args);
5518 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5519 return klass ? &klass->byval_arg : NULL;
5522 if ((index <= 0) || (index > image->tables [table].rows)) {
5523 *error = ResolveTokenError_OutOfRange;
5527 init_generic_context_from_args (&context, type_args, method_args);
5528 klass = mono_class_get_full (image, token, &context);
5530 if (mono_loader_get_last_error ())
5531 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5534 return &klass->byval_arg;
5539 ICALL_EXPORT MonoMethod*
5540 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5542 int table = mono_metadata_token_table (token);
5543 int index = mono_metadata_token_index (token);
5544 MonoGenericContext context;
5547 *error = ResolveTokenError_Other;
5549 /* Validate token */
5550 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5551 (table != MONO_TABLE_MEMBERREF)) {
5552 *error = ResolveTokenError_BadTable;
5556 if (image->dynamic) {
5557 if (table == MONO_TABLE_METHOD)
5558 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5560 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5561 *error = ResolveTokenError_BadTable;
5565 init_generic_context_from_args (&context, type_args, method_args);
5566 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5569 if ((index <= 0) || (index > image->tables [table].rows)) {
5570 *error = ResolveTokenError_OutOfRange;
5573 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5574 *error = ResolveTokenError_BadTable;
5578 init_generic_context_from_args (&context, type_args, method_args);
5579 method = mono_get_method_full (image, token, NULL, &context);
5581 if (mono_loader_get_last_error ())
5582 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5587 ICALL_EXPORT MonoString*
5588 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5590 int index = mono_metadata_token_index (token);
5592 *error = ResolveTokenError_Other;
5594 /* Validate token */
5595 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5596 *error = ResolveTokenError_BadTable;
5601 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5603 if ((index <= 0) || (index >= image->heap_us.size)) {
5604 *error = ResolveTokenError_OutOfRange;
5608 /* FIXME: What to do if the index points into the middle of a string ? */
5610 return mono_ldstr (mono_domain_get (), image, index);
5613 ICALL_EXPORT MonoClassField*
5614 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5617 int table = mono_metadata_token_table (token);
5618 int index = mono_metadata_token_index (token);
5619 MonoGenericContext context;
5620 MonoClassField *field;
5622 *error = ResolveTokenError_Other;
5624 /* Validate token */
5625 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5626 *error = ResolveTokenError_BadTable;
5630 if (image->dynamic) {
5631 if (table == MONO_TABLE_FIELD)
5632 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5634 if (mono_memberref_is_method (image, token)) {
5635 *error = ResolveTokenError_BadTable;
5639 init_generic_context_from_args (&context, type_args, method_args);
5640 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5643 if ((index <= 0) || (index > image->tables [table].rows)) {
5644 *error = ResolveTokenError_OutOfRange;
5647 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5648 *error = ResolveTokenError_BadTable;
5652 init_generic_context_from_args (&context, type_args, method_args);
5653 field = mono_field_from_token (image, token, &klass, &context);
5655 if (mono_loader_get_last_error ())
5656 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5662 ICALL_EXPORT MonoObject*
5663 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5665 int table = mono_metadata_token_table (token);
5667 *error = ResolveTokenError_Other;
5670 case MONO_TABLE_TYPEDEF:
5671 case MONO_TABLE_TYPEREF:
5672 case MONO_TABLE_TYPESPEC: {
5673 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5675 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5679 case MONO_TABLE_METHOD:
5680 case MONO_TABLE_METHODSPEC: {
5681 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5683 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5687 case MONO_TABLE_FIELD: {
5688 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5690 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5694 case MONO_TABLE_MEMBERREF:
5695 if (mono_memberref_is_method (image, token)) {
5696 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5698 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5703 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5705 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5712 *error = ResolveTokenError_BadTable;
5718 ICALL_EXPORT MonoArray*
5719 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5721 int table = mono_metadata_token_table (token);
5722 int idx = mono_metadata_token_index (token);
5723 MonoTableInfo *tables = image->tables;
5728 *error = ResolveTokenError_OutOfRange;
5730 /* FIXME: Support other tables ? */
5731 if (table != MONO_TABLE_STANDALONESIG)
5737 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5740 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5742 ptr = mono_metadata_blob_heap (image, sig);
5743 len = mono_metadata_decode_blob_size (ptr, &ptr);
5745 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5746 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5750 ICALL_EXPORT MonoReflectionType*
5751 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5754 int isbyref = 0, rank;
5755 char *str = mono_string_to_utf8 (smodifiers);
5758 MONO_ARCH_SAVE_REGS;
5760 klass = mono_class_from_mono_type (tb->type.type);
5762 /* logic taken from mono_reflection_parse_type(): keep in sync */
5766 if (isbyref) { /* only one level allowed by the spec */
5773 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5776 klass = mono_ptr_class_get (&klass->byval_arg);
5777 mono_class_init (klass);
5788 else if (*p != '*') { /* '*' means unknown lower bound */
5799 klass = mono_array_class_get (klass, rank);
5800 mono_class_init (klass);
5807 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5810 ICALL_EXPORT MonoBoolean
5811 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5816 MONO_ARCH_SAVE_REGS;
5819 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5825 check_for_invalid_type (MonoClass *klass)
5829 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5832 name = mono_type_get_full_name (klass);
5833 str = mono_string_new (mono_domain_get (), name);
5835 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5838 ICALL_EXPORT MonoReflectionType *
5839 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5841 MonoClass *klass, *aklass;
5843 MONO_ARCH_SAVE_REGS;
5845 klass = mono_class_from_mono_type (type->type);
5846 check_for_invalid_type (klass);
5848 if (rank == 0) //single dimentional array
5849 aklass = mono_array_class_get (klass, 1);
5851 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5853 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5856 ICALL_EXPORT MonoReflectionType *
5857 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5861 MONO_ARCH_SAVE_REGS;
5863 klass = mono_class_from_mono_type (type->type);
5864 mono_class_init_or_throw (klass);
5865 check_for_invalid_type (klass);
5867 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5870 ICALL_EXPORT MonoReflectionType *
5871 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5873 MonoClass *klass, *pklass;
5875 klass = mono_class_from_mono_type (type->type);
5876 mono_class_init_or_throw (klass);
5877 check_for_invalid_type (klass);
5879 pklass = mono_ptr_class_get (type->type);
5881 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5884 ICALL_EXPORT MonoObject *
5885 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5886 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5888 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5889 MonoObject *delegate;
5891 MonoMethod *method = info->method;
5893 MONO_ARCH_SAVE_REGS;
5895 mono_class_init_or_throw (delegate_class);
5897 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5899 if (mono_security_get_mode () == MONO_SECURITY_MODE_CORE_CLR) {
5900 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5904 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5906 if (method->dynamic) {
5907 /* Creating a trampoline would leak memory */
5908 func = mono_compile_method (method);
5910 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5911 method = mono_object_get_virtual_method (target, method);
5912 func = mono_create_ftnptr (mono_domain_get (),
5913 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5916 mono_delegate_ctor_with_method (delegate, target, func, method);
5922 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5924 /* Reset the invoke impl to the default one */
5925 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5929 * Magic number to convert a time which is relative to
5930 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5932 #define EPOCH_ADJUST ((guint64)62135596800LL)
5935 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5937 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5940 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5942 convert_to_absolute_date(SYSTEMTIME *date)
5944 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5945 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5946 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5947 /* from the calendar FAQ */
5948 int a = (14 - date->wMonth) / 12;
5949 int y = date->wYear - a;
5950 int m = date->wMonth + 12 * a - 2;
5951 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5953 /* d is now the day of the week for the first of the month (0 == Sunday) */
5955 int day_of_week = date->wDayOfWeek;
5957 /* set day_in_month to the first day in the month which falls on day_of_week */
5958 int day_in_month = 1 + (day_of_week - d);
5959 if (day_in_month <= 0)
5962 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5963 date->wDay = day_in_month + (date->wDay - 1) * 7;
5964 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5971 * Return's the offset from GMT of a local time.
5973 * tm is a local time
5974 * t is the same local time as seconds.
5977 gmt_offset(struct tm *tm, time_t t)
5979 #if defined (HAVE_TM_GMTOFF)
5980 return tm->tm_gmtoff;
5985 g.tm_isdst = tm->tm_isdst;
5987 return (int)difftime(t, t2);
5992 * This is heavily based on zdump.c from glibc 2.2.
5994 * * data[0]: start of daylight saving time (in DateTime ticks).
5995 * * data[1]: end of daylight saving time (in DateTime ticks).
5996 * * data[2]: utcoffset (in TimeSpan ticks).
5997 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5998 * * name[0]: name of this timezone when not daylight saving.
5999 * * name[1]: name of this timezone when daylight saving.
6001 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
6002 * the class library allows years between 1 and 9999.
6004 * Returns true on success and zero on failure.
6006 ICALL_EXPORT guint32
6007 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
6010 MonoDomain *domain = mono_domain_get ();
6011 struct tm start, tt;
6015 int is_daylight = 0, day;
6018 MONO_ARCH_SAVE_REGS;
6020 MONO_CHECK_ARG_NULL (data);
6021 MONO_CHECK_ARG_NULL (names);
6023 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
6024 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
6027 * no info is better than crashing: we'll need our own tz data
6028 * to make this work properly, anyway. The range is probably
6029 * reduced to 1970 .. 2037 because that is what mktime is
6030 * guaranteed to support (we get into an infinite loop
6034 memset (&start, 0, sizeof (start));
6037 start.tm_year = year-1900;
6039 t = mktime (&start);
6041 if ((year < 1970) || (year > 2037) || (t == -1)) {
6043 tt = *localtime (&t);
6044 strftime (tzone, sizeof (tzone), "%Z", &tt);
6045 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6046 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6050 gmtoff = gmt_offset (&start, t);
6052 /* For each day of the year, calculate the tm_gmtoff. */
6053 for (day = 0; day < 365; day++) {
6056 tt = *localtime (&t);
6058 /* Daylight saving starts or ends here. */
6059 if (gmt_offset (&tt, t) != gmtoff) {
6063 /* Try to find the exact hour when daylight saving starts/ends. */
6067 tt1 = *localtime (&t1);
6068 } while (gmt_offset (&tt1, t1) != gmtoff);
6070 /* Try to find the exact minute when daylight saving starts/ends. */
6073 tt1 = *localtime (&t1);
6074 } while (gmt_offset (&tt1, t1) == gmtoff);
6076 strftime (tzone, sizeof (tzone), "%Z", &tt);
6078 /* Write data, if we're already in daylight saving, we're done. */
6080 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6081 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6087 memset (&end, 0, sizeof (end));
6088 end.tm_year = year-1900 + 1;
6093 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6094 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6095 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6096 mono_array_set ((*data), gint64, 1, ((gint64)te + EPOCH_ADJUST) * 10000000L);
6100 /* This is only set once when we enter daylight saving. */
6101 mono_array_set ((*data), gint64, 2, (gint64)gmtoff * 10000000L);
6102 mono_array_set ((*data), gint64, 3, (gint64)(gmt_offset (&tt, t) - gmtoff) * 10000000L);
6104 gmtoff = gmt_offset (&tt, t);
6109 strftime (tzone, sizeof (tzone), "%Z", &tt);
6110 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6111 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6112 mono_array_set ((*data), gint64, 0, 0);
6113 mono_array_set ((*data), gint64, 1, 0);
6114 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6115 mono_array_set ((*data), gint64, 3, 0);
6120 MonoDomain *domain = mono_domain_get ();
6121 TIME_ZONE_INFORMATION tz_info;
6126 tz_id = GetTimeZoneInformation (&tz_info);
6127 if (tz_id == TIME_ZONE_ID_INVALID)
6130 MONO_CHECK_ARG_NULL (data);
6131 MONO_CHECK_ARG_NULL (names);
6133 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6134 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6136 for (i = 0; i < 32; ++i)
6137 if (!tz_info.DaylightName [i])
6139 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6140 for (i = 0; i < 32; ++i)
6141 if (!tz_info.StandardName [i])
6143 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6145 if ((year <= 1601) || (year > 30827)) {
6147 * According to MSDN, the MS time functions can't handle dates outside
6153 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6154 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6155 tz_info.StandardDate.wYear = year;
6156 convert_to_absolute_date(&tz_info.StandardDate);
6157 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6162 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6163 tz_info.DaylightDate.wYear = year;
6164 convert_to_absolute_date(&tz_info.DaylightDate);
6165 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6170 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6172 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6173 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6179 ICALL_EXPORT gpointer
6180 ves_icall_System_Object_obj_address (MonoObject *this)
6182 MONO_ARCH_SAVE_REGS;
6189 static inline gint32
6190 mono_array_get_byte_length (MonoArray *array)
6196 klass = array->obj.vtable->klass;
6198 if (array->bounds == NULL)
6199 length = array->max_length;
6202 for (i = 0; i < klass->rank; ++ i)
6203 length *= array->bounds [i].length;
6206 switch (klass->element_class->byval_arg.type) {
6209 case MONO_TYPE_BOOLEAN:
6213 case MONO_TYPE_CHAR:
6221 return length * sizeof (gpointer);
6232 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6234 MONO_ARCH_SAVE_REGS;
6236 return mono_array_get_byte_length (array);
6240 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6242 MONO_ARCH_SAVE_REGS;
6244 return mono_array_get (array, gint8, idx);
6248 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6250 MONO_ARCH_SAVE_REGS;
6252 mono_array_set (array, gint8, idx, value);
6255 ICALL_EXPORT MonoBoolean
6256 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6258 guint8 *src_buf, *dest_buf;
6260 MONO_ARCH_SAVE_REGS;
6262 /* This is called directly from the class libraries without going through the managed wrapper */
6263 MONO_CHECK_ARG_NULL (src);
6264 MONO_CHECK_ARG_NULL (dest);
6266 /* watch out for integer overflow */
6267 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6270 src_buf = (guint8 *)src->vector + src_offset;
6271 dest_buf = (guint8 *)dest->vector + dest_offset;
6274 memcpy (dest_buf, src_buf, count);
6276 mono_gc_memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6281 #ifndef DISABLE_REMOTING
6282 ICALL_EXPORT MonoObject *
6283 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6285 MonoDomain *domain = mono_object_domain (this);
6287 MonoRealProxy *rp = ((MonoRealProxy *)this);
6288 MonoTransparentProxy *tp;
6292 MONO_ARCH_SAVE_REGS;
6294 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6295 tp = (MonoTransparentProxy*) res;
6297 MONO_OBJECT_SETREF (tp, rp, rp);
6298 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6299 klass = mono_class_from_mono_type (type);
6301 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6302 tp->remote_class = mono_remote_class (domain, class_name, klass);
6304 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6308 ICALL_EXPORT MonoReflectionType *
6309 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6311 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6315 /* System.Environment */
6318 ves_icall_System_Environment_get_UserName (void)
6320 MONO_ARCH_SAVE_REGS;
6322 /* using glib is more portable */
6323 return mono_string_new (mono_domain_get (), g_get_user_name ());
6327 ICALL_EXPORT MonoString *
6328 ves_icall_System_Environment_get_MachineName (void)
6330 #if defined (HOST_WIN32)
6335 len = MAX_COMPUTERNAME_LENGTH + 1;
6336 buf = g_new (gunichar2, len);
6339 if (GetComputerName (buf, (PDWORD) &len))
6340 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6344 #elif !defined(DISABLE_SOCKETS)
6348 if (gethostname (buf, sizeof (buf)) == 0)
6349 result = mono_string_new (mono_domain_get (), buf);
6355 return mono_string_new (mono_domain_get (), "mono");
6360 ves_icall_System_Environment_get_Platform (void)
6362 #if defined (TARGET_WIN32)
6365 #elif defined(__MACH__)
6368 // Notice that the value is hidden from user code, and only exposed
6369 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6370 // define and making assumptions based on Unix/128/4 values before there
6371 // was a MacOS define. Lots of code would assume that not-Unix meant
6372 // Windows, but in this case, it would be OSX.
6381 ICALL_EXPORT MonoString *
6382 ves_icall_System_Environment_get_NewLine (void)
6384 MONO_ARCH_SAVE_REGS;
6386 #if defined (HOST_WIN32)
6387 return mono_string_new (mono_domain_get (), "\r\n");
6389 return mono_string_new (mono_domain_get (), "\n");
6393 ICALL_EXPORT MonoString *
6394 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6399 MONO_ARCH_SAVE_REGS;
6404 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6405 value = g_getenv (utf8_name);
6412 return mono_string_new (mono_domain_get (), value);
6416 * There is no standard way to get at environ.
6419 #ifndef __MINGW32_VERSION
6420 #if defined(__APPLE__) && !defined (__arm__)
6421 /* Apple defines this in crt_externs.h but doesn't provide that header for
6422 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6423 * in fact exist on all implementations (so far)
6425 gchar ***_NSGetEnviron(void);
6426 #define environ (*_NSGetEnviron())
6434 ICALL_EXPORT MonoArray *
6435 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6446 env_strings = GetEnvironmentStrings();
6449 env_string = env_strings;
6450 while (*env_string != '\0') {
6451 /* weird case that MS seems to skip */
6452 if (*env_string != '=')
6454 while (*env_string != '\0')
6460 domain = mono_domain_get ();
6461 names = mono_array_new (domain, mono_defaults.string_class, n);
6465 env_string = env_strings;
6466 while (*env_string != '\0') {
6467 /* weird case that MS seems to skip */
6468 if (*env_string != '=') {
6469 equal_str = wcschr(env_string, '=');
6470 g_assert(equal_str);
6471 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6472 mono_array_setref (names, n, str);
6475 while (*env_string != '\0')
6480 FreeEnvironmentStrings (env_strings);
6492 MONO_ARCH_SAVE_REGS;
6495 for (e = environ; *e != 0; ++ e)
6498 domain = mono_domain_get ();
6499 names = mono_array_new (domain, mono_defaults.string_class, n);
6502 for (e = environ; *e != 0; ++ e) {
6503 parts = g_strsplit (*e, "=", 2);
6505 str = mono_string_new (domain, *parts);
6506 mono_array_setref (names, n, str);
6519 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6521 #if !GLIB_CHECK_VERSION(2,4,0)
6522 #define g_setenv(a,b,c) setenv(a,b,c)
6523 #define g_unsetenv(a) unsetenv(a)
6527 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6532 gunichar2 *utf16_name, *utf16_value;
6534 gchar *utf8_name, *utf8_value;
6537 MONO_ARCH_SAVE_REGS;
6540 utf16_name = mono_string_to_utf16 (name);
6541 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6542 SetEnvironmentVariable (utf16_name, NULL);
6543 g_free (utf16_name);
6547 utf16_value = mono_string_to_utf16 (value);
6549 SetEnvironmentVariable (utf16_name, utf16_value);
6551 g_free (utf16_name);
6552 g_free (utf16_value);
6554 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6556 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6557 g_unsetenv (utf8_name);
6562 utf8_value = mono_string_to_utf8_checked (value, &error);
6563 if (!mono_error_ok (&error)) {
6565 mono_error_raise_exception (&error);
6567 g_setenv (utf8_name, utf8_value, TRUE);
6570 g_free (utf8_value);
6575 ves_icall_System_Environment_Exit (int result)
6577 MONO_ARCH_SAVE_REGS;
6579 mono_threads_set_shutting_down ();
6581 mono_runtime_set_shutting_down ();
6583 /* This will kill the tp threads which cannot be suspended */
6584 mono_thread_pool_cleanup ();
6586 /* Suspend all managed threads since the runtime is going away */
6587 mono_thread_suspend_all_other_threads ();
6589 mono_runtime_quit ();
6591 /* we may need to do some cleanup here... */
6595 ICALL_EXPORT MonoString*
6596 ves_icall_System_Environment_GetGacPath (void)
6598 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6601 ICALL_EXPORT MonoString*
6602 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6604 #if defined (HOST_WIN32)
6605 #ifndef CSIDL_FLAG_CREATE
6606 #define CSIDL_FLAG_CREATE 0x8000
6609 WCHAR path [MAX_PATH];
6610 /* Create directory if no existing */
6611 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6615 return mono_string_new_utf16 (mono_domain_get (), path, len);
6618 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6620 return mono_string_new (mono_domain_get (), "");
6623 ICALL_EXPORT MonoArray *
6624 ves_icall_System_Environment_GetLogicalDrives (void)
6626 gunichar2 buf [256], *ptr, *dname;
6628 guint initial_size = 127, size = 128;
6631 MonoString *drivestr;
6632 MonoDomain *domain = mono_domain_get ();
6635 MONO_ARCH_SAVE_REGS;
6640 while (size > initial_size) {
6641 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6642 if (size > initial_size) {
6645 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6646 initial_size = size;
6660 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6665 while (*u16) { u16++; len ++; }
6666 drivestr = mono_string_new_utf16 (domain, dname, len);
6667 mono_array_setref (result, ndrives++, drivestr);
6677 ICALL_EXPORT MonoString *
6678 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6680 gunichar2 volume_name [MAX_PATH + 1];
6682 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6684 return mono_string_from_utf16 (volume_name);
6687 ICALL_EXPORT MonoString *
6688 ves_icall_System_Environment_InternalGetHome (void)
6690 MONO_ARCH_SAVE_REGS;
6692 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6695 static const char *encodings [] = {
6697 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6698 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6699 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6701 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6702 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6703 "x_unicode_2_0_utf_7",
6705 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6706 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6708 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6711 "unicodefffe", "utf_16be",
6718 * Returns the internal codepage, if the value of "int_code_page" is
6719 * 1 at entry, and we can not compute a suitable code page number,
6720 * returns the code page as a string
6722 ICALL_EXPORT MonoString*
6723 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6728 char *codepage = NULL;
6730 int want_name = *int_code_page;
6733 *int_code_page = -1;
6734 MONO_ARCH_SAVE_REGS;
6736 g_get_charset (&cset);
6737 c = codepage = strdup (cset);
6738 for (c = codepage; *c; c++){
6739 if (isascii (*c) && isalpha (*c))
6744 /* g_print ("charset: %s\n", cset); */
6746 /* handle some common aliases */
6749 for (i = 0; p != 0; ){
6750 if ((gssize) p < 7){
6752 p = encodings [++i];
6755 if (strcmp (p, codepage) == 0){
6756 *int_code_page = code;
6759 p = encodings [++i];
6762 if (strstr (codepage, "utf_8") != NULL)
6763 *int_code_page |= 0x10000000;
6766 if (want_name && *int_code_page == -1)
6767 return mono_string_new (mono_domain_get (), cset);
6772 ICALL_EXPORT MonoBoolean
6773 ves_icall_System_Environment_get_HasShutdownStarted (void)
6775 if (mono_runtime_is_shutting_down ())
6778 if (mono_domain_is_unloading (mono_domain_get ()))
6785 ves_icall_System_Environment_BroadcastSettingChange (void)
6788 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, NULL, L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6793 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6794 MonoReflectionMethod *method,
6795 MonoArray *out_args)
6797 MONO_ARCH_SAVE_REGS;
6799 mono_message_init (mono_object_domain (this), this, method, out_args);
6802 #ifndef DISABLE_REMOTING
6803 ICALL_EXPORT MonoBoolean
6804 ves_icall_IsTransparentProxy (MonoObject *proxy)
6806 MONO_ARCH_SAVE_REGS;
6811 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6817 ICALL_EXPORT MonoReflectionMethod *
6818 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6819 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6823 MonoMethod **vtable;
6824 MonoMethod *res = NULL;
6826 MONO_CHECK_ARG_NULL (rtype);
6827 MONO_CHECK_ARG_NULL (rmethod);
6829 method = rmethod->method;
6830 klass = mono_class_from_mono_type (rtype->type);
6831 mono_class_init_or_throw (klass);
6833 if (MONO_CLASS_IS_INTERFACE (klass))
6836 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6839 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6840 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6846 mono_class_setup_vtable (klass);
6847 vtable = klass->vtable;
6849 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6850 gboolean variance_used = FALSE;
6851 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6852 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6854 res = vtable [offs + method->slot];
6856 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6859 if (method->slot != -1)
6860 res = vtable [method->slot];
6866 return mono_method_get_object (mono_domain_get (), res, NULL);
6870 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6875 MONO_ARCH_SAVE_REGS;
6877 klass = mono_class_from_mono_type (type->type);
6878 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6880 if (enable) vtable->remote = 1;
6881 else vtable->remote = 0;
6884 ICALL_EXPORT MonoObject *
6885 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6890 MONO_ARCH_SAVE_REGS;
6892 domain = mono_object_domain (type);
6893 klass = mono_class_from_mono_type (type->type);
6894 mono_class_init_or_throw (klass);
6896 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6897 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6899 if (klass->rank >= 1) {
6900 g_assert (klass->rank == 1);
6901 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6903 /* Bypass remoting object creation check */
6904 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6909 ICALL_EXPORT MonoString *
6910 ves_icall_System_IO_get_temp_path (void)
6912 MONO_ARCH_SAVE_REGS;
6914 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6917 #ifndef PLATFORM_NO_DRIVEINFO
6918 ICALL_EXPORT MonoBoolean
6919 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6920 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6924 ULARGE_INTEGER wapi_free_bytes_avail;
6925 ULARGE_INTEGER wapi_total_number_of_bytes;
6926 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6928 MONO_ARCH_SAVE_REGS;
6930 *error = ERROR_SUCCESS;
6931 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6932 &wapi_total_number_of_free_bytes);
6935 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6936 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6937 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6939 *free_bytes_avail = 0;
6940 *total_number_of_bytes = 0;
6941 *total_number_of_free_bytes = 0;
6942 *error = GetLastError ();
6948 ICALL_EXPORT guint32
6949 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6951 MONO_ARCH_SAVE_REGS;
6953 return GetDriveType (mono_string_chars (root_path_name));
6957 ICALL_EXPORT gpointer
6958 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6960 MONO_ARCH_SAVE_REGS;
6962 return mono_compile_method (method);
6965 ICALL_EXPORT MonoString *
6966 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6971 MONO_ARCH_SAVE_REGS;
6973 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6975 #if defined (HOST_WIN32)
6976 /* Avoid mixing '/' and '\\' */
6979 for (i = strlen (path) - 1; i >= 0; i--)
6980 if (path [i] == '/')
6984 mcpath = mono_string_new (mono_domain_get (), path);
6991 get_bundled_app_config (void)
6993 const gchar *app_config;
6996 gchar *config_file_name, *config_file_path;
7000 MONO_ARCH_SAVE_REGS;
7002 domain = mono_domain_get ();
7003 file = domain->setup->configuration_file;
7007 // Retrieve config file and remove the extension
7008 config_file_name = mono_string_to_utf8 (file);
7009 config_file_path = mono_portability_find_file (config_file_name, TRUE);
7010 if (!config_file_path)
7011 config_file_path = config_file_name;
7012 len = strlen (config_file_path) - strlen (".config");
7013 module = g_malloc0 (len + 1);
7014 memcpy (module, config_file_path, len);
7015 // Get the config file from the module name
7016 app_config = mono_config_string_for_assembly_file (module);
7019 if (config_file_name != config_file_path)
7020 g_free (config_file_name);
7021 g_free (config_file_path);
7026 return mono_string_new (mono_domain_get (), app_config);
7030 get_bundled_machine_config (void)
7032 const gchar *machine_config;
7034 MONO_ARCH_SAVE_REGS;
7036 machine_config = mono_get_machine_config ();
7038 if (!machine_config)
7041 return mono_string_new (mono_domain_get (), machine_config);
7044 ICALL_EXPORT MonoString *
7045 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7050 MONO_ARCH_SAVE_REGS;
7052 path = g_path_get_dirname (mono_get_config_dir ());
7054 #if defined (HOST_WIN32)
7055 /* Avoid mixing '/' and '\\' */
7058 for (i = strlen (path) - 1; i >= 0; i--)
7059 if (path [i] == '/')
7063 ipath = mono_string_new (mono_domain_get (), path);
7069 ICALL_EXPORT gboolean
7070 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7072 MonoPEResourceDataEntry *entry;
7075 MONO_ARCH_SAVE_REGS;
7077 if (!assembly || !result || !size)
7082 image = assembly->assembly->image;
7083 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7087 *result = mono_image_rva_map (image, entry->rde_data_offset);
7092 *size = entry->rde_size;
7097 ICALL_EXPORT MonoBoolean
7098 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7100 return mono_debug_using_mono_debugger () || mono_is_debugger_attached ();
7103 ICALL_EXPORT MonoBoolean
7104 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7106 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7107 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7113 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7115 if (mono_get_runtime_callbacks ()->debug_log)
7116 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7120 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7122 #if defined (HOST_WIN32)
7123 OutputDebugString (mono_string_chars (message));
7125 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7129 /* Only used for value types */
7130 ICALL_EXPORT MonoObject *
7131 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7136 MONO_ARCH_SAVE_REGS;
7138 domain = mono_object_domain (type);
7139 klass = mono_class_from_mono_type (type->type);
7140 mono_class_init_or_throw (klass);
7142 if (mono_class_is_nullable (klass))
7143 /* No arguments -> null */
7146 return mono_object_new (domain, klass);
7149 ICALL_EXPORT MonoReflectionMethod *
7150 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7152 MonoClass *klass, *parent;
7153 MonoMethod *method = m->method;
7154 MonoMethod *result = NULL;
7157 MONO_ARCH_SAVE_REGS;
7159 if (method->klass == NULL)
7162 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7163 MONO_CLASS_IS_INTERFACE (method->klass) ||
7164 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7167 slot = mono_method_get_vtable_slot (method);
7171 klass = method->klass;
7172 if (klass->generic_class)
7173 klass = klass->generic_class->container_class;
7176 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7177 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7178 mono_class_setup_vtable (parent);
7179 if (parent->vtable_size <= slot)
7184 klass = klass->parent;
7189 if (klass == method->klass)
7192 /*This is possible if definition == FALSE.
7193 * Do it here to be really sure we don't read invalid memory.
7195 if (slot >= klass->vtable_size)
7198 mono_class_setup_vtable (klass);
7200 result = klass->vtable [slot];
7201 if (result == NULL) {
7202 /* It is an abstract method */
7203 gpointer iter = NULL;
7204 while ((result = mono_class_get_methods (klass, &iter)))
7205 if (result->slot == slot)
7212 return mono_method_get_object (mono_domain_get (), result, NULL);
7215 ICALL_EXPORT MonoString*
7216 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7218 MonoMethod *method = m->method;
7220 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7225 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7227 MONO_ARCH_SAVE_REGS;
7229 iter->sig = *(MonoMethodSignature**)argsp;
7231 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7232 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7235 /* FIXME: it's not documented what start is exactly... */
7239 iter->args = argsp + sizeof (gpointer);
7241 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7243 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7246 ICALL_EXPORT MonoTypedRef
7247 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7249 guint32 i, arg_size;
7252 MONO_ARCH_SAVE_REGS;
7254 i = iter->sig->sentinelpos + iter->next_arg;
7256 g_assert (i < iter->sig->param_count);
7258 res.type = iter->sig->params [i];
7259 res.klass = mono_class_from_mono_type (res.type);
7260 arg_size = mono_type_stack_size (res.type, &align);
7261 #if defined(__arm__) || defined(__mips__)
7262 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7264 res.value = iter->args;
7265 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7266 if (arg_size <= sizeof (gpointer)) {
7268 int padding = arg_size - mono_type_size (res.type, &dummy);
7269 res.value = (guint8*)res.value + padding;
7272 iter->args = (char*)iter->args + arg_size;
7275 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7280 ICALL_EXPORT MonoTypedRef
7281 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7283 guint32 i, arg_size;
7286 MONO_ARCH_SAVE_REGS;
7288 i = iter->sig->sentinelpos + iter->next_arg;
7290 g_assert (i < iter->sig->param_count);
7292 while (i < iter->sig->param_count) {
7293 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7295 res.type = iter->sig->params [i];
7296 res.klass = mono_class_from_mono_type (res.type);
7297 /* FIXME: endianess issue... */
7298 arg_size = mono_type_stack_size (res.type, &align);
7299 #if defined(__arm__) || defined(__mips__)
7300 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7302 res.value = iter->args;
7303 iter->args = (char*)iter->args + arg_size;
7305 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7308 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7316 ICALL_EXPORT MonoType*
7317 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7320 MONO_ARCH_SAVE_REGS;
7322 i = iter->sig->sentinelpos + iter->next_arg;
7324 g_assert (i < iter->sig->param_count);
7326 return iter->sig->params [i];
7329 ICALL_EXPORT MonoObject*
7330 mono_TypedReference_ToObject (MonoTypedRef tref)
7332 MONO_ARCH_SAVE_REGS;
7334 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7335 MonoObject** objp = tref.value;
7339 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7342 ICALL_EXPORT MonoObject*
7343 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7345 MONO_ARCH_SAVE_REGS;
7347 if (MONO_TYPE_IS_REFERENCE (type)) {
7348 MonoObject** objp = value;
7352 return mono_value_box (mono_domain_get (), klass, value);
7356 prelink_method (MonoMethod *method)
7358 const char *exc_class, *exc_arg;
7359 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7361 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7363 mono_raise_exception(
7364 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7366 /* create the wrapper, too? */
7370 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7372 MONO_ARCH_SAVE_REGS;
7373 prelink_method (method->method);
7377 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7379 MonoClass *klass = mono_class_from_mono_type (type->type);
7381 gpointer iter = NULL;
7382 MONO_ARCH_SAVE_REGS;
7384 mono_class_init_or_throw (klass);
7386 while ((m = mono_class_get_methods (klass, &iter)))
7390 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7392 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7393 gint32 const **exponents,
7394 gunichar2 const **digitLowerTable,
7395 gunichar2 const **digitUpperTable,
7396 gint64 const **tenPowersList,
7397 gint32 const **decHexDigits)
7399 *mantissas = Formatter_MantissaBitsTable;
7400 *exponents = Formatter_TensExponentTable;
7401 *digitLowerTable = Formatter_DigitLowerTable;
7402 *digitUpperTable = Formatter_DigitUpperTable;
7403 *tenPowersList = Formatter_TenPowersList;
7404 *decHexDigits = Formatter_DecHexDigits;
7408 get_category_data (int version,
7409 guint8 const **category_data,
7410 guint16 const **category_astral_index)
7412 *category_astral_index = NULL;
7414 #ifndef DISABLE_NET_4_0
7416 *category_data = CategoryData_v4;
7417 #ifndef DISABLE_ASTRAL
7418 *category_astral_index = CategoryData_v4_astral_index;
7424 *category_data = CategoryData_v2;
7425 #ifndef DISABLE_ASTRAL
7426 *category_astral_index = CategoryData_v2_astral_index;
7430 /* These parameters are "readonly" in corlib/System/Char.cs */
7432 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7433 guint8 const **category_data,
7434 guint16 const **category_astral_index,
7435 guint8 const **numeric_data,
7436 gdouble const **numeric_data_values,
7437 guint16 const **to_lower_data_low,
7438 guint16 const **to_lower_data_high,
7439 guint16 const **to_upper_data_low,
7440 guint16 const **to_upper_data_high)
7442 get_category_data (category_data_version, category_data, category_astral_index);
7443 *numeric_data = NumericData;
7444 *numeric_data_values = NumericDataValues;
7445 *to_lower_data_low = ToLowerDataLow;
7446 *to_lower_data_high = ToLowerDataHigh;
7447 *to_upper_data_low = ToUpperDataLow;
7448 *to_upper_data_high = ToUpperDataHigh;
7452 ves_icall_MonoDebugger_GetMethodToken (MonoReflectionMethod *method)
7454 return method->method->token;
7458 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7459 * and avoid useless allocations.
7462 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7466 for (i = 0; i < type->num_mods; ++i) {
7467 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7472 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7474 for (i = 0; i < type->num_mods; ++i) {
7475 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7476 MonoClass *klass = mono_class_get (image, type->modifiers [i].token);
7477 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7484 ICALL_EXPORT MonoArray*
7485 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7487 MonoType *type = param->ClassImpl->type;
7488 MonoClass *member_class = mono_object_class (param->MemberImpl);
7489 MonoMethod *method = NULL;
7492 MonoMethodSignature *sig;
7494 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7495 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7496 method = rmethod->method;
7497 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7498 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7499 if (!(method = prop->property->get))
7500 method = prop->property->set;
7503 char *type_name = mono_type_get_full_name (member_class);
7504 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7505 MonoException *ex = mono_get_exception_not_supported (msg);
7508 mono_raise_exception (ex);
7511 image = method->klass->image;
7512 pos = param->PositionImpl;
7513 sig = mono_method_signature (method);
7517 type = sig->params [pos];
7519 return type_array_from_modifiers (image, type, optional);
7523 get_property_type (MonoProperty *prop)
7525 MonoMethodSignature *sig;
7527 sig = mono_method_signature (prop->get);
7529 } else if (prop->set) {
7530 sig = mono_method_signature (prop->set);
7531 return sig->params [sig->param_count - 1];
7536 ICALL_EXPORT MonoArray*
7537 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7539 MonoType *type = get_property_type (property->property);
7540 MonoImage *image = property->klass->image;
7544 return type_array_from_modifiers (image, type, optional);
7548 *Construct a MonoType suited to be used to decode a constant blob object.
7550 * @type is the target type which will be constructed
7551 * @blob_type is the blob type, for example, that comes from the constant table
7552 * @real_type is the expected constructed type.
7555 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7557 type->type = blob_type;
7558 type->data.klass = NULL;
7559 if (blob_type == MONO_TYPE_CLASS)
7560 type->data.klass = mono_defaults.object_class;
7561 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7562 /* For enums, we need to use the base type */
7563 type->type = MONO_TYPE_VALUETYPE;
7564 type->data.klass = mono_class_from_mono_type (real_type);
7566 type->data.klass = mono_class_from_mono_type (real_type);
7569 ICALL_EXPORT MonoObject*
7570 property_info_get_default_value (MonoReflectionProperty *property)
7573 MonoProperty *prop = property->property;
7574 MonoType *type = get_property_type (prop);
7575 MonoDomain *domain = mono_object_domain (property);
7576 MonoTypeEnum def_type;
7577 const char *def_value;
7580 mono_class_init (prop->parent);
7582 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7583 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7585 def_value = mono_class_get_property_default_value (prop, &def_type);
7587 mono_type_from_blob_type (&blob_type, def_type, type);
7588 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7593 ICALL_EXPORT MonoBoolean
7594 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7596 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7597 MonoCustomAttrInfo *cinfo;
7600 mono_class_init_or_throw (attr_class);
7602 cinfo = mono_reflection_get_custom_attrs_info (obj);
7605 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7607 mono_custom_attrs_free (cinfo);
7611 ICALL_EXPORT MonoArray*
7612 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7614 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7619 mono_class_init_or_throw (attr_class);
7621 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7622 if (!mono_error_ok (&error))
7623 mono_error_raise_exception (&error);
7624 if (mono_loader_get_last_error ()) {
7625 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7626 g_assert_not_reached ();
7634 ICALL_EXPORT MonoString*
7635 ves_icall_Mono_Runtime_GetDisplayName (void)
7638 MonoString *display_name;
7640 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7641 display_name = mono_string_new (mono_domain_get (), info);
7643 return display_name;
7646 ICALL_EXPORT MonoString*
7647 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7649 MonoString *message;
7653 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7654 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7657 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7659 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7667 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7668 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7669 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7670 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7671 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7672 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7673 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7674 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7678 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7683 gunichar2 last, prev_last, prev2_last;
7690 int havePadding = 0;
7692 last = prev_last = 0, prev2_last = 0;
7693 for (i = 0; i < ilength; i++) {
7695 if (c >= sizeof (dbase64)) {
7696 exc = mono_exception_from_name_msg (mono_get_corlib (),
7697 "System", "FormatException",
7698 "Invalid character found.");
7699 mono_raise_exception (exc);
7700 } else if (isspace (c)) {
7702 } else if (havePadding && c != '=') {
7703 exc = mono_exception_from_name_msg (mono_get_corlib (),
7704 "System", "FormatException",
7705 "Invalid character found.");
7706 mono_raise_exception (exc);
7708 if (c == '=') havePadding = 1;
7709 prev2_last = prev_last;
7715 olength = ilength - ignored;
7717 if (allowWhitespaceOnly && olength == 0) {
7718 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7721 if ((olength & 3) != 0 || olength <= 0) {
7722 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7723 "FormatException", "Invalid length.");
7724 mono_raise_exception (exc);
7727 if (prev2_last == '=') {
7728 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7729 mono_raise_exception (exc);
7732 olength = (olength * 3) / 4;
7736 if (prev_last == '=')
7739 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7740 res_ptr = mono_array_addr (result, guchar, 0);
7741 for (i = 0; i < ilength; ) {
7744 for (k = 0; k < 4 && i < ilength;) {
7750 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7751 exc = mono_exception_from_name_msg (mono_get_corlib (),
7752 "System", "FormatException",
7753 "Invalid character found.");
7754 mono_raise_exception (exc);
7759 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7761 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7763 *res_ptr++ = (b [2] << 6) | b [3];
7765 while (i < ilength && isspace (start [i]))
7772 ICALL_EXPORT MonoArray *
7773 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7775 MONO_ARCH_SAVE_REGS;
7777 return base64_to_byte_array (mono_string_chars (str),
7778 mono_string_length (str), allowWhitespaceOnly);
7781 ICALL_EXPORT MonoArray *
7782 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7784 MONO_ARCH_SAVE_REGS;
7786 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7790 #ifndef DISABLE_ICALL_TABLES
7792 #define ICALL_TYPE(id,name,first)
7793 #define ICALL(id,name,func) Icall_ ## id,
7796 #include "metadata/icall-def.h"
7802 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7803 #define ICALL(id,name,func)
7805 #include "metadata/icall-def.h"
7811 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7812 #define ICALL(id,name,func)
7814 guint16 first_icall;
7817 static const IcallTypeDesc
7818 icall_type_descs [] = {
7819 #include "metadata/icall-def.h"
7823 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7826 #define ICALL_TYPE(id,name,first)
7829 #ifdef HAVE_ARRAY_ELEM_INIT
7830 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7831 #define MSGSTRFIELD1(line) str##line
7833 static const struct msgstrtn_t {
7834 #define ICALL(id,name,func)
7836 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7837 #include "metadata/icall-def.h"
7839 } icall_type_names_str = {
7840 #define ICALL_TYPE(id,name,first) (name),
7841 #include "metadata/icall-def.h"
7844 static const guint16 icall_type_names_idx [] = {
7845 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7846 #include "metadata/icall-def.h"
7849 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7851 static const struct msgstr_t {
7853 #define ICALL_TYPE(id,name,first)
7854 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7855 #include "metadata/icall-def.h"
7857 } icall_names_str = {
7858 #define ICALL(id,name,func) (name),
7859 #include "metadata/icall-def.h"
7862 static const guint16 icall_names_idx [] = {
7863 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7864 #include "metadata/icall-def.h"
7867 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7873 #define ICALL_TYPE(id,name,first) name,
7874 #define ICALL(id,name,func)
7875 static const char* const
7876 icall_type_names [] = {
7877 #include "metadata/icall-def.h"
7881 #define icall_type_name_get(id) (icall_type_names [(id)])
7885 #define ICALL_TYPE(id,name,first)
7886 #define ICALL(id,name,func) name,
7887 static const char* const
7889 #include "metadata/icall-def.h"
7892 #define icall_name_get(id) icall_names [(id)]
7894 #endif /* !HAVE_ARRAY_ELEM_INIT */
7898 #define ICALL_TYPE(id,name,first)
7899 #define ICALL(id,name,func) func,
7900 static const gconstpointer
7901 icall_functions [] = {
7902 #include "metadata/icall-def.h"
7906 #ifdef ENABLE_ICALL_SYMBOL_MAP
7909 #define ICALL_TYPE(id,name,first)
7910 #define ICALL(id,name,func) #func,
7911 static const gconstpointer
7912 icall_symbols [] = {
7913 #include "metadata/icall-def.h"
7918 #endif /* DISABLE_ICALL_TABLES */
7920 static GHashTable *icall_hash = NULL;
7921 static GHashTable *jit_icall_hash_name = NULL;
7922 static GHashTable *jit_icall_hash_addr = NULL;
7925 mono_icall_init (void)
7927 #ifndef DISABLE_ICALL_TABLES
7930 /* check that tables are sorted: disable in release */
7933 const char *prev_class = NULL;
7934 const char *prev_method;
7936 for (i = 0; i < Icall_type_num; ++i) {
7937 const IcallTypeDesc *desc;
7940 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7941 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7942 prev_class = icall_type_name_get (i);
7943 desc = &icall_type_descs [i];
7944 num_icalls = icall_desc_num_icalls (desc);
7945 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7946 for (j = 0; j < num_icalls; ++j) {
7947 const char *methodn = icall_name_get (desc->first_icall + j);
7948 if (prev_method && strcmp (prev_method, methodn) >= 0)
7949 g_print ("method %s should come before method %s\n", methodn, prev_method);
7950 prev_method = methodn;
7956 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7960 mono_icall_cleanup (void)
7962 g_hash_table_destroy (icall_hash);
7963 g_hash_table_destroy (jit_icall_hash_name);
7964 g_hash_table_destroy (jit_icall_hash_addr);
7968 mono_add_internal_call (const char *name, gconstpointer method)
7970 mono_loader_lock ();
7972 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7974 mono_loader_unlock ();
7977 #ifndef DISABLE_ICALL_TABLES
7979 #ifdef HAVE_ARRAY_ELEM_INIT
7981 compare_method_imap (const void *key, const void *elem)
7983 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7984 return strcmp (key, method_name);
7988 find_method_icall (const IcallTypeDesc *imap, const char *name)
7990 const guint16 *nameslot = bsearch (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7993 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7997 compare_class_imap (const void *key, const void *elem)
7999 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
8000 return strcmp (key, class_name);
8003 static const IcallTypeDesc*
8004 find_class_icalls (const char *name)
8006 const guint16 *nameslot = bsearch (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8009 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8012 #else /* HAVE_ARRAY_ELEM_INIT */
8015 compare_method_imap (const void *key, const void *elem)
8017 const char** method_name = (const char**)elem;
8018 return strcmp (key, *method_name);
8022 find_method_icall (const IcallTypeDesc *imap, const char *name)
8024 const char **nameslot = bsearch (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8027 return (gpointer)icall_functions [(nameslot - icall_names)];
8031 compare_class_imap (const void *key, const void *elem)
8033 const char** class_name = (const char**)elem;
8034 return strcmp (key, *class_name);
8037 static const IcallTypeDesc*
8038 find_class_icalls (const char *name)
8040 const char **nameslot = bsearch (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8043 return &icall_type_descs [nameslot - icall_type_names];
8046 #endif /* HAVE_ARRAY_ELEM_INIT */
8048 #endif /* DISABLE_ICALL_TABLES */
8051 * we should probably export this as an helper (handle nested types).
8052 * Returns the number of chars written in buf.
8055 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8057 int nspacelen, cnamelen;
8058 nspacelen = strlen (klass->name_space);
8059 cnamelen = strlen (klass->name);
8060 if (nspacelen + cnamelen + 2 > bufsize)
8063 memcpy (buf, klass->name_space, nspacelen);
8064 buf [nspacelen ++] = '.';
8066 memcpy (buf + nspacelen, klass->name, cnamelen);
8067 buf [nspacelen + cnamelen] = 0;
8068 return nspacelen + cnamelen;
8071 #ifdef DISABLE_ICALL_TABLES
8073 no_icall_table (void)
8075 g_assert_not_reached ();
8080 mono_lookup_internal_call (MonoMethod *method)
8085 int typelen = 0, mlen, siglen;
8087 #ifndef DISABLE_ICALL_TABLES
8088 const IcallTypeDesc *imap = NULL;
8091 g_assert (method != NULL);
8093 if (method->is_inflated)
8094 method = ((MonoMethodInflated *) method)->declaring;
8096 if (method->klass->nested_in) {
8097 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8101 mname [pos++] = '/';
8104 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8110 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8115 #ifndef DISABLE_ICALL_TABLES
8116 imap = find_class_icalls (mname);
8119 mname [typelen] = ':';
8120 mname [typelen + 1] = ':';
8122 mlen = strlen (method->name);
8123 memcpy (mname + typelen + 2, method->name, mlen);
8124 sigstart = mname + typelen + 2 + mlen;
8127 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8128 siglen = strlen (tmpsig);
8129 if (typelen + mlen + siglen + 6 > sizeof (mname))
8132 memcpy (sigstart + 1, tmpsig, siglen);
8133 sigstart [siglen + 1] = ')';
8134 sigstart [siglen + 2] = 0;
8137 mono_loader_lock ();
8139 res = g_hash_table_lookup (icall_hash, mname);
8141 mono_loader_unlock ();
8144 /* try without signature */
8146 res = g_hash_table_lookup (icall_hash, mname);
8148 mono_loader_unlock ();
8152 #ifdef DISABLE_ICALL_TABLES
8153 mono_loader_unlock ();
8154 /* Fail only when the result is actually used */
8155 /* mono_marshal_get_native_wrapper () depends on this */
8156 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8157 return ves_icall_System_String_ctor_RedirectToCreateString;
8159 return no_icall_table;
8161 /* it wasn't found in the static call tables */
8163 mono_loader_unlock ();
8166 res = find_method_icall (imap, sigstart - mlen);
8168 mono_loader_unlock ();
8171 /* try _with_ signature */
8173 res = find_method_icall (imap, sigstart - mlen);
8175 mono_loader_unlock ();
8179 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8180 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8181 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8182 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8183 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");
8184 g_print ("If you see other errors or faults after this message they are probably related\n");
8185 g_print ("and you need to fix your mono install first.\n");
8187 mono_loader_unlock ();
8193 #ifdef ENABLE_ICALL_SYMBOL_MAP
8195 func_cmp (gconstpointer key, gconstpointer p)
8197 return (gsize)key - (gsize)*(gsize*)p;
8202 * mono_lookup_icall_symbol:
8204 * Given the icall METHOD, returns its C symbol.
8207 mono_lookup_icall_symbol (MonoMethod *m)
8209 #ifdef DISABLE_ICALL_TABLES
8210 g_assert_not_reached ();
8213 #ifdef ENABLE_ICALL_SYMBOL_MAP
8217 static gconstpointer *functions_sorted;
8218 static const char**symbols_sorted;
8219 static gboolean inited;
8224 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8225 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8226 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8227 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8228 /* Bubble sort the two arrays */
8232 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8233 if (functions_sorted [i] > functions_sorted [i + 1]) {
8236 tmp = functions_sorted [i];
8237 functions_sorted [i] = functions_sorted [i + 1];
8238 functions_sorted [i + 1] = tmp;
8239 tmp = symbols_sorted [i];
8240 symbols_sorted [i] = symbols_sorted [i + 1];
8241 symbols_sorted [i + 1] = tmp;
8248 func = mono_lookup_internal_call (m);
8251 slot = bsearch (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8255 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8257 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8258 g_assert_not_reached ();
8265 type_from_typename (char *typename)
8267 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8269 if (!strcmp (typename, "int"))
8270 klass = mono_defaults.int_class;
8271 else if (!strcmp (typename, "ptr"))
8272 klass = mono_defaults.int_class;
8273 else if (!strcmp (typename, "void"))
8274 klass = mono_defaults.void_class;
8275 else if (!strcmp (typename, "int32"))
8276 klass = mono_defaults.int32_class;
8277 else if (!strcmp (typename, "uint32"))
8278 klass = mono_defaults.uint32_class;
8279 else if (!strcmp (typename, "int8"))
8280 klass = mono_defaults.sbyte_class;
8281 else if (!strcmp (typename, "uint8"))
8282 klass = mono_defaults.byte_class;
8283 else if (!strcmp (typename, "int16"))
8284 klass = mono_defaults.int16_class;
8285 else if (!strcmp (typename, "uint16"))
8286 klass = mono_defaults.uint16_class;
8287 else if (!strcmp (typename, "long"))
8288 klass = mono_defaults.int64_class;
8289 else if (!strcmp (typename, "ulong"))
8290 klass = mono_defaults.uint64_class;
8291 else if (!strcmp (typename, "float"))
8292 klass = mono_defaults.single_class;
8293 else if (!strcmp (typename, "double"))
8294 klass = mono_defaults.double_class;
8295 else if (!strcmp (typename, "object"))
8296 klass = mono_defaults.object_class;
8297 else if (!strcmp (typename, "obj"))
8298 klass = mono_defaults.object_class;
8299 else if (!strcmp (typename, "string"))
8300 klass = mono_defaults.string_class;
8301 else if (!strcmp (typename, "bool"))
8302 klass = mono_defaults.boolean_class;
8303 else if (!strcmp (typename, "boolean"))
8304 klass = mono_defaults.boolean_class;
8306 g_error ("%s", typename);
8307 g_assert_not_reached ();
8309 return &klass->byval_arg;
8312 MonoMethodSignature*
8313 mono_create_icall_signature (const char *sigstr)
8318 MonoMethodSignature *res;
8320 mono_loader_lock ();
8321 res = g_hash_table_lookup (mono_defaults.corlib->helper_signatures, sigstr);
8323 mono_loader_unlock ();
8327 parts = g_strsplit (sigstr, " ", 256);
8336 res = mono_metadata_signature_alloc (mono_defaults.corlib, len - 1);
8341 * Under windows, the default pinvoke calling convention is STDCALL but
8344 res->call_convention = MONO_CALL_C;
8347 res->ret = type_from_typename (parts [0]);
8348 for (i = 1; i < len; ++i) {
8349 res->params [i - 1] = type_from_typename (parts [i]);
8354 g_hash_table_insert (mono_defaults.corlib->helper_signatures, (gpointer)sigstr, res);
8356 mono_loader_unlock ();
8362 mono_find_jit_icall_by_name (const char *name)
8364 MonoJitICallInfo *info;
8365 g_assert (jit_icall_hash_name);
8367 mono_loader_lock ();
8368 info = g_hash_table_lookup (jit_icall_hash_name, name);
8369 mono_loader_unlock ();
8374 mono_find_jit_icall_by_addr (gconstpointer addr)
8376 MonoJitICallInfo *info;
8377 g_assert (jit_icall_hash_addr);
8379 mono_loader_lock ();
8380 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8381 mono_loader_unlock ();
8387 * mono_get_jit_icall_info:
8389 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8390 * caller should access it while holding the loader lock.
8393 mono_get_jit_icall_info (void)
8395 return jit_icall_hash_name;
8399 * mono_lookup_jit_icall_symbol:
8401 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8404 mono_lookup_jit_icall_symbol (const char *name)
8406 MonoJitICallInfo *info;
8407 const char *res = NULL;
8409 mono_loader_lock ();
8410 info = g_hash_table_lookup (jit_icall_hash_name, name);
8412 res = info->c_symbol;
8413 mono_loader_unlock ();
8418 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8420 mono_loader_lock ();
8421 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8422 mono_loader_unlock ();
8426 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8428 MonoJitICallInfo *info;
8433 mono_loader_lock ();
8435 if (!jit_icall_hash_name) {
8436 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8437 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8440 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8441 g_warning ("jit icall already defined \"%s\"\n", name);
8442 g_assert_not_reached ();
8445 info = g_new0 (MonoJitICallInfo, 1);
8450 info->c_symbol = c_symbol;
8453 info->wrapper = func;
8455 info->wrapper = NULL;
8458 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8459 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8461 mono_loader_unlock ();
8466 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8468 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);