5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2011-2014 Xamarin Inc (http://www.xamarin.com).
23 #ifdef HAVE_SYS_TIME_H
29 #if defined (HOST_WIN32)
32 #if defined (HAVE_WCHAR_H)
36 #include "mono/utils/mono-membar.h"
37 #include <mono/metadata/object.h>
38 #include <mono/metadata/threads.h>
39 #include <mono/metadata/threads-types.h>
40 #include <mono/metadata/threadpool.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/assembly.h>
44 #include <mono/metadata/tabledefs.h>
45 #include <mono/metadata/exception.h>
46 #include <mono/metadata/file-io.h>
47 #include <mono/metadata/console-io.h>
48 #include <mono/metadata/socket-io.h>
49 #include <mono/metadata/mono-endian.h>
50 #include <mono/metadata/tokentype.h>
51 #include <mono/metadata/domain-internals.h>
52 #include <mono/metadata/metadata-internals.h>
53 #include <mono/metadata/class-internals.h>
54 #include <mono/metadata/marshal.h>
55 #include <mono/metadata/gc-internal.h>
56 #include <mono/metadata/mono-gc.h>
57 #include <mono/metadata/rand.h>
58 #include <mono/metadata/sysmath.h>
59 #include <mono/metadata/string-icalls.h>
60 #include <mono/metadata/debug-helpers.h>
61 #include <mono/metadata/process.h>
62 #include <mono/metadata/environment.h>
63 #include <mono/metadata/profiler-private.h>
64 #include <mono/metadata/locales.h>
65 #include <mono/metadata/filewatcher.h>
66 #include <mono/metadata/char-conversions.h>
67 #include <mono/metadata/security.h>
68 #include <mono/metadata/mono-config.h>
69 #include <mono/metadata/cil-coff.h>
70 #include <mono/metadata/number-formatter.h>
71 #include <mono/metadata/security-manager.h>
72 #include <mono/metadata/security-core-clr.h>
73 #include <mono/metadata/mono-perfcounters.h>
74 #include <mono/metadata/mono-debug.h>
75 #include <mono/metadata/mono-ptr-array.h>
76 #include <mono/metadata/verify-internals.h>
77 #include <mono/metadata/runtime.h>
78 #include <mono/metadata/file-mmap.h>
79 #include <mono/io-layer/io-layer.h>
80 #include <mono/utils/strtod.h>
81 #include <mono/utils/monobitset.h>
82 #include <mono/utils/mono-time.h>
83 #include <mono/utils/mono-proclib.h>
84 #include <mono/utils/mono-string.h>
85 #include <mono/utils/mono-error-internals.h>
86 #include <mono/utils/mono-mmap.h>
87 #include <mono/utils/mono-io-portability.h>
88 #include <mono/utils/mono-digest.h>
89 #include <mono/utils/bsearch.h>
90 #include <mono/utils/mono-mutex.h>
91 #include <mono/utils/mono-threads.h>
93 #if defined (HOST_WIN32)
99 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
101 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
104 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
106 static inline MonoBoolean
107 is_generic_parameter (MonoType *type)
109 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
113 mono_class_init_or_throw (MonoClass *klass)
115 if (!mono_class_init (klass))
116 mono_raise_exception (mono_class_get_exception_for_failure (klass));
120 * We expect a pointer to a char, not a string
122 ICALL_EXPORT gboolean
123 mono_double_ParseImpl (char *ptr, double *result)
125 gchar *endptr = NULL;
131 /* mono_strtod () is not thread-safe */
132 mono_mutex_lock (&mono_strtod_mutex);
133 *result = mono_strtod (ptr, &endptr);
134 mono_mutex_unlock (&mono_strtod_mutex);
137 if (!*ptr || (endptr && *endptr))
143 ICALL_EXPORT MonoObject *
144 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
153 ao = (MonoArray *)this;
154 ac = (MonoClass *)ao->obj.vtable->klass;
156 esize = mono_array_element_size (ac);
157 ea = (gpointer*)((char*)ao->vector + (pos * esize));
159 if (ac->element_class->valuetype)
160 return mono_value_box (this->vtable->domain, ac->element_class, ea);
165 ICALL_EXPORT MonoObject *
166 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
174 MONO_CHECK_ARG_NULL (idxs);
176 io = (MonoArray *)idxs;
177 ic = (MonoClass *)io->obj.vtable->klass;
179 ao = (MonoArray *)this;
180 ac = (MonoClass *)ao->obj.vtable->klass;
182 g_assert (ic->rank == 1);
183 if (io->bounds != NULL || io->max_length != ac->rank)
184 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
186 ind = (gint32 *)io->vector;
188 if (ao->bounds == NULL) {
189 if (*ind < 0 || *ind >= ao->max_length)
190 mono_raise_exception (mono_get_exception_index_out_of_range ());
192 return ves_icall_System_Array_GetValueImpl (this, *ind);
195 for (i = 0; i < ac->rank; i++)
196 if ((ind [i] < ao->bounds [i].lower_bound) ||
197 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
198 mono_raise_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - ao->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos*ao->bounds [i].length + ind [i] -
203 ao->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (this, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
211 MonoClass *ac, *vc, *ec;
223 vc = value->vtable->klass;
227 ac = this->obj.vtable->klass;
228 ec = ac->element_class;
230 esize = mono_array_element_size (ac);
231 ea = (gpointer*)((char*)this->vector + (pos * esize));
232 va = (gpointer*)((char*)value + sizeof (MonoObject));
234 if (mono_class_is_nullable (ec)) {
235 mono_nullable_init ((guint8*)ea, value, ec);
240 mono_gc_bzero_atomic (ea, esize);
244 #define NO_WIDENING_CONVERSION G_STMT_START{\
245 mono_raise_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
249 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
250 if (esize < vsize + (extra)) \
251 mono_raise_exception (mono_get_exception_argument ( \
252 "value", "not a widening conversion")); \
255 #define INVALID_CAST G_STMT_START{ \
256 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
257 mono_raise_exception (mono_get_exception_invalid_cast ()); \
260 /* Check element (destination) type. */
261 switch (ec->byval_arg.type) {
262 case MONO_TYPE_STRING:
263 switch (vc->byval_arg.type) {
264 case MONO_TYPE_STRING:
270 case MONO_TYPE_BOOLEAN:
271 switch (vc->byval_arg.type) {
272 case MONO_TYPE_BOOLEAN:
285 NO_WIDENING_CONVERSION;
292 if (!ec->valuetype) {
293 if (!mono_object_isinst (value, ec))
295 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
299 if (mono_object_isinst (value, ec)) {
300 if (ec->has_references)
301 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
303 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
310 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
312 et = ec->byval_arg.type;
313 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
314 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
316 vt = vc->byval_arg.type;
317 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
318 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
320 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
326 case MONO_TYPE_CHAR: \
327 CHECK_WIDENING_CONVERSION(0); \
328 *(etype *) ea = (etype) u64; \
330 /* You can't assign a signed value to an unsigned array. */ \
335 /* You can't assign a floating point number to an integer array. */ \
338 NO_WIDENING_CONVERSION; \
342 #define ASSIGN_SIGNED(etype) G_STMT_START{\
348 CHECK_WIDENING_CONVERSION(0); \
349 *(etype *) ea = (etype) i64; \
351 /* You can assign an unsigned value to a signed array if the array's */ \
352 /* element size is larger than the value size. */ \
357 case MONO_TYPE_CHAR: \
358 CHECK_WIDENING_CONVERSION(1); \
359 *(etype *) ea = (etype) u64; \
361 /* You can't assign a floating point number to an integer array. */ \
364 NO_WIDENING_CONVERSION; \
368 #define ASSIGN_REAL(etype) G_STMT_START{\
372 CHECK_WIDENING_CONVERSION(0); \
373 *(etype *) ea = (etype) r64; \
375 /* All integer values fit into a floating point array, so we don't */ \
376 /* need to CHECK_WIDENING_CONVERSION here. */ \
381 *(etype *) ea = (etype) i64; \
387 case MONO_TYPE_CHAR: \
388 *(etype *) ea = (etype) u64; \
395 u64 = *(guint8 *) va;
398 u64 = *(guint16 *) va;
401 u64 = *(guint32 *) va;
404 u64 = *(guint64 *) va;
410 i64 = *(gint16 *) va;
413 i64 = *(gint32 *) va;
416 i64 = *(gint64 *) va;
419 r64 = *(gfloat *) va;
422 r64 = *(gdouble *) va;
425 u64 = *(guint16 *) va;
427 case MONO_TYPE_BOOLEAN:
428 /* Boolean is only compatible with itself. */
441 NO_WIDENING_CONVERSION;
448 /* If we can't do a direct copy, let's try a widening conversion. */
451 ASSIGN_UNSIGNED (guint16);
453 ASSIGN_UNSIGNED (guint8);
455 ASSIGN_UNSIGNED (guint16);
457 ASSIGN_UNSIGNED (guint32);
459 ASSIGN_UNSIGNED (guint64);
461 ASSIGN_SIGNED (gint8);
463 ASSIGN_SIGNED (gint16);
465 ASSIGN_SIGNED (gint32);
467 ASSIGN_SIGNED (gint64);
469 ASSIGN_REAL (gfloat);
471 ASSIGN_REAL (gdouble);
475 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
479 #undef NO_WIDENING_CONVERSION
480 #undef CHECK_WIDENING_CONVERSION
481 #undef ASSIGN_UNSIGNED
487 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
495 MONO_CHECK_ARG_NULL (idxs);
497 ic = idxs->obj.vtable->klass;
498 ac = this->obj.vtable->klass;
500 g_assert (ic->rank == 1);
501 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
502 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
504 ind = (gint32 *)idxs->vector;
506 if (this->bounds == NULL) {
507 if (*ind < 0 || *ind >= this->max_length)
508 mono_raise_exception (mono_get_exception_index_out_of_range ());
510 ves_icall_System_Array_SetValueImpl (this, value, *ind);
514 for (i = 0; i < ac->rank; i++)
515 if ((ind [i] < this->bounds [i].lower_bound) ||
516 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
517 mono_raise_exception (mono_get_exception_index_out_of_range ());
519 pos = ind [0] - this->bounds [0].lower_bound;
520 for (i = 1; i < ac->rank; i++)
521 pos = pos * this->bounds [i].length + ind [i] -
522 this->bounds [i].lower_bound;
524 ves_icall_System_Array_SetValueImpl (this, value, pos);
527 ICALL_EXPORT MonoArray *
528 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
530 MonoClass *aklass, *klass;
533 gboolean bounded = FALSE;
537 MONO_CHECK_ARG_NULL (type);
538 MONO_CHECK_ARG_NULL (lengths);
540 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
542 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
544 for (i = 0; i < mono_array_length (lengths); i++)
545 if (mono_array_get (lengths, gint32, i) < 0)
546 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
548 klass = mono_class_from_mono_type (type->type);
549 mono_class_init_or_throw (klass);
551 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
552 /* vectors are not the same as one dimensional arrays with no-zero bounds */
557 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
559 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
560 for (i = 0; i < aklass->rank; ++i) {
561 sizes [i] = mono_array_get (lengths, guint32, i);
563 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
565 sizes [i + aklass->rank] = 0;
568 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
573 ICALL_EXPORT MonoArray *
574 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
576 MonoClass *aklass, *klass;
579 gboolean bounded = FALSE;
583 MONO_CHECK_ARG_NULL (type);
584 MONO_CHECK_ARG_NULL (lengths);
586 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
588 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
590 for (i = 0; i < mono_array_length (lengths); i++)
591 if ((mono_array_get (lengths, gint64, i) < 0) ||
592 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
593 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
595 klass = mono_class_from_mono_type (type->type);
596 mono_class_init_or_throw (klass);
598 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
599 /* vectors are not the same as one dimensional arrays with no-zero bounds */
604 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
606 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
607 for (i = 0; i < aklass->rank; ++i) {
608 sizes [i] = mono_array_get (lengths, guint64, i);
610 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
612 sizes [i + aklass->rank] = 0;
615 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
621 ves_icall_System_Array_GetRank (MonoObject *this)
625 return this->vtable->klass->rank;
629 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
631 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
636 if ((dimension < 0) || (dimension >= rank))
637 mono_raise_exception (mono_get_exception_index_out_of_range ());
639 if (this->bounds == NULL)
640 length = this->max_length;
642 length = this->bounds [dimension].length;
644 #ifdef MONO_BIG_ARRAYS
645 if (length > G_MAXINT32)
646 mono_raise_exception (mono_get_exception_overflow ());
652 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
654 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank))
659 mono_raise_exception (mono_get_exception_index_out_of_range ());
661 if (this->bounds == NULL)
662 return this->max_length;
664 return this->bounds [dimension].length;
668 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
670 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
674 if ((dimension < 0) || (dimension >= rank))
675 mono_raise_exception (mono_get_exception_index_out_of_range ());
677 if (this->bounds == NULL)
680 return this->bounds [dimension].lower_bound;
684 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
686 int sz = mono_array_element_size (mono_object_class (arr));
687 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
690 ICALL_EXPORT gboolean
691 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
696 MonoVTable *src_vtable;
697 MonoVTable *dest_vtable;
698 MonoClass *src_class;
699 MonoClass *dest_class;
701 src_vtable = source->obj.vtable;
702 dest_vtable = dest->obj.vtable;
704 if (src_vtable->rank != dest_vtable->rank)
707 if (source->bounds || dest->bounds)
710 /* there's no integer overflow since mono_array_length returns an unsigned integer */
711 if ((dest_idx + length > mono_array_length_fast (dest)) ||
712 (source_idx + length > mono_array_length_fast (source)))
715 src_class = src_vtable->klass->element_class;
716 dest_class = dest_vtable->klass->element_class;
719 * Handle common cases.
722 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
723 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
725 if (src_class == mono_defaults.object_class && dest_class->valuetype)
728 /* Check if we're copying a char[] <==> (u)short[] */
729 if (src_class != dest_class) {
730 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
733 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
734 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
738 if (dest_class->valuetype) {
739 element_size = mono_array_element_size (source->obj.vtable->klass);
740 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
741 if (dest_class->has_references) {
742 mono_value_copy_array (dest, dest_idx, source_addr, length);
744 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
745 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
748 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
755 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
764 ao = (MonoArray *)this;
765 ac = (MonoClass *)ao->obj.vtable->klass;
767 esize = mono_array_element_size (ac);
768 ea = (gpointer*)((char*)ao->vector + (pos * esize));
770 mono_gc_memmove_atomic (value, ea, esize);
774 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
783 ao = (MonoArray *)this;
784 ac = (MonoClass *)ao->obj.vtable->klass;
785 ec = ac->element_class;
787 esize = mono_array_element_size (ac);
788 ea = (gpointer*)((char*)ao->vector + (pos * esize));
790 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
791 g_assert (esize == sizeof (gpointer));
792 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
794 g_assert (ec->inited);
795 g_assert (esize == mono_class_value_size (ec, NULL));
796 if (ec->has_references)
797 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
799 mono_gc_memmove_atomic (ea, value, esize);
804 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
806 MonoClass *klass = array->obj.vtable->klass;
807 guint32 size = mono_array_element_size (klass);
808 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
810 const char *field_data;
812 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
813 MonoException *exc = mono_get_exception_argument("array",
814 "Cannot initialize array of non-primitive type.");
815 mono_raise_exception (exc);
818 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
819 MonoException *exc = mono_get_exception_argument("field_handle",
820 "Field doesn't have an RVA");
821 mono_raise_exception (exc);
824 size *= array->max_length;
825 field_data = mono_field_get_data (field_handle);
827 if (size > mono_type_size (field_handle->type, &align)) {
828 MonoException *exc = mono_get_exception_argument("field_handle",
829 "Field not large enough to fill array");
830 mono_raise_exception (exc);
833 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
835 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
836 guint ## n *src = (guint ## n *) field_data; \
837 guint ## n *end = (guint ## n *)((char*)src + size); \
839 for (; src < end; data++, src++) { \
840 *data = read ## n (src); \
844 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
846 switch (type->type) {
863 memcpy (mono_array_addr (array, char, 0), field_data, size);
867 memcpy (mono_array_addr (array, char, 0), field_data, size);
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
876 return offsetof (MonoString, chars);
879 ICALL_EXPORT MonoObject *
880 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
884 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
887 return mono_object_clone (obj);
891 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
896 MONO_CHECK_ARG_NULL (handle);
898 klass = mono_class_from_mono_type (handle);
899 MONO_CHECK_ARG (handle, klass);
901 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
903 /* This will call the type constructor */
904 mono_runtime_class_init (vtable);
908 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
912 mono_image_check_for_module_cctor (image);
913 if (image->has_module_cctor) {
914 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
915 mono_error_raise_exception (&error);
916 /*It's fine to raise the exception here*/
917 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
921 ICALL_EXPORT MonoBoolean
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
927 /* later make this configurable and per-arch */
928 int min_size = 4096 * 4 * sizeof (void*);
929 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
930 /* if we have no info we are optimistic and assume there is enough room */
934 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
938 current = (guint8 *)&stack_addr;
939 if (current > stack_addr) {
940 if ((current - stack_addr) < min_size)
943 if (current - (stack_addr - stack_size) < min_size)
949 ICALL_EXPORT MonoObject *
950 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
954 return mono_object_clone (this);
958 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
961 MonoObject **values = NULL;
964 gint32 result = (int)(gsize)mono_defaults.int32_class;
965 MonoClassField* field;
970 klass = mono_object_class (this);
972 if (mono_class_num_fields (klass) == 0)
976 * Compute the starting value of the hashcode for fields of primitive
977 * types, and return the remaining fields in an array to the managed side.
978 * This way, we can avoid costly reflection operations in managed code.
981 while ((field = mono_class_get_fields (klass, &iter))) {
982 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
984 if (mono_field_is_deleted (field))
986 /* FIXME: Add more types */
987 switch (field->type->type) {
989 result ^= *(gint32*)((guint8*)this + field->offset);
991 case MONO_TYPE_STRING: {
993 s = *(MonoString**)((guint8*)this + field->offset);
995 result ^= mono_string_hash (s);
1000 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1001 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1002 values [count++] = o;
1008 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1009 for (i = 0; i < count; ++i)
1010 mono_array_setref (*fields, i, values [i]);
1017 ICALL_EXPORT MonoBoolean
1018 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1021 MonoObject **values = NULL;
1023 MonoClassField* field;
1027 MONO_ARCH_SAVE_REGS;
1029 MONO_CHECK_ARG_NULL (that);
1031 if (this->vtable != that->vtable)
1034 klass = mono_object_class (this);
1036 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1037 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1040 * Do the comparison for fields of primitive type and return a result if
1041 * possible. Otherwise, return the remaining fields in an array to the
1042 * managed side. This way, we can avoid costly reflection operations in
1047 while ((field = mono_class_get_fields (klass, &iter))) {
1048 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1050 if (mono_field_is_deleted (field))
1052 /* FIXME: Add more types */
1053 switch (field->type->type) {
1056 case MONO_TYPE_BOOLEAN:
1057 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1062 case MONO_TYPE_CHAR:
1063 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1068 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1073 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1077 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1081 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1086 case MONO_TYPE_STRING: {
1087 MonoString *s1, *s2;
1088 guint32 s1len, s2len;
1089 s1 = *(MonoString**)((guint8*)this + field->offset);
1090 s2 = *(MonoString**)((guint8*)that + field->offset);
1093 if ((s1 == NULL) || (s2 == NULL))
1095 s1len = mono_string_length (s1);
1096 s2len = mono_string_length (s2);
1100 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1106 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1107 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1108 values [count++] = o;
1109 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1110 values [count++] = o;
1113 if (klass->enumtype)
1114 /* enums only have one non-static field */
1120 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1121 for (i = 0; i < count; ++i)
1122 mono_array_setref_fast (*fields, i, values [i]);
1129 ICALL_EXPORT MonoReflectionType *
1130 ves_icall_System_Object_GetType (MonoObject *obj)
1132 MONO_ARCH_SAVE_REGS;
1134 #ifndef DISABLE_REMOTING
1135 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1136 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1139 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1143 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1145 MONO_ARCH_SAVE_REGS;
1147 mtype->type = &obj->vtable->klass->byval_arg;
1148 g_assert (mtype->type->type);
1152 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1154 MONO_ARCH_SAVE_REGS;
1156 MONO_CHECK_ARG_NULL (obj);
1158 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1162 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1163 MonoReflectionMethod *method,
1164 MonoArray *opt_param_types)
1166 MONO_ARCH_SAVE_REGS;
1168 MONO_CHECK_ARG_NULL (method);
1170 return mono_image_create_method_token (
1171 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1175 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1177 MONO_ARCH_SAVE_REGS;
1179 mono_image_create_pefile (mb, file);
1183 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1185 MONO_ARCH_SAVE_REGS;
1187 mono_image_build_metadata (mb);
1191 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1193 MONO_ARCH_SAVE_REGS;
1195 mono_image_register_token (mb->dynamic_image, token, obj);
1199 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1201 MonoMethod **dest = data;
1203 /* skip unmanaged frames */
1219 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1221 MonoMethod **dest = data;
1223 /* skip unmanaged frames */
1228 if (!strcmp (m->klass->name_space, "System.Reflection"))
1237 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1239 MonoMethod **dest = data;
1241 /* skip unmanaged frames */
1245 if (m->wrapper_type != MONO_WRAPPER_NONE)
1248 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1262 static MonoReflectionType *
1263 type_from_name (const char *str, MonoBoolean ignoreCase)
1265 MonoMethod *m, *dest;
1267 MonoType *type = NULL;
1268 MonoAssembly *assembly = NULL;
1269 MonoTypeNameParse info;
1270 char *temp_str = g_strdup (str);
1271 gboolean type_resolve = FALSE;
1273 MONO_ARCH_SAVE_REGS;
1275 /* mono_reflection_parse_type() mangles the string */
1276 if (!mono_reflection_parse_type (temp_str, &info)) {
1277 mono_reflection_free_type_info (&info);
1284 * We must compute the calling assembly as type loading must happen under a metadata context.
1285 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1286 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1288 m = mono_method_get_last_managed ();
1291 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1296 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1297 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1298 * to crash. This only seems to happen in some strange remoting
1299 * scenarios and I was unable to figure out what's happening there.
1300 * Dec 10, 2005 - Martin.
1304 assembly = dest->klass->image->assembly;
1305 type_resolve = TRUE;
1307 g_warning (G_STRLOC);
1310 if (info.assembly.name)
1311 assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
1315 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1316 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1319 if (!info.assembly.name && !type) /* try mscorlib */
1320 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1322 if (assembly && !type && type_resolve) {
1323 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1324 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1327 mono_reflection_free_type_info (&info);
1333 return mono_type_get_object (mono_domain_get (), type);
1337 MonoReflectionType *
1338 mono_type_get (const char *str)
1340 char *copy = g_strdup (str);
1341 MonoReflectionType *type = type_from_name (copy, FALSE);
1348 ICALL_EXPORT MonoReflectionType*
1349 ves_icall_type_from_name (MonoString *name,
1350 MonoBoolean throwOnError,
1351 MonoBoolean ignoreCase)
1353 char *str = mono_string_to_utf8 (name);
1354 MonoReflectionType *type;
1356 type = type_from_name (str, ignoreCase);
1359 MonoException *e = NULL;
1362 e = mono_get_exception_type_load (name, NULL);
1364 mono_loader_clear_error ();
1366 mono_raise_exception (e);
1373 ICALL_EXPORT MonoReflectionType*
1374 ves_icall_type_from_handle (MonoType *handle)
1376 MonoDomain *domain = mono_domain_get ();
1378 MONO_ARCH_SAVE_REGS;
1380 return mono_type_get_object (domain, handle);
1383 ICALL_EXPORT MonoBoolean
1384 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1386 MONO_ARCH_SAVE_REGS;
1388 if (c && type->type && c->type)
1389 return mono_metadata_type_equal (type->type, c->type);
1391 return (type == c) ? TRUE : FALSE;
1394 /* System.TypeCode */
1413 TYPECODE_STRING = 18
1416 ICALL_EXPORT guint32
1417 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1419 int t = type->type->type;
1421 MONO_ARCH_SAVE_REGS;
1423 if (type->type->byref)
1424 return TYPECODE_OBJECT;
1428 case MONO_TYPE_VOID:
1429 return TYPECODE_OBJECT;
1430 case MONO_TYPE_BOOLEAN:
1431 return TYPECODE_BOOLEAN;
1433 return TYPECODE_BYTE;
1435 return TYPECODE_SBYTE;
1437 return TYPECODE_UINT16;
1439 return TYPECODE_INT16;
1440 case MONO_TYPE_CHAR:
1441 return TYPECODE_CHAR;
1445 return TYPECODE_OBJECT;
1447 return TYPECODE_UINT32;
1449 return TYPECODE_INT32;
1451 return TYPECODE_UINT64;
1453 return TYPECODE_INT64;
1455 return TYPECODE_SINGLE;
1457 return TYPECODE_DOUBLE;
1458 case MONO_TYPE_VALUETYPE: {
1459 MonoClass *klass = type->type->data.klass;
1461 if (klass->enumtype) {
1462 t = mono_class_enum_basetype (klass)->type;
1464 } else if (mono_is_corlib_image (klass->image)) {
1465 if (strcmp (klass->name_space, "System") == 0) {
1466 if (strcmp (klass->name, "Decimal") == 0)
1467 return TYPECODE_DECIMAL;
1468 else if (strcmp (klass->name, "DateTime") == 0)
1469 return TYPECODE_DATETIME;
1472 return TYPECODE_OBJECT;
1474 case MONO_TYPE_STRING:
1475 return TYPECODE_STRING;
1476 case MONO_TYPE_SZARRAY:
1477 case MONO_TYPE_ARRAY:
1478 case MONO_TYPE_OBJECT:
1480 case MONO_TYPE_MVAR:
1481 case MONO_TYPE_TYPEDBYREF:
1482 return TYPECODE_OBJECT;
1483 case MONO_TYPE_CLASS:
1485 MonoClass *klass = type->type->data.klass;
1486 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1487 if (strcmp (klass->name, "DBNull") == 0)
1488 return TYPECODE_DBNULL;
1491 return TYPECODE_OBJECT;
1492 case MONO_TYPE_GENERICINST:
1493 return TYPECODE_OBJECT;
1495 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1500 ICALL_EXPORT guint32
1501 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1507 MONO_ARCH_SAVE_REGS;
1509 g_assert (type != NULL);
1511 domain = ((MonoObject *)type)->vtable->domain;
1513 if (!c) /* FIXME: dont know what do do here */
1516 klass = mono_class_from_mono_type (type->type);
1517 klassc = mono_class_from_mono_type (c->type);
1519 /* Interface check requires a more complex setup so we
1520 * only do for them. Otherwise we simply avoid mono_class_init.
1522 if (check_interfaces) {
1523 mono_class_init_or_throw (klass);
1524 mono_class_init_or_throw (klassc);
1525 } else if (!klass->supertypes || !klassc->supertypes) {
1526 mono_class_setup_supertypes (klass);
1527 mono_class_setup_supertypes (klassc);
1530 if (type->type->byref)
1531 return klassc == mono_defaults.object_class;
1533 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1537 mono_type_is_primitive (MonoType *type)
1539 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1540 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1544 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1546 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1547 return mono_class_enum_basetype (type->data.klass);
1548 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1549 return mono_class_enum_basetype (type->data.generic_class->container_class);
1553 ICALL_EXPORT guint32
1554 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1560 MONO_ARCH_SAVE_REGS;
1562 g_assert (type != NULL);
1564 domain = ((MonoObject *)type)->vtable->domain;
1566 klass = mono_class_from_mono_type (type->type);
1567 klassc = mono_class_from_mono_type (c->type);
1569 if (type->type->byref ^ c->type->byref)
1572 if (type->type->byref) {
1573 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1574 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1576 klass = mono_class_from_mono_type (t);
1577 klassc = mono_class_from_mono_type (ot);
1579 if (mono_type_is_primitive (t)) {
1580 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1581 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1582 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1583 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1584 return t->type == ot->type;
1586 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1589 if (klass->valuetype)
1590 return klass == klassc;
1591 return klass->valuetype == klassc->valuetype;
1594 return mono_class_is_assignable_from (klass, klassc);
1597 ICALL_EXPORT guint32
1598 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1600 MonoClass *klass = mono_class_from_mono_type (type->type);
1601 mono_class_init_or_throw (klass);
1602 return mono_object_isinst (obj, klass) != NULL;
1605 ICALL_EXPORT guint32
1606 ves_icall_get_attributes (MonoReflectionType *type)
1608 MonoClass *klass = mono_class_from_mono_type (type->type);
1609 return klass->flags;
1612 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1613 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1615 MonoClass *klass = field->field->parent;
1616 MonoMarshalType *info;
1620 if (klass->generic_container ||
1621 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1624 ftype = mono_field_get_type (field->field);
1625 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1628 info = mono_marshal_load_type_info (klass);
1630 for (i = 0; i < info->num_fields; ++i) {
1631 if (info->fields [i].field == field->field) {
1632 if (!info->fields [i].mspec)
1635 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1642 ICALL_EXPORT MonoReflectionField*
1643 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1645 gboolean found = FALSE;
1652 klass = handle->parent;
1654 klass = mono_class_from_mono_type (type);
1656 /* Check that the field belongs to the class */
1657 for (k = klass; k; k = k->parent) {
1658 if (k == handle->parent) {
1665 /* The managed code will throw the exception */
1669 return mono_field_get_object (mono_domain_get (), klass, handle);
1672 ICALL_EXPORT MonoArray*
1673 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1676 MonoType *type = mono_field_get_type_checked (field->field, &error);
1677 mono_error_raise_exception (&error);
1679 return type_array_from_modifiers (field->field->parent->image, type, optional);
1683 vell_icall_get_method_attributes (MonoMethod *method)
1685 return method->flags;
1689 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1692 MonoDomain *domain = mono_domain_get ();
1693 MonoMethodSignature* sig;
1694 MONO_ARCH_SAVE_REGS;
1696 sig = mono_method_signature_checked (method, &error);
1697 if (!mono_error_ok (&error))
1698 mono_error_raise_exception (&error);
1701 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1702 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1703 info->attrs = method->flags;
1704 info->implattrs = method->iflags;
1705 if (sig->call_convention == MONO_CALL_DEFAULT)
1706 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1708 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1713 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1716 ICALL_EXPORT MonoArray*
1717 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1719 MonoDomain *domain = mono_domain_get ();
1721 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1724 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1725 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1727 MonoDomain *domain = mono_domain_get ();
1728 MonoReflectionMarshalAsAttribute* res = NULL;
1729 MonoMarshalSpec **mspecs;
1732 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1733 mono_method_get_marshal_info (method, mspecs);
1736 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1738 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1740 mono_metadata_free_marshal_spec (mspecs [i]);
1747 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1749 MonoClass *parent = field->field->parent;
1750 if (!parent->size_inited)
1751 mono_class_init (parent);
1752 mono_class_setup_fields_locking (parent);
1754 return field->field->offset - sizeof (MonoObject);
1757 ICALL_EXPORT MonoReflectionType*
1758 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1761 MONO_ARCH_SAVE_REGS;
1763 parent = declaring? field->field->parent: field->klass;
1765 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1768 ICALL_EXPORT MonoObject *
1769 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1771 MonoClass *fklass = field->klass;
1772 MonoClassField *cf = field->field;
1773 MonoDomain *domain = mono_object_domain (field);
1775 if (fklass->image->assembly->ref_only)
1776 mono_raise_exception (mono_get_exception_invalid_operation (
1777 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1779 if (mono_security_core_clr_enabled ())
1780 mono_security_core_clr_ensure_reflection_access_field (cf);
1782 return mono_field_get_value_object (domain, cf, obj);
1786 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1789 MonoClassField *cf = field->field;
1793 MONO_ARCH_SAVE_REGS;
1795 if (field->klass->image->assembly->ref_only)
1796 mono_raise_exception (mono_get_exception_invalid_operation (
1797 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1799 if (mono_security_core_clr_enabled ())
1800 mono_security_core_clr_ensure_reflection_access_field (cf);
1802 type = mono_field_get_type_checked (cf, &error);
1803 if (!mono_error_ok (&error))
1804 mono_error_raise_exception (&error);
1806 v = (gchar *) value;
1808 switch (type->type) {
1811 case MONO_TYPE_BOOLEAN:
1814 case MONO_TYPE_CHAR:
1823 case MONO_TYPE_VALUETYPE:
1826 v += sizeof (MonoObject);
1828 case MONO_TYPE_STRING:
1829 case MONO_TYPE_OBJECT:
1830 case MONO_TYPE_CLASS:
1831 case MONO_TYPE_ARRAY:
1832 case MONO_TYPE_SZARRAY:
1835 case MONO_TYPE_GENERICINST: {
1836 MonoGenericClass *gclass = type->data.generic_class;
1837 g_assert (!gclass->context.class_inst->is_open);
1839 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1840 MonoClass *nklass = mono_class_from_mono_type (type);
1841 MonoObject *nullable;
1844 * Convert the boxed vtype into a Nullable structure.
1845 * This is complicated by the fact that Nullables have
1846 * a variable structure.
1848 nullable = mono_object_new (mono_domain_get (), nklass);
1850 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1852 v = mono_object_unbox (nullable);
1855 if (gclass->container_class->valuetype && (v != NULL))
1856 v += sizeof (MonoObject);
1860 g_error ("type 0x%x not handled in "
1861 "ves_icall_FieldInfo_SetValueInternal", type->type);
1866 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1867 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1868 if (!vtable->initialized)
1869 mono_runtime_class_init (vtable);
1870 mono_field_static_set_value (vtable, cf, v);
1872 mono_field_set_value (obj, cf, v);
1876 ICALL_EXPORT MonoObject *
1877 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1879 MonoObject *o = NULL;
1880 MonoClassField *field = this->field;
1882 MonoDomain *domain = mono_object_domain (this);
1884 MonoTypeEnum def_type;
1885 const char *def_value;
1889 MONO_ARCH_SAVE_REGS;
1891 mono_class_init (field->parent);
1893 t = mono_field_get_type_checked (field, &error);
1894 if (!mono_error_ok (&error))
1895 mono_error_raise_exception (&error);
1897 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1898 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1900 if (image_is_dynamic (field->parent->image)) {
1902 g_assert_not_reached ();
1905 def_value = mono_class_get_field_default_value (field, &def_type);
1906 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1907 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1909 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1913 case MONO_TYPE_BOOLEAN:
1916 case MONO_TYPE_CHAR:
1924 case MONO_TYPE_R8: {
1927 /* boxed value type */
1928 t = g_new0 (MonoType, 1);
1930 klass = mono_class_from_mono_type (t);
1932 o = mono_object_new (domain, klass);
1933 v = ((gchar *) o) + sizeof (MonoObject);
1934 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1937 case MONO_TYPE_STRING:
1938 case MONO_TYPE_CLASS:
1939 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1942 g_assert_not_reached ();
1948 ICALL_EXPORT MonoReflectionType*
1949 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1952 MonoClassField *field = ref_field->field;
1953 MonoType *type = mono_field_get_type_checked (field, &error);
1954 if (!mono_error_ok (&error))
1955 mono_error_raise_exception (&error);
1956 return mono_type_get_object (mono_object_domain (ref_field), type);
1959 ICALL_EXPORT MonoReflectionType*
1960 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1962 MonoMethod *method = rmethod->method.method;
1964 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1967 /* From MonoProperty.cs */
1969 PInfo_Attributes = 1,
1970 PInfo_GetMethod = 1 << 1,
1971 PInfo_SetMethod = 1 << 2,
1972 PInfo_ReflectedType = 1 << 3,
1973 PInfo_DeclaringType = 1 << 4,
1978 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1980 MonoDomain *domain = mono_object_domain (property);
1982 MONO_ARCH_SAVE_REGS;
1984 if ((req_info & PInfo_ReflectedType) != 0)
1985 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1986 if ((req_info & PInfo_DeclaringType) != 0)
1987 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1989 if ((req_info & PInfo_Name) != 0)
1990 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1992 if ((req_info & PInfo_Attributes) != 0)
1993 info->attrs = property->property->attrs;
1995 if ((req_info & PInfo_GetMethod) != 0)
1996 MONO_STRUCT_SETREF (info, get, property->property->get ?
1997 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1999 if ((req_info & PInfo_SetMethod) != 0)
2000 MONO_STRUCT_SETREF (info, set, property->property->set ?
2001 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2003 * There may be other methods defined for properties, though, it seems they are not exposed
2004 * in the reflection API
2009 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2011 MonoDomain *domain = mono_object_domain (event);
2013 MONO_ARCH_SAVE_REGS;
2015 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2016 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2018 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2019 info->attrs = event->event->attrs;
2020 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2021 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2022 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2024 #ifndef MONO_SMALL_CONFIG
2025 if (event->event->other) {
2027 while (event->event->other [n])
2029 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2031 for (i = 0; i < n; i++)
2032 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2038 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2043 mono_class_setup_interfaces (klass, error);
2044 if (!mono_error_ok (error))
2047 for (i = 0; i < klass->interface_count; i++) {
2048 ic = klass->interfaces [i];
2049 g_hash_table_insert (ifaces, ic, ic);
2051 collect_interfaces (ic, ifaces, error);
2052 if (!mono_error_ok (error))
2058 MonoArray *iface_array;
2059 MonoGenericContext *context;
2063 } FillIfaceArrayData;
2066 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2068 FillIfaceArrayData *data = user_data;
2069 MonoClass *ic = key;
2070 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2072 if (!mono_error_ok (data->error))
2075 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2076 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2077 if (!mono_error_ok (data->error))
2081 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2084 mono_metadata_free_type (inflated);
2087 ICALL_EXPORT MonoArray*
2088 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2091 MonoClass *class = mono_class_from_mono_type (type->type);
2093 FillIfaceArrayData data = { 0 };
2096 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2098 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2099 data.context = mono_class_get_context (class);
2100 class = class->generic_class->container_class;
2103 for (parent = class; parent; parent = parent->parent) {
2104 mono_class_setup_interfaces (parent, &error);
2105 if (!mono_error_ok (&error))
2107 collect_interfaces (parent, iface_hash, &error);
2108 if (!mono_error_ok (&error))
2112 data.error = &error;
2113 data.domain = mono_object_domain (type);
2115 len = g_hash_table_size (iface_hash);
2117 g_hash_table_destroy (iface_hash);
2118 if (!data.domain->empty_types)
2119 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2120 return data.domain->empty_types;
2123 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2124 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2125 if (!mono_error_ok (&error))
2128 g_hash_table_destroy (iface_hash);
2129 return data.iface_array;
2132 g_hash_table_destroy (iface_hash);
2133 mono_error_raise_exception (&error);
2138 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2140 gboolean variance_used;
2141 MonoClass *class = mono_class_from_mono_type (type->type);
2142 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2143 MonoReflectionMethod *member;
2146 int i = 0, len, ioffset;
2149 MONO_ARCH_SAVE_REGS;
2150 mono_class_init_or_throw (class);
2151 mono_class_init_or_throw (iclass);
2153 mono_class_setup_vtable (class);
2155 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2159 len = mono_class_num_methods (iclass);
2160 domain = mono_object_domain (type);
2161 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2162 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2164 while ((method = mono_class_get_methods (iclass, &iter))) {
2165 member = mono_method_get_object (domain, method, iclass);
2166 mono_array_setref (*methods, i, member);
2167 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2168 mono_array_setref (*targets, i, member);
2175 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2177 MonoClass *klass = mono_class_from_mono_type (type->type);
2178 mono_class_init_or_throw (klass);
2180 if (image_is_dynamic (klass->image)) {
2181 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2182 *packing = tb->packing_size;
2183 *size = tb->class_size;
2185 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2189 ICALL_EXPORT MonoReflectionType*
2190 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2194 MONO_ARCH_SAVE_REGS;
2196 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2197 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2199 class = mono_class_from_mono_type (type->type);
2200 mono_class_init_or_throw (class);
2202 // GetElementType should only return a type for:
2203 // Array Pointer PassedByRef
2204 if (type->type->byref)
2205 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2206 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2207 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2208 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2209 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2214 ICALL_EXPORT MonoReflectionType*
2215 ves_icall_get_type_parent (MonoReflectionType *type)
2217 MonoClass *class = mono_class_from_mono_type (type->type);
2218 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2221 ICALL_EXPORT MonoBoolean
2222 ves_icall_type_ispointer (MonoReflectionType *type)
2224 MONO_ARCH_SAVE_REGS;
2226 return type->type->type == MONO_TYPE_PTR;
2229 ICALL_EXPORT MonoBoolean
2230 ves_icall_type_isprimitive (MonoReflectionType *type)
2232 MONO_ARCH_SAVE_REGS;
2234 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)));
2237 ICALL_EXPORT MonoBoolean
2238 ves_icall_type_isbyref (MonoReflectionType *type)
2240 MONO_ARCH_SAVE_REGS;
2242 return type->type->byref;
2245 ICALL_EXPORT MonoBoolean
2246 ves_icall_type_iscomobject (MonoReflectionType *type)
2248 MonoClass *klass = mono_class_from_mono_type (type->type);
2249 mono_class_init_or_throw (klass);
2251 return mono_class_is_com_object (klass);
2254 ICALL_EXPORT MonoReflectionModule*
2255 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2257 MonoClass *class = mono_class_from_mono_type (type->type);
2258 return mono_module_get_object (mono_object_domain (type), class->image);
2261 ICALL_EXPORT MonoReflectionAssembly*
2262 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2264 MonoDomain *domain = mono_domain_get ();
2265 MonoClass *class = mono_class_from_mono_type (type->type);
2266 return mono_assembly_get_object (domain, class->image->assembly);
2269 ICALL_EXPORT MonoReflectionType*
2270 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2272 MonoDomain *domain = mono_domain_get ();
2275 MONO_ARCH_SAVE_REGS;
2277 if (type->type->byref)
2279 if (type->type->type == MONO_TYPE_VAR) {
2280 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2281 class = param ? param->owner.klass : NULL;
2282 } else if (type->type->type == MONO_TYPE_MVAR) {
2283 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2284 class = param ? param->owner.method->klass : NULL;
2286 class = mono_class_from_mono_type (type->type)->nested_in;
2289 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2292 ICALL_EXPORT MonoString*
2293 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2295 MonoDomain *domain = mono_domain_get ();
2296 MonoClass *class = mono_class_from_mono_type (type->type);
2298 if (type->type->byref) {
2299 char *n = g_strdup_printf ("%s&", class->name);
2300 MonoString *res = mono_string_new (domain, n);
2306 return mono_string_new (domain, class->name);
2310 ICALL_EXPORT MonoString*
2311 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2313 MonoDomain *domain = mono_domain_get ();
2314 MonoClass *class = mono_class_from_mono_type (type->type);
2316 while (class->nested_in)
2317 class = class->nested_in;
2319 if (class->name_space [0] == '\0')
2322 return mono_string_new (domain, class->name_space);
2326 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2330 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2331 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2333 class = mono_class_from_mono_type (type->type);
2338 ICALL_EXPORT MonoArray*
2339 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2342 MonoClass *klass, *pklass;
2343 MonoDomain *domain = mono_object_domain (type);
2344 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2346 MONO_ARCH_SAVE_REGS;
2348 klass = mono_class_from_mono_type (type->type);
2350 if (klass->generic_container) {
2351 MonoGenericContainer *container = klass->generic_container;
2352 res = mono_array_new_specific (array_vtable, container->type_argc);
2353 for (i = 0; i < container->type_argc; ++i) {
2354 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2355 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2357 } else if (klass->generic_class) {
2358 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2359 res = mono_array_new_specific (array_vtable, inst->type_argc);
2360 for (i = 0; i < inst->type_argc; ++i)
2361 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2363 res = mono_array_new_specific (array_vtable, 0);
2368 ICALL_EXPORT gboolean
2369 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2372 MONO_ARCH_SAVE_REGS;
2374 if (!IS_MONOTYPE (type))
2377 if (type->type->byref)
2380 klass = mono_class_from_mono_type (type->type);
2381 return klass->generic_container != NULL;
2384 ICALL_EXPORT MonoReflectionType*
2385 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2388 MONO_ARCH_SAVE_REGS;
2390 if (type->type->byref)
2393 klass = mono_class_from_mono_type (type->type);
2395 if (klass->generic_container) {
2396 return type; /* check this one */
2398 if (klass->generic_class) {
2399 MonoClass *generic_class = klass->generic_class->container_class;
2402 tb = mono_class_get_ref_info (generic_class);
2404 if (generic_class->wastypebuilder && tb)
2407 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2412 ICALL_EXPORT MonoReflectionType*
2413 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2416 MonoType *geninst, **types;
2419 g_assert (IS_MONOTYPE (type));
2420 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2422 count = mono_array_length (type_array);
2423 types = g_new0 (MonoType *, count);
2425 for (i = 0; i < count; i++) {
2426 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2427 types [i] = t->type;
2430 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2435 class = mono_class_from_mono_type (geninst);
2437 /*we might inflate to the GTD*/
2438 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2439 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2441 return mono_type_get_object (mono_object_domain (type), geninst);
2444 ICALL_EXPORT gboolean
2445 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2448 MONO_ARCH_SAVE_REGS;
2450 if (type->type->byref)
2453 klass = mono_class_from_mono_type (type->type);
2455 return klass->generic_class != NULL;
2458 ICALL_EXPORT gboolean
2459 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2462 MONO_ARCH_SAVE_REGS;
2464 if (!IS_MONOTYPE (type))
2467 if (type->type->byref)
2470 klass = mono_class_from_mono_type (type->type);
2471 return klass->generic_class != NULL || klass->generic_container != NULL;
2475 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2477 MONO_ARCH_SAVE_REGS;
2479 if (!IS_MONOTYPE (type))
2482 if (is_generic_parameter (type->type))
2483 return mono_type_get_generic_param_num (type->type);
2487 ICALL_EXPORT GenericParameterAttributes
2488 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2490 MONO_ARCH_SAVE_REGS;
2492 g_assert (IS_MONOTYPE (type));
2493 g_assert (is_generic_parameter (type->type));
2494 return mono_generic_param_info (type->type->data.generic_param)->flags;
2497 ICALL_EXPORT MonoArray *
2498 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2500 MonoGenericParamInfo *param_info;
2506 MONO_ARCH_SAVE_REGS;
2508 g_assert (IS_MONOTYPE (type));
2510 domain = mono_object_domain (type);
2511 param_info = mono_generic_param_info (type->type->data.generic_param);
2512 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2515 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2516 for (i = 0; i < count; i++)
2517 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2523 ICALL_EXPORT MonoBoolean
2524 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2526 MONO_ARCH_SAVE_REGS;
2527 return is_generic_parameter (type->type);
2530 ICALL_EXPORT MonoBoolean
2531 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2533 MONO_ARCH_SAVE_REGS;
2534 return is_generic_parameter (tb->type.type);
2538 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2539 MonoReflectionType *t)
2541 enumtype->type = t->type;
2544 ICALL_EXPORT MonoReflectionMethod*
2545 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2546 MonoReflectionMethod* generic)
2553 MONO_ARCH_SAVE_REGS;
2555 domain = ((MonoObject *)type)->vtable->domain;
2557 klass = mono_class_from_mono_type (type->type);
2558 mono_class_init_or_throw (klass);
2561 while ((method = mono_class_get_methods (klass, &iter))) {
2562 if (method->token == generic->method->token)
2563 return mono_method_get_object (domain, method, klass);
2571 ICALL_EXPORT MonoReflectionMethod *
2572 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2575 MonoType *type = ref_type->type;
2577 MONO_ARCH_SAVE_REGS;
2579 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2580 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2581 if (type->type == MONO_TYPE_VAR)
2584 method = mono_type_get_generic_param_owner (type)->owner.method;
2586 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2589 ICALL_EXPORT MonoReflectionDllImportAttribute*
2590 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2592 static MonoClass *DllImportAttributeClass = NULL;
2593 MonoDomain *domain = mono_domain_get ();
2594 MonoReflectionDllImportAttribute *attr;
2595 MonoImage *image = method->klass->image;
2596 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2597 MonoTableInfo *tables = image->tables;
2598 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2599 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2600 guint32 im_cols [MONO_IMPLMAP_SIZE];
2601 guint32 scope_token;
2602 const char *import = NULL;
2603 const char *scope = NULL;
2606 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2609 if (!DllImportAttributeClass) {
2610 DllImportAttributeClass =
2611 mono_class_from_name (mono_defaults.corlib,
2612 "System.Runtime.InteropServices", "DllImportAttribute");
2613 g_assert (DllImportAttributeClass);
2616 if (image_is_dynamic (method->klass->image)) {
2617 MonoReflectionMethodAux *method_aux =
2618 g_hash_table_lookup (
2619 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2621 import = method_aux->dllentry;
2622 scope = method_aux->dll;
2625 if (!import || !scope) {
2626 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2631 if (piinfo->implmap_idx) {
2632 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2634 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2635 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2636 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2637 scope = mono_metadata_string_heap (image, scope_token);
2640 flags = piinfo->piflags;
2642 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2644 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2645 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2646 attr->call_conv = (flags & 0x700) >> 8;
2647 attr->charset = ((flags & 0x6) >> 1) + 1;
2648 if (attr->charset == 1)
2650 attr->exact_spelling = (flags & 0x1) != 0;
2651 attr->set_last_error = (flags & 0x40) != 0;
2652 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2653 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2654 attr->preserve_sig = FALSE;
2659 ICALL_EXPORT MonoReflectionMethod *
2660 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2662 MonoMethodInflated *imethod;
2665 MONO_ARCH_SAVE_REGS;
2667 if (method->method->is_generic)
2670 if (!method->method->is_inflated)
2673 imethod = (MonoMethodInflated *) method->method;
2675 result = imethod->declaring;
2676 /* Not a generic method. */
2677 if (!result->is_generic)
2680 if (image_is_dynamic (method->method->klass->image)) {
2681 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2682 MonoReflectionMethod *res;
2685 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2686 * the dynamic case as well ?
2688 mono_image_lock ((MonoImage*)image);
2689 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2690 mono_image_unlock ((MonoImage*)image);
2696 if (imethod->context.class_inst) {
2697 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2698 /*Generic methods gets the context of the GTD.*/
2699 if (mono_class_get_context (klass))
2700 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2703 return mono_method_get_object (mono_object_domain (method), result, NULL);
2706 ICALL_EXPORT gboolean
2707 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2709 MONO_ARCH_SAVE_REGS;
2711 return mono_method_signature (method->method)->generic_param_count != 0;
2714 ICALL_EXPORT gboolean
2715 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2717 MONO_ARCH_SAVE_REGS;
2719 return method->method->is_generic;
2722 ICALL_EXPORT MonoArray*
2723 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2728 MONO_ARCH_SAVE_REGS;
2730 domain = mono_object_domain (method);
2732 if (method->method->is_inflated) {
2733 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2736 count = inst->type_argc;
2737 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2739 for (i = 0; i < count; i++)
2740 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2746 count = mono_method_signature (method->method)->generic_param_count;
2747 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2749 for (i = 0; i < count; i++) {
2750 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2751 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2752 MonoClass *pklass = mono_class_from_generic_parameter (
2753 param, method->method->klass->image, TRUE);
2754 mono_array_setref (res, i,
2755 mono_type_get_object (domain, &pklass->byval_arg));
2761 ICALL_EXPORT MonoObject *
2762 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2765 * Invoke from reflection is supposed to always be a virtual call (the API
2766 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2767 * greater flexibility.
2769 MonoMethod *m = method->method;
2770 MonoMethodSignature *sig = mono_method_signature (m);
2775 MONO_ARCH_SAVE_REGS;
2779 if (mono_security_core_clr_enabled ())
2780 mono_security_core_clr_ensure_reflection_access_method (m);
2782 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2783 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2784 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2789 if (!mono_object_isinst (this, m->klass)) {
2790 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2791 char *target_name = mono_type_get_full_name (m->klass);
2792 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2793 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2795 g_free (target_name);
2799 m = mono_object_get_virtual_method (this, m);
2800 /* must pass the pointer to the value for valuetype methods */
2801 if (m->klass->valuetype)
2802 obj = mono_object_unbox (this);
2803 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2804 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2809 if (sig->ret->byref) {
2810 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"));
2814 pcount = params? mono_array_length (params): 0;
2815 if (pcount != sig->param_count) {
2816 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2820 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2821 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."));
2825 image = m->klass->image;
2826 if (image->assembly->ref_only) {
2827 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."));
2831 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2832 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2836 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2839 intptr_t *lower_bounds;
2840 pcount = mono_array_length (params);
2841 lengths = alloca (sizeof (uintptr_t) * pcount);
2842 /* Note: the synthetized array .ctors have int32 as argument type */
2843 for (i = 0; i < pcount; ++i)
2844 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2846 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2847 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2848 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2850 for (i = 0; i < mono_array_length (arr); ++i) {
2851 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2853 mono_array_setref_fast (arr, i, subarray);
2855 return (MonoObject*)arr;
2858 if (m->klass->rank == pcount) {
2859 /* Only lengths provided. */
2860 lower_bounds = NULL;
2862 g_assert (pcount == (m->klass->rank * 2));
2863 /* lower bounds are first. */
2864 lower_bounds = (intptr_t*)lengths;
2865 lengths += m->klass->rank;
2868 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2870 return mono_runtime_invoke_array (m, obj, params, NULL);
2873 #ifndef DISABLE_REMOTING
2874 ICALL_EXPORT MonoObject *
2875 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2877 MonoDomain *domain = mono_object_domain (method);
2878 MonoMethod *m = method->method;
2879 MonoMethodSignature *sig = mono_method_signature (m);
2880 MonoArray *out_args;
2882 int i, j, outarg_count = 0;
2884 MONO_ARCH_SAVE_REGS;
2886 if (m->klass == mono_defaults.object_class) {
2888 if (!strcmp (m->name, "FieldGetter")) {
2889 MonoClass *k = this->vtable->klass;
2893 /* If this is a proxy, then it must be a CBO */
2894 if (k == mono_defaults.transparent_proxy_class) {
2895 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2896 this = tp->rp->unwrapped_server;
2898 k = this->vtable->klass;
2901 name = mono_array_get (params, MonoString *, 1);
2902 str = mono_string_to_utf8 (name);
2905 MonoClassField* field = mono_class_get_field_from_name (k, str);
2907 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2908 if (field_klass->valuetype)
2909 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2911 result = *((gpointer *)((char *)this + field->offset));
2913 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2914 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2915 mono_array_setref (out_args, 0, result);
2923 g_assert_not_reached ();
2925 } else if (!strcmp (m->name, "FieldSetter")) {
2926 MonoClass *k = this->vtable->klass;
2932 /* If this is a proxy, then it must be a CBO */
2933 if (k == mono_defaults.transparent_proxy_class) {
2934 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2935 this = tp->rp->unwrapped_server;
2937 k = this->vtable->klass;
2940 name = mono_array_get (params, MonoString *, 1);
2941 str = mono_string_to_utf8 (name);
2944 MonoClassField* field = mono_class_get_field_from_name (k, str);
2946 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2947 MonoObject *val = mono_array_get (params, gpointer, 2);
2949 if (field_klass->valuetype) {
2950 size = mono_type_size (field->type, &align);
2951 g_assert (size == mono_class_value_size (field_klass, NULL));
2952 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2954 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2957 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2958 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2968 g_assert_not_reached ();
2973 for (i = 0; i < mono_array_length (params); i++) {
2974 if (sig->params [i]->byref)
2978 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2980 /* handle constructors only for objects already allocated */
2981 if (!strcmp (method->method->name, ".ctor"))
2984 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2985 g_assert (!method->method->klass->valuetype);
2986 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2988 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2989 if (sig->params [i]->byref) {
2991 arg = mono_array_get (params, gpointer, i);
2992 mono_array_setref (out_args, j, arg);
2997 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3004 read_enum_value (char *mem, int type)
3007 case MONO_TYPE_BOOLEAN:
3009 return *(guint8*)mem;
3011 return *(gint8*)mem;
3012 case MONO_TYPE_CHAR:
3014 return *(guint16*)mem;
3016 return *(gint16*)mem;
3018 return *(guint32*)mem;
3020 return *(gint32*)mem;
3022 return *(guint64*)mem;
3024 return *(gint64*)mem;
3026 g_assert_not_reached ();
3032 write_enum_value (char *mem, int type, guint64 value)
3036 case MONO_TYPE_I1: {
3037 guint8 *p = (guint8*)mem;
3042 case MONO_TYPE_I2: {
3043 guint16 *p = (void*)mem;
3048 case MONO_TYPE_I4: {
3049 guint32 *p = (void*)mem;
3054 case MONO_TYPE_I8: {
3055 guint64 *p = (void*)mem;
3060 g_assert_not_reached ();
3065 ICALL_EXPORT MonoObject *
3066 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3069 MonoClass *enumc, *objc;
3074 MONO_ARCH_SAVE_REGS;
3076 MONO_CHECK_ARG_NULL (enumType);
3077 MONO_CHECK_ARG_NULL (value);
3079 domain = mono_object_domain (enumType);
3080 enumc = mono_class_from_mono_type (enumType->type);
3082 mono_class_init_or_throw (enumc);
3084 objc = value->vtable->klass;
3086 if (!enumc->enumtype)
3087 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3088 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_BOOLEAN && objc->byval_arg.type <= MONO_TYPE_U8)))
3089 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."));
3091 etype = mono_class_enum_basetype (enumc);
3093 /* MS throws this for typebuilders */
3094 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3096 res = mono_object_new (domain, enumc);
3097 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3098 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3103 ICALL_EXPORT MonoObject *
3104 ves_icall_System_Enum_get_value (MonoObject *this)
3112 MONO_ARCH_SAVE_REGS;
3117 g_assert (this->vtable->klass->enumtype);
3119 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3120 res = mono_object_new (mono_object_domain (this), enumc);
3121 dst = (char *)res + sizeof (MonoObject);
3122 src = (char *)this + sizeof (MonoObject);
3123 size = mono_class_value_size (enumc, NULL);
3125 memcpy (dst, src, size);
3130 ICALL_EXPORT MonoReflectionType *
3131 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3136 MONO_ARCH_SAVE_REGS;
3138 klass = mono_class_from_mono_type (type->type);
3139 mono_class_init_or_throw (klass);
3141 etype = mono_class_enum_basetype (klass);
3143 /* MS throws this for typebuilders */
3144 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3146 return mono_type_get_object (mono_object_domain (type), etype);
3150 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3152 gpointer tdata = (char *)this + sizeof (MonoObject);
3153 gpointer odata = (char *)other + sizeof (MonoObject);
3154 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3155 g_assert (basetype);
3157 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3158 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3159 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3162 return me > other ? 1 : -1; \
3165 switch (basetype->type) {
3167 COMPARE_ENUM_VALUES (guint8);
3169 COMPARE_ENUM_VALUES (gint8);
3170 case MONO_TYPE_CHAR:
3172 COMPARE_ENUM_VALUES (guint16);
3174 COMPARE_ENUM_VALUES (gint16);
3176 COMPARE_ENUM_VALUES (guint32);
3178 COMPARE_ENUM_VALUES (gint32);
3180 COMPARE_ENUM_VALUES (guint64);
3182 COMPARE_ENUM_VALUES (gint64);
3184 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3186 #undef COMPARE_ENUM_VALUES
3191 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3193 gpointer data = (char *)this + sizeof (MonoObject);
3194 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3195 g_assert (basetype);
3197 switch (basetype->type) {
3199 return *((gint8*)data);
3201 return *((guint8*)data);
3202 case MONO_TYPE_CHAR:
3204 return *((guint16*)data);
3207 return *((gint16*)data);
3209 return *((guint32*)data);
3211 return *((gint32*)data);
3213 case MONO_TYPE_I8: {
3214 gint64 value = *((gint64*)data);
3215 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3218 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3224 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3226 MonoDomain *domain = mono_object_domain (type);
3227 MonoClass *enumc = mono_class_from_mono_type (type->type);
3228 guint j = 0, nvalues, crow;
3230 MonoClassField *field;
3232 MONO_ARCH_SAVE_REGS;
3234 mono_class_init_or_throw (enumc);
3236 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3237 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3238 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3239 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3243 while ((field = mono_class_get_fields (enumc, &iter))) {
3246 MonoTypeEnum def_type;
3248 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3250 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3252 if (mono_field_is_deleted (field))
3254 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3256 p = mono_class_get_field_default_value (field, &def_type);
3257 len = mono_metadata_decode_blob_size (p, &p);
3258 switch (mono_class_enum_basetype (enumc)->type) {
3261 mono_array_set (info->values, gchar, j, *p);
3263 case MONO_TYPE_CHAR:
3266 mono_array_set (info->values, gint16, j, read16 (p));
3270 mono_array_set (info->values, gint32, j, read32 (p));
3274 mono_array_set (info->values, gint64, j, read64 (p));
3277 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3284 BFLAGS_IgnoreCase = 1,
3285 BFLAGS_DeclaredOnly = 2,
3286 BFLAGS_Instance = 4,
3288 BFLAGS_Public = 0x10,
3289 BFLAGS_NonPublic = 0x20,
3290 BFLAGS_FlattenHierarchy = 0x40,
3291 BFLAGS_InvokeMethod = 0x100,
3292 BFLAGS_CreateInstance = 0x200,
3293 BFLAGS_GetField = 0x400,
3294 BFLAGS_SetField = 0x800,
3295 BFLAGS_GetProperty = 0x1000,
3296 BFLAGS_SetProperty = 0x2000,
3297 BFLAGS_ExactBinding = 0x10000,
3298 BFLAGS_SuppressChangeType = 0x20000,
3299 BFLAGS_OptionalParamBinding = 0x40000
3302 ICALL_EXPORT MonoReflectionField *
3303 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3306 MonoClass *startklass, *klass;
3308 MonoClassField *field;
3311 int (*compare_func) (const char *s1, const char *s2) = NULL;
3312 domain = ((MonoObject *)type)->vtable->domain;
3313 klass = startklass = mono_class_from_mono_type (type->type);
3316 mono_raise_exception (mono_get_exception_argument_null ("name"));
3317 if (type->type->byref)
3320 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3323 if (klass->exception_type != MONO_EXCEPTION_NONE)
3324 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3327 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3328 guint32 flags = mono_field_get_flags (field);
3331 if (mono_field_is_deleted_with_flags (field, flags))
3333 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3334 if (bflags & BFLAGS_Public)
3336 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3337 if (bflags & BFLAGS_NonPublic) {
3344 if (flags & FIELD_ATTRIBUTE_STATIC) {
3345 if (bflags & BFLAGS_Static)
3346 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3349 if (bflags & BFLAGS_Instance)
3356 utf8_name = mono_string_to_utf8 (name);
3358 if (compare_func (mono_field_get_name (field), utf8_name)) {
3364 return mono_field_get_object (domain, klass, field);
3366 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3372 ICALL_EXPORT MonoArray*
3373 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3376 MonoClass *startklass, *klass, *refklass;
3381 MonoClassField *field;
3382 MonoPtrArray tmp_array;
3384 MONO_ARCH_SAVE_REGS;
3386 domain = ((MonoObject *)type)->vtable->domain;
3387 if (type->type->byref)
3388 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3389 klass = startklass = mono_class_from_mono_type (type->type);
3390 refklass = mono_class_from_mono_type (reftype->type);
3392 mono_ptr_array_init (tmp_array, 2);
3395 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3396 mono_ptr_array_destroy (tmp_array);
3397 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3401 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3402 guint32 flags = mono_field_get_flags (field);
3404 if (mono_field_is_deleted_with_flags (field, flags))
3406 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3407 if (bflags & BFLAGS_Public)
3409 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3410 if (bflags & BFLAGS_NonPublic) {
3417 if (flags & FIELD_ATTRIBUTE_STATIC) {
3418 if (bflags & BFLAGS_Static)
3419 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3422 if (bflags & BFLAGS_Instance)
3428 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3429 mono_ptr_array_append (tmp_array, member);
3431 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3434 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3436 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3437 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3439 mono_ptr_array_destroy (tmp_array);
3445 method_nonpublic (MonoMethod* method, gboolean start_klass)
3447 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3448 case METHOD_ATTRIBUTE_ASSEM:
3449 return (start_klass || mono_defaults.generic_ilist_class);
3450 case METHOD_ATTRIBUTE_PRIVATE:
3452 case METHOD_ATTRIBUTE_PUBLIC:
3460 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3463 MonoClass *startklass;
3466 int len, match, nslots;
3467 /*FIXME, use MonoBitSet*/
3468 guint32 method_slots_default [8];
3469 guint32 *method_slots = NULL;
3470 int (*compare_func) (const char *s1, const char *s2) = NULL;
3472 array = g_ptr_array_new ();
3478 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3480 /* An optimization for calls made from Delegate:CreateDelegate () */
3481 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3482 method = mono_get_delegate_invoke (klass);
3483 if (mono_loader_get_last_error ())
3486 g_ptr_array_add (array, method);
3490 mono_class_setup_vtable (klass);
3491 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3494 if (is_generic_parameter (&klass->byval_arg))
3495 nslots = mono_class_get_vtable_size (klass->parent);
3497 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3498 if (nslots >= sizeof (method_slots_default) * 8) {
3499 method_slots = g_new0 (guint32, nslots / 32 + 1);
3501 method_slots = method_slots_default;
3502 memset (method_slots, 0, sizeof (method_slots_default));
3505 mono_class_setup_vtable (klass);
3506 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3510 while ((method = mono_class_get_methods (klass, &iter))) {
3512 if (method->slot != -1) {
3513 g_assert (method->slot < nslots);
3514 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3516 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3517 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3520 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3522 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3523 if (bflags & BFLAGS_Public)
3525 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3531 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3532 if (bflags & BFLAGS_Static)
3533 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3536 if (bflags & BFLAGS_Instance)
3544 if (compare_func (name, method->name))
3549 g_ptr_array_add (array, method);
3551 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3553 if (method_slots != method_slots_default)
3554 g_free (method_slots);
3559 if (method_slots != method_slots_default)
3560 g_free (method_slots);
3561 g_ptr_array_free (array, TRUE);
3563 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3564 *ex = mono_class_get_exception_for_failure (klass);
3566 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3567 mono_loader_clear_error ();
3572 ICALL_EXPORT MonoArray*
3573 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3575 static MonoClass *MethodInfo_array;
3578 MonoVTable *array_vtable;
3579 MonoException *ex = NULL;
3580 const char *mname = NULL;
3581 GPtrArray *method_array;
3582 MonoClass *klass, *refklass;
3585 if (!MethodInfo_array) {
3586 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3587 mono_memory_barrier ();
3588 MethodInfo_array = klass;
3591 klass = mono_class_from_mono_type (type->type);
3592 refklass = mono_class_from_mono_type (reftype->type);
3593 domain = ((MonoObject *)type)->vtable->domain;
3594 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3595 if (type->type->byref)
3596 return mono_array_new_specific (array_vtable, 0);
3599 mname = mono_string_to_utf8 (name);
3601 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3602 g_free ((char*)mname);
3604 mono_raise_exception (ex);
3606 res = mono_array_new_specific (array_vtable, method_array->len);
3609 for (i = 0; i < method_array->len; ++i) {
3610 MonoMethod *method = g_ptr_array_index (method_array, i);
3611 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3614 g_ptr_array_free (method_array, TRUE);
3618 ICALL_EXPORT MonoArray*
3619 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3622 static MonoClass *System_Reflection_ConstructorInfo;
3623 MonoClass *startklass, *klass, *refklass;
3628 gpointer iter = NULL;
3629 MonoPtrArray tmp_array;
3631 MONO_ARCH_SAVE_REGS;
3633 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3635 domain = ((MonoObject *)type)->vtable->domain;
3636 if (type->type->byref)
3637 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3638 klass = startklass = mono_class_from_mono_type (type->type);
3639 refklass = mono_class_from_mono_type (reftype->type);
3641 if (!System_Reflection_ConstructorInfo)
3642 System_Reflection_ConstructorInfo = mono_class_from_name (
3643 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3646 while ((method = mono_class_get_methods (klass, &iter))) {
3648 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3650 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3651 if (bflags & BFLAGS_Public)
3654 if (bflags & BFLAGS_NonPublic)
3660 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3661 if (bflags & BFLAGS_Static)
3662 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3665 if (bflags & BFLAGS_Instance)
3671 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3673 mono_ptr_array_append (tmp_array, member);
3676 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3678 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3679 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3681 mono_ptr_array_destroy (tmp_array);
3687 property_hash (gconstpointer data)
3689 MonoProperty *prop = (MonoProperty*)data;
3691 return g_str_hash (prop->name);
3695 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3697 // Properties are hide-by-name-and-signature
3698 if (!g_str_equal (prop1->name, prop2->name))
3701 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3703 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3709 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3714 return method_nonpublic (accessor, start_klass);
3717 ICALL_EXPORT MonoArray*
3718 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3722 static MonoClass *System_Reflection_PropertyInfo;
3723 MonoClass *startklass, *klass;
3729 gchar *propname = NULL;
3730 int (*compare_func) (const char *s1, const char *s2) = NULL;
3732 GHashTable *properties = NULL;
3733 MonoPtrArray tmp_array;
3735 MONO_ARCH_SAVE_REGS;
3737 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3739 if (!System_Reflection_PropertyInfo)
3740 System_Reflection_PropertyInfo = mono_class_from_name (
3741 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3743 domain = ((MonoObject *)type)->vtable->domain;
3744 if (type->type->byref)
3745 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3746 klass = startklass = mono_class_from_mono_type (type->type);
3749 propname = mono_string_to_utf8 (name);
3750 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3753 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3755 mono_class_setup_vtable (klass);
3756 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3760 while ((prop = mono_class_get_properties (klass, &iter))) {
3766 flags = method->flags;
3769 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3770 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3771 if (bflags & BFLAGS_Public)
3773 } else if (bflags & BFLAGS_NonPublic) {
3774 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3775 property_accessor_nonpublic(prop->set, startklass == klass)) {
3782 if (flags & METHOD_ATTRIBUTE_STATIC) {
3783 if (bflags & BFLAGS_Static)
3784 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3787 if (bflags & BFLAGS_Instance)
3796 if (compare_func (propname, prop->name))
3800 if (g_hash_table_lookup (properties, prop))
3803 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3805 g_hash_table_insert (properties, prop, prop);
3807 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3810 g_hash_table_destroy (properties);
3813 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3814 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3815 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3817 mono_ptr_array_destroy (tmp_array);
3823 g_hash_table_destroy (properties);
3826 mono_ptr_array_destroy (tmp_array);
3828 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3829 ex = mono_class_get_exception_for_failure (klass);
3831 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3832 mono_loader_clear_error ();
3834 mono_raise_exception (ex);
3838 ICALL_EXPORT MonoReflectionEvent *
3839 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3842 MonoClass *klass, *startklass;
3847 int (*compare_func) (const char *s1, const char *s2);
3849 MONO_ARCH_SAVE_REGS;
3851 event_name = mono_string_to_utf8 (name);
3852 if (type->type->byref)
3854 klass = startklass = mono_class_from_mono_type (type->type);
3855 domain = mono_object_domain (type);
3857 mono_class_init_or_throw (klass);
3859 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3861 if (klass->exception_type != MONO_EXCEPTION_NONE)
3862 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3865 while ((event = mono_class_get_events (klass, &iter))) {
3866 if (compare_func (event->name, event_name))
3869 method = event->add;
3871 method = event->remove;
3873 method = event->raise;
3875 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3876 if (!(bflags & BFLAGS_Public))
3879 if (!(bflags & BFLAGS_NonPublic))
3881 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3885 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3886 if (!(bflags & BFLAGS_Static))
3888 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3891 if (!(bflags & BFLAGS_Instance))
3895 if (!(bflags & BFLAGS_NonPublic))
3898 g_free (event_name);
3899 return mono_event_get_object (domain, startklass, event);
3902 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3905 g_free (event_name);
3910 event_hash (gconstpointer data)
3912 MonoEvent *event = (MonoEvent*)data;
3914 return g_str_hash (event->name);
3918 event_equal (MonoEvent *event1, MonoEvent *event2)
3920 // Events are hide-by-name
3921 return g_str_equal (event1->name, event2->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;
3936 GHashTable *events = NULL;
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);
3952 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3954 mono_class_setup_vtable (klass);
3955 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3959 while ((event = mono_class_get_events (klass, &iter))) {
3961 method = event->add;
3963 method = event->remove;
3965 method = event->raise;
3967 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3968 if (bflags & BFLAGS_Public)
3970 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3971 if (bflags & BFLAGS_NonPublic)
3976 if (bflags & BFLAGS_NonPublic)
3982 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3983 if (bflags & BFLAGS_Static)
3984 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3987 if (bflags & BFLAGS_Instance)
3992 if (bflags & BFLAGS_Instance)
3997 if (g_hash_table_lookup (events, event))
4000 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4002 g_hash_table_insert (events, event, event);
4004 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4007 g_hash_table_destroy (events);
4009 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4011 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4012 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4014 mono_ptr_array_destroy (tmp_array);
4019 mono_ptr_array_destroy (tmp_array);
4020 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4021 ex = mono_class_get_exception_for_failure (klass);
4023 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4024 mono_loader_clear_error ();
4026 mono_raise_exception (ex);
4030 ICALL_EXPORT MonoReflectionType *
4031 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4039 MONO_ARCH_SAVE_REGS;
4042 mono_raise_exception (mono_get_exception_argument_null ("name"));
4044 domain = ((MonoObject *)type)->vtable->domain;
4045 if (type->type->byref)
4047 klass = mono_class_from_mono_type (type->type);
4049 str = mono_string_to_utf8 (name);
4052 if (klass->exception_type != MONO_EXCEPTION_NONE)
4053 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4056 * If a nested type is generic, return its generic type definition.
4057 * Note that this means that the return value is essentially a
4058 * nested type of the generic type definition of @klass.
4060 * A note in MSDN claims that a generic type definition can have
4061 * nested types that aren't generic. In any case, the container of that
4062 * nested type would be the generic type definition.
4064 if (klass->generic_class)
4065 klass = klass->generic_class->container_class;
4068 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4070 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4071 if (bflags & BFLAGS_Public)
4074 if (bflags & BFLAGS_NonPublic)
4079 if (strcmp (nested->name, str) == 0){
4081 return mono_type_get_object (domain, &nested->byval_arg);
4084 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4090 ICALL_EXPORT MonoArray*
4091 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4100 MonoPtrArray tmp_array;
4102 MONO_ARCH_SAVE_REGS;
4104 domain = ((MonoObject *)type)->vtable->domain;
4105 if (type->type->byref)
4106 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4107 klass = mono_class_from_mono_type (type->type);
4110 * If a nested type is generic, return its generic type definition.
4111 * Note that this means that the return value is essentially the set
4112 * of nested types of the generic type definition of @klass.
4114 * A note in MSDN claims that a generic type definition can have
4115 * nested types that aren't generic. In any case, the container of that
4116 * nested type would be the generic type definition.
4118 if (klass->generic_class)
4119 klass = klass->generic_class->container_class;
4121 mono_ptr_array_init (tmp_array, 1);
4123 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4125 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4126 if (bflags & BFLAGS_Public)
4129 if (bflags & BFLAGS_NonPublic)
4134 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4135 mono_ptr_array_append (tmp_array, member);
4138 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4140 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4141 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4143 mono_ptr_array_destroy (tmp_array);
4148 ICALL_EXPORT MonoReflectionType*
4149 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4152 MonoType *type = NULL;
4153 MonoTypeNameParse info;
4154 gboolean type_resolve;
4156 MONO_ARCH_SAVE_REGS;
4158 /* On MS.NET, this does not fire a TypeResolve event */
4159 type_resolve = TRUE;
4160 str = mono_string_to_utf8 (name);
4161 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4162 if (!mono_reflection_parse_type (str, &info)) {
4164 mono_reflection_free_type_info (&info);
4165 if (throwOnError) /* uhm: this is a parse error, though... */
4166 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4167 /*g_print ("failed parse\n");*/
4171 if (info.assembly.name) {
4173 mono_reflection_free_type_info (&info);
4175 /* 1.0 and 2.0 throw different exceptions */
4176 if (mono_defaults.generic_ilist_class)
4177 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4179 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4184 if (module != NULL) {
4186 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4191 if (assembly_is_dynamic (assembly->assembly)) {
4192 /* Enumerate all modules */
4193 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4197 if (abuilder->modules) {
4198 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4199 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4200 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4206 if (!type && abuilder->loaded_modules) {
4207 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4208 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4209 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4216 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4218 mono_reflection_free_type_info (&info);
4220 MonoException *e = NULL;
4223 e = mono_get_exception_type_load (name, NULL);
4225 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4226 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4228 mono_loader_clear_error ();
4231 mono_raise_exception (e);
4234 } else if (mono_loader_get_last_error ()) {
4236 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4237 mono_loader_clear_error ();
4240 if (type->type == MONO_TYPE_CLASS) {
4241 MonoClass *klass = mono_type_get_class (type);
4243 if (mono_security_enabled () && !klass->exception_type)
4244 /* Some security problems are detected during generic vtable construction */
4245 mono_class_setup_vtable (klass);
4247 /* need to report exceptions ? */
4248 if (throwOnError && klass->exception_type) {
4249 /* report SecurityException (or others) that occured when loading the assembly */
4250 MonoException *exc = mono_class_get_exception_for_failure (klass);
4251 mono_loader_clear_error ();
4252 mono_raise_exception (exc);
4253 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4258 /* g_print ("got it\n"); */
4259 return mono_type_get_object (mono_object_domain (assembly), type);
4263 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4266 gchar *shadow_ini_file;
4269 /* Check for shadow-copied assembly */
4270 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4271 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4273 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4274 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4280 g_free (shadow_ini_file);
4281 if (content != NULL) {
4284 *filename = content;
4291 ICALL_EXPORT MonoString *
4292 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4294 MonoDomain *domain = mono_object_domain (assembly);
4295 MonoAssembly *mass = assembly->assembly;
4296 MonoString *res = NULL;
4301 MONO_ARCH_SAVE_REGS;
4303 if (g_path_is_absolute (mass->image->name)) {
4304 absolute = g_strdup (mass->image->name);
4305 dirname = g_path_get_dirname (absolute);
4307 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4308 dirname = g_strdup (mass->basedir);
4311 replace_shadow_path (domain, dirname, &absolute);
4316 for (i = strlen (absolute) - 1; i >= 0; i--)
4317 if (absolute [i] == '\\')
4322 uri = g_filename_to_uri (absolute, NULL, NULL);
4324 const char *prepend = "file://";
4326 if (*absolute == '/' && *(absolute + 1) == '/') {
4329 prepend = "file:///";
4332 uri = g_strconcat (prepend, absolute, NULL);
4336 res = mono_string_new (domain, uri);
4343 ICALL_EXPORT MonoBoolean
4344 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4346 MonoAssembly *mass = assembly->assembly;
4348 MONO_ARCH_SAVE_REGS;
4350 return mass->in_gac;
4353 ICALL_EXPORT MonoReflectionAssembly*
4354 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4358 MonoImageOpenStatus status;
4360 MONO_ARCH_SAVE_REGS;
4362 name = mono_string_to_utf8 (mname);
4363 res = mono_assembly_load_with_partial_name (name, &status);
4369 return mono_assembly_get_object (mono_domain_get (), res);
4372 ICALL_EXPORT MonoString *
4373 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4375 MonoDomain *domain = mono_object_domain (assembly);
4378 MONO_ARCH_SAVE_REGS;
4380 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4385 ICALL_EXPORT MonoBoolean
4386 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4388 MONO_ARCH_SAVE_REGS;
4390 return assembly->assembly->ref_only;
4393 ICALL_EXPORT MonoString *
4394 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4396 MonoDomain *domain = mono_object_domain (assembly);
4398 MONO_ARCH_SAVE_REGS;
4400 return mono_string_new (domain, assembly->assembly->image->version);
4403 ICALL_EXPORT MonoReflectionMethod*
4404 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4406 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4408 MONO_ARCH_SAVE_REGS;
4412 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4415 ICALL_EXPORT MonoReflectionModule*
4416 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4418 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4421 ICALL_EXPORT MonoArray*
4422 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4424 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4425 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4429 MONO_ARCH_SAVE_REGS;
4431 for (i = 0; i < table->rows; ++i) {
4432 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4433 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4439 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4441 static MonoClass *System_Version = NULL;
4442 static MonoMethod *create_version = NULL;
4446 if (!System_Version) {
4447 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4448 g_assert (System_Version);
4451 if (!create_version) {
4452 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4453 create_version = mono_method_desc_search_in_class (desc, System_Version);
4454 g_assert (create_version);
4455 mono_method_desc_free (desc);
4461 args [3] = &revision;
4462 result = mono_object_new (domain, System_Version);
4463 mono_runtime_invoke (create_version, result, args, NULL);
4468 ICALL_EXPORT MonoArray*
4469 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4471 static MonoClass *System_Reflection_AssemblyName;
4473 MonoDomain *domain = mono_object_domain (assembly);
4475 static MonoMethod *create_culture = NULL;
4476 MonoImage *image = assembly->assembly->image;
4479 MONO_ARCH_SAVE_REGS;
4481 if (!System_Reflection_AssemblyName)
4482 System_Reflection_AssemblyName = mono_class_from_name (
4483 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4485 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4488 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4490 if (count > 0 && !create_culture) {
4491 MonoMethodDesc *desc = mono_method_desc_new (
4492 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4493 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4494 g_assert (create_culture);
4495 mono_method_desc_free (desc);
4498 for (i = 0; i < count; i++) {
4499 MonoReflectionAssemblyName *aname;
4500 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4502 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4504 aname = (MonoReflectionAssemblyName *) mono_object_new (
4505 domain, System_Reflection_AssemblyName);
4507 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4509 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4510 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4511 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4512 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4513 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4514 aname->versioncompat = 1; /* SameMachine (default) */
4515 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4516 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4518 if (create_culture) {
4520 MonoBoolean assembly_ref = 1;
4521 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4522 args [1] = &assembly_ref;
4523 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4526 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4527 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4528 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4530 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4531 /* public key token isn't copied - the class library will
4532 automatically generate it from the public key if required */
4533 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4534 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4536 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4537 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4540 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4543 /* note: this function doesn't return the codebase on purpose (i.e. it can
4544 be used under partial trust as path information isn't present). */
4546 mono_array_setref (result, i, aname);
4551 /* move this in some file in mono/util/ */
4553 g_concat_dir_and_file (const char *dir, const char *file)
4555 g_return_val_if_fail (dir != NULL, NULL);
4556 g_return_val_if_fail (file != NULL, NULL);
4559 * If the directory name doesn't have a / on the end, we need
4560 * to add one so we get a proper path to the file
4562 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4563 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4565 return g_strconcat (dir, file, NULL);
4569 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4571 char *n = mono_string_to_utf8 (name);
4572 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4574 guint32 cols [MONO_MANIFEST_SIZE];
4575 guint32 impl, file_idx;
4579 MONO_ARCH_SAVE_REGS;
4581 for (i = 0; i < table->rows; ++i) {
4582 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4583 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4584 if (strcmp (val, n) == 0)
4588 if (i == table->rows)
4591 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4594 * this code should only be called after obtaining the
4595 * ResourceInfo and handling the other cases.
4597 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4598 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4600 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4605 module = assembly->assembly->image;
4607 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4609 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4612 ICALL_EXPORT gboolean
4613 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4615 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4617 guint32 cols [MONO_MANIFEST_SIZE];
4618 guint32 file_cols [MONO_FILE_SIZE];
4622 MONO_ARCH_SAVE_REGS;
4624 n = mono_string_to_utf8 (name);
4625 for (i = 0; i < table->rows; ++i) {
4626 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4627 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4628 if (strcmp (val, n) == 0)
4632 if (i == table->rows)
4635 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4636 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4639 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4640 case MONO_IMPLEMENTATION_FILE:
4641 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4642 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4643 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4644 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4645 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4646 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4649 info->location = RESOURCE_LOCATION_EMBEDDED;
4652 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4653 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4654 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4655 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4656 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4657 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4659 mono_raise_exception (ex);
4661 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4663 /* Obtain info recursively */
4664 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4665 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4668 case MONO_IMPLEMENTATION_EXP_TYPE:
4669 g_assert_not_reached ();
4677 ICALL_EXPORT MonoObject*
4678 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4680 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4681 MonoArray *result = NULL;
4686 MONO_ARCH_SAVE_REGS;
4688 /* check hash if needed */
4690 n = mono_string_to_utf8 (name);
4691 for (i = 0; i < table->rows; ++i) {
4692 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4693 if (strcmp (val, n) == 0) {
4696 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4697 fn = mono_string_new (mono_object_domain (assembly), n);
4699 return (MonoObject*)fn;
4707 for (i = 0; i < table->rows; ++i) {
4708 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4712 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4715 for (i = 0; i < table->rows; ++i) {
4716 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4717 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4718 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4719 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4724 return (MonoObject*)result;
4727 ICALL_EXPORT MonoArray*
4728 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4730 MonoDomain *domain = mono_domain_get();
4733 int i, j, file_count = 0;
4734 MonoImage **modules;
4735 guint32 module_count, real_module_count;
4736 MonoTableInfo *table;
4737 guint32 cols [MONO_FILE_SIZE];
4738 MonoImage *image = assembly->assembly->image;
4740 g_assert (image != NULL);
4741 g_assert (!assembly_is_dynamic (assembly->assembly));
4743 table = &image->tables [MONO_TABLE_FILE];
4744 file_count = table->rows;
4746 modules = image->modules;
4747 module_count = image->module_count;
4749 real_module_count = 0;
4750 for (i = 0; i < module_count; ++i)
4752 real_module_count ++;
4754 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4755 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4757 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4759 for (i = 0; i < module_count; ++i)
4761 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4765 for (i = 0; i < file_count; ++i, ++j) {
4766 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4767 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4768 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4770 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4772 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4773 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4775 mono_array_setref (res, j, mono_module_get_object (domain, m));
4782 ICALL_EXPORT MonoReflectionMethod*
4783 ves_icall_GetCurrentMethod (void)
4785 MonoMethod *m = mono_method_get_last_managed ();
4787 while (m->is_inflated)
4788 m = ((MonoMethodInflated*)m)->declaring;
4790 return mono_method_get_object (mono_domain_get (), m, NULL);
4795 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4798 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4799 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4800 //method is inflated, we should inflate it on the other class
4801 MonoGenericContext ctx;
4802 ctx.method_inst = inflated->context.method_inst;
4803 ctx.class_inst = inflated->context.class_inst;
4804 if (klass->generic_class)
4805 ctx.class_inst = klass->generic_class->context.class_inst;
4806 else if (klass->generic_container)
4807 ctx.class_inst = klass->generic_container->context.class_inst;
4808 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4811 mono_class_setup_methods (method->klass);
4812 if (method->klass->exception_type)
4814 for (i = 0; i < method->klass->method.count; ++i) {
4815 if (method->klass->methods [i] == method) {
4820 mono_class_setup_methods (klass);
4821 if (klass->exception_type)
4823 g_assert (offset >= 0 && offset < klass->method.count);
4824 return klass->methods [offset];
4827 ICALL_EXPORT MonoReflectionMethod*
4828 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4832 klass = mono_class_from_mono_type (type);
4833 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4835 if (method->klass != klass) {
4836 method = mono_method_get_equivalent_method (method, klass);
4841 klass = method->klass;
4842 return mono_method_get_object (mono_domain_get (), method, klass);
4845 ICALL_EXPORT MonoReflectionMethod*
4846 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4848 return mono_method_get_object (mono_domain_get (), method, NULL);
4851 ICALL_EXPORT MonoReflectionMethodBody*
4852 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4854 return mono_method_body_get_object (mono_domain_get (), method);
4857 ICALL_EXPORT MonoReflectionAssembly*
4858 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4860 MonoMethod *dest = NULL;
4862 MONO_ARCH_SAVE_REGS;
4864 mono_stack_walk_no_il (get_executing, &dest);
4866 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4870 ICALL_EXPORT MonoReflectionAssembly*
4871 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4873 MonoDomain* domain = mono_domain_get ();
4875 MONO_ARCH_SAVE_REGS;
4877 if (!domain->entry_assembly)
4880 return mono_assembly_get_object (domain, domain->entry_assembly);
4883 ICALL_EXPORT MonoReflectionAssembly*
4884 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4889 MONO_ARCH_SAVE_REGS;
4892 mono_stack_walk_no_il (get_executing, &dest);
4894 mono_stack_walk_no_il (get_caller, &dest);
4897 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4900 ICALL_EXPORT MonoString *
4901 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4902 gboolean assembly_qualified)
4904 MonoDomain *domain = mono_object_domain (object);
4905 MonoTypeNameFormat format;
4910 format = assembly_qualified ?
4911 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4912 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4914 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4916 name = mono_type_get_name_full (object->type, format);
4920 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4925 res = mono_string_new (domain, name);
4932 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4934 MonoClass *klass = mono_class_from_mono_type (this->type);
4935 mono_class_init_or_throw (klass);
4936 return mono_security_core_clr_class_level (klass);
4940 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4942 static MonoMethod *create_culture = NULL;
4945 const char *pkey_ptr;
4947 MonoBoolean assembly_ref = 0;
4949 MONO_ARCH_SAVE_REGS;
4951 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4952 aname->major = name->major;
4953 aname->minor = name->minor;
4954 aname->build = name->build;
4955 aname->flags = name->flags;
4956 aname->revision = name->revision;
4957 aname->hashalg = name->hash_alg;
4958 aname->versioncompat = 1; /* SameMachine (default) */
4959 aname->processor_architecture = name->arch;
4961 if (by_default_version)
4962 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4965 if (absolute != NULL && *absolute != '\0') {
4966 const gchar *prepend = "file://";
4969 codebase = g_strdup (absolute);
4974 for (i = strlen (codebase) - 1; i >= 0; i--)
4975 if (codebase [i] == '\\')
4978 if (*codebase == '/' && *(codebase + 1) == '/') {
4981 prepend = "file:///";
4985 result = g_strconcat (prepend, codebase, NULL);
4991 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4995 if (!create_culture) {
4996 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4997 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4998 g_assert (create_culture);
4999 mono_method_desc_free (desc);
5002 if (name->culture) {
5003 args [0] = mono_string_new (domain, name->culture);
5004 args [1] = &assembly_ref;
5005 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5008 if (name->public_key) {
5009 pkey_ptr = (char*)name->public_key;
5010 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5012 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5013 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5014 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5015 } else if (default_publickey) {
5016 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5017 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5020 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5021 if (name->public_key_token [0]) {
5025 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5026 p = mono_array_addr (aname->keyToken, char, 0);
5028 for (i = 0, j = 0; i < 8; i++) {
5029 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5030 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5033 } else if (default_token) {
5034 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5038 ICALL_EXPORT MonoString *
5039 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5041 MonoDomain *domain = mono_object_domain (assembly);
5042 MonoAssembly *mass = assembly->assembly;
5046 name = mono_stringify_assembly_name (&mass->aname);
5047 res = mono_string_new (domain, name);
5054 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5057 MonoAssembly *mass = assembly->assembly;
5059 MONO_ARCH_SAVE_REGS;
5061 if (g_path_is_absolute (mass->image->name)) {
5062 fill_reflection_assembly_name (mono_object_domain (assembly),
5063 aname, &mass->aname, mass->image->name, TRUE,
5067 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5069 fill_reflection_assembly_name (mono_object_domain (assembly),
5070 aname, &mass->aname, absolute, TRUE, TRUE,
5077 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5080 MonoImageOpenStatus status = MONO_IMAGE_OK;
5083 MonoAssemblyName name;
5086 MONO_ARCH_SAVE_REGS;
5088 filename = mono_string_to_utf8 (fname);
5090 dirname = g_path_get_dirname (filename);
5091 replace_shadow_path (mono_domain_get (), dirname, &filename);
5094 image = mono_image_open (filename, &status);
5100 if (status == MONO_IMAGE_IMAGE_INVALID)
5101 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5103 exc = mono_get_exception_file_not_found2 (NULL, fname);
5104 mono_raise_exception (exc);
5107 res = mono_assembly_fill_assembly_name (image, &name);
5109 mono_image_close (image);
5111 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5114 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5118 mono_image_close (image);
5121 ICALL_EXPORT MonoBoolean
5122 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5123 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5125 MonoBoolean result = FALSE;
5126 MonoDeclSecurityEntry entry;
5128 /* SecurityAction.RequestMinimum */
5129 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5130 *minimum = entry.blob;
5131 *minLength = entry.size;
5134 /* SecurityAction.RequestOptional */
5135 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5136 *optional = entry.blob;
5137 *optLength = entry.size;
5140 /* SecurityAction.RequestRefuse */
5141 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5142 *refused = entry.blob;
5143 *refLength = entry.size;
5151 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5155 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5157 guint32 attrs, visibility;
5159 /* we start the count from 1 because we skip the special type <Module> */
5162 for (i = 1; i < tdef->rows; ++i) {
5163 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5164 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5165 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5169 count = tdef->rows - 1;
5171 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5172 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5174 for (i = 1; i < tdef->rows; ++i) {
5175 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5176 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5177 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5179 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5180 g_assert (!mono_loader_get_last_error ()); /* Plug any leaks */
5183 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5185 MonoException *ex = mono_error_convert_to_exception (&error);
5186 mono_array_setref (*exceptions, count, ex);
5195 ICALL_EXPORT MonoArray*
5196 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5198 MonoArray *res = NULL;
5199 MonoArray *exceptions = NULL;
5200 MonoImage *image = NULL;
5201 MonoTableInfo *table = NULL;
5204 int i, len, ex_count;
5206 MONO_ARCH_SAVE_REGS;
5208 domain = mono_object_domain (assembly);
5210 g_assert (!assembly_is_dynamic (assembly->assembly));
5211 image = assembly->assembly->image;
5212 table = &image->tables [MONO_TABLE_FILE];
5213 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5215 /* Append data from all modules in the assembly */
5216 for (i = 0; i < table->rows; ++i) {
5217 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5218 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5221 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5222 /* Append the new types to the end of the array */
5223 if (mono_array_length (res2) > 0) {
5225 MonoArray *res3, *ex3;
5227 len1 = mono_array_length (res);
5228 len2 = mono_array_length (res2);
5230 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5231 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5232 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5235 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5236 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5237 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5244 /* the ReflectionTypeLoadException must have all the types (Types property),
5245 * NULL replacing types which throws an exception. The LoaderException must
5246 * contain all exceptions for NULL items.
5249 len = mono_array_length (res);
5252 for (i = 0; i < len; i++) {
5253 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5257 klass = mono_type_get_class (t->type);
5258 if ((klass != NULL) && klass->exception_type) {
5259 /* keep the class in the list */
5260 list = g_list_append (list, klass);
5261 /* and replace Type with NULL */
5262 mono_array_setref (res, i, NULL);
5269 if (list || ex_count) {
5271 MonoException *exc = NULL;
5272 MonoArray *exl = NULL;
5273 int j, length = g_list_length (list) + ex_count;
5275 mono_loader_clear_error ();
5277 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5278 /* Types for which mono_class_get_checked () succeeded */
5279 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5280 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5281 mono_array_setref (exl, i, exc);
5283 /* Types for which it don't */
5284 for (j = 0; j < mono_array_length (exceptions); ++j) {
5285 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5287 g_assert (i < length);
5288 mono_array_setref (exl, i, exc);
5295 exc = mono_get_exception_reflection_type_load (res, exl);
5296 mono_loader_clear_error ();
5297 mono_raise_exception (exc);
5303 ICALL_EXPORT gboolean
5304 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5306 MonoAssemblyName aname;
5307 MonoDomain *domain = mono_object_domain (name);
5309 gboolean is_version_defined;
5310 gboolean is_token_defined;
5312 aname.public_key = NULL;
5313 val = mono_string_to_utf8 (assname);
5314 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5315 g_free ((guint8*) aname.public_key);
5320 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5321 FALSE, is_token_defined);
5323 mono_assembly_name_free (&aname);
5324 g_free ((guint8*) aname.public_key);
5330 ICALL_EXPORT MonoReflectionType*
5331 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5334 MonoDomain *domain = mono_object_domain (module);
5337 MONO_ARCH_SAVE_REGS;
5339 g_assert (module->image);
5341 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5342 /* These images do not have a global type */
5345 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5346 mono_error_raise_exception (&error);
5347 return mono_type_get_object (domain, &klass->byval_arg);
5351 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5353 /*if (module->image)
5354 mono_image_close (module->image);*/
5357 ICALL_EXPORT MonoString*
5358 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5360 MonoDomain *domain = mono_object_domain (module);
5362 MONO_ARCH_SAVE_REGS;
5364 g_assert (module->image);
5365 return mono_string_new (domain, module->image->guid);
5368 ICALL_EXPORT gpointer
5369 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5372 if (module->image && module->image->is_module_handle)
5373 return module->image->raw_data;
5376 return (gpointer) (-1);
5380 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5382 if (image_is_dynamic (image)) {
5383 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5384 *pe_kind = dyn->pe_kind;
5385 *machine = dyn->machine;
5388 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5389 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5394 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5396 return (image->md_version_major << 16) | (image->md_version_minor);
5399 ICALL_EXPORT MonoArray*
5400 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5402 MonoArray *exceptions;
5405 MONO_ARCH_SAVE_REGS;
5408 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5410 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5411 for (i = 0; i < mono_array_length (exceptions); ++i) {
5412 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5414 mono_raise_exception (ex);
5421 mono_memberref_is_method (MonoImage *image, guint32 token)
5423 if (!image_is_dynamic (image)) {
5424 guint32 cols [MONO_MEMBERREF_SIZE];
5426 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5427 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5428 mono_metadata_decode_blob_size (sig, &sig);
5429 return (*sig != 0x6);
5431 MonoClass *handle_class;
5433 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5436 return mono_defaults.methodhandle_class == handle_class;
5441 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5444 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5445 mono_array_addr (type_args, MonoType*, 0));
5447 context->class_inst = NULL;
5449 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5450 mono_array_addr (method_args, MonoType*, 0));
5452 context->method_inst = NULL;
5455 ICALL_EXPORT MonoType*
5456 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5459 int table = mono_metadata_token_table (token);
5460 int index = mono_metadata_token_index (token);
5461 MonoGenericContext context;
5464 *resolve_error = ResolveTokenError_Other;
5466 /* Validate token */
5467 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5468 (table != MONO_TABLE_TYPESPEC)) {
5469 *resolve_error = ResolveTokenError_BadTable;
5473 if (image_is_dynamic (image)) {
5474 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5475 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5476 return klass ? &klass->byval_arg : NULL;
5479 init_generic_context_from_args (&context, type_args, method_args);
5480 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5481 return klass ? &klass->byval_arg : NULL;
5484 if ((index <= 0) || (index > image->tables [table].rows)) {
5485 *resolve_error = ResolveTokenError_OutOfRange;
5489 init_generic_context_from_args (&context, type_args, method_args);
5490 klass = mono_class_get_checked (image, token, &error);
5492 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5493 mono_error_raise_exception (&error);
5496 return &klass->byval_arg;
5501 ICALL_EXPORT MonoMethod*
5502 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5504 int table = mono_metadata_token_table (token);
5505 int index = mono_metadata_token_index (token);
5506 MonoGenericContext context;
5509 *error = ResolveTokenError_Other;
5511 /* Validate token */
5512 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5513 (table != MONO_TABLE_MEMBERREF)) {
5514 *error = ResolveTokenError_BadTable;
5518 if (image_is_dynamic (image)) {
5519 if (table == MONO_TABLE_METHOD)
5520 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5522 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5523 *error = ResolveTokenError_BadTable;
5527 init_generic_context_from_args (&context, type_args, method_args);
5528 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5531 if ((index <= 0) || (index > image->tables [table].rows)) {
5532 *error = ResolveTokenError_OutOfRange;
5535 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5536 *error = ResolveTokenError_BadTable;
5540 init_generic_context_from_args (&context, type_args, method_args);
5541 method = mono_get_method_full (image, token, NULL, &context);
5543 if (mono_loader_get_last_error ())
5544 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5549 ICALL_EXPORT MonoString*
5550 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5552 int index = mono_metadata_token_index (token);
5554 *error = ResolveTokenError_Other;
5556 /* Validate token */
5557 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5558 *error = ResolveTokenError_BadTable;
5562 if (image_is_dynamic (image))
5563 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5565 if ((index <= 0) || (index >= image->heap_us.size)) {
5566 *error = ResolveTokenError_OutOfRange;
5570 /* FIXME: What to do if the index points into the middle of a string ? */
5572 return mono_ldstr (mono_domain_get (), image, index);
5575 ICALL_EXPORT MonoClassField*
5576 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5580 int table = mono_metadata_token_table (token);
5581 int index = mono_metadata_token_index (token);
5582 MonoGenericContext context;
5583 MonoClassField *field;
5585 *resolve_error = ResolveTokenError_Other;
5587 /* Validate token */
5588 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5589 *resolve_error = ResolveTokenError_BadTable;
5593 if (image_is_dynamic (image)) {
5594 if (table == MONO_TABLE_FIELD)
5595 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5597 if (mono_memberref_is_method (image, token)) {
5598 *resolve_error = ResolveTokenError_BadTable;
5602 init_generic_context_from_args (&context, type_args, method_args);
5603 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5606 if ((index <= 0) || (index > image->tables [table].rows)) {
5607 *resolve_error = ResolveTokenError_OutOfRange;
5610 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5611 *resolve_error = ResolveTokenError_BadTable;
5615 init_generic_context_from_args (&context, type_args, method_args);
5616 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5617 mono_error_raise_exception (&error);
5623 ICALL_EXPORT MonoObject*
5624 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5626 int table = mono_metadata_token_table (token);
5628 *error = ResolveTokenError_Other;
5631 case MONO_TABLE_TYPEDEF:
5632 case MONO_TABLE_TYPEREF:
5633 case MONO_TABLE_TYPESPEC: {
5634 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5636 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5640 case MONO_TABLE_METHOD:
5641 case MONO_TABLE_METHODSPEC: {
5642 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5644 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5648 case MONO_TABLE_FIELD: {
5649 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5651 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5655 case MONO_TABLE_MEMBERREF:
5656 if (mono_memberref_is_method (image, token)) {
5657 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5659 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5664 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5666 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5673 *error = ResolveTokenError_BadTable;
5679 ICALL_EXPORT MonoArray*
5680 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5682 int table = mono_metadata_token_table (token);
5683 int idx = mono_metadata_token_index (token);
5684 MonoTableInfo *tables = image->tables;
5689 *error = ResolveTokenError_OutOfRange;
5691 /* FIXME: Support other tables ? */
5692 if (table != MONO_TABLE_STANDALONESIG)
5695 if (image_is_dynamic (image))
5698 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5701 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5703 ptr = mono_metadata_blob_heap (image, sig);
5704 len = mono_metadata_decode_blob_size (ptr, &ptr);
5706 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5707 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5711 ICALL_EXPORT MonoReflectionType*
5712 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5715 int isbyref = 0, rank;
5716 char *str = mono_string_to_utf8 (smodifiers);
5719 MONO_ARCH_SAVE_REGS;
5721 klass = mono_class_from_mono_type (tb->type.type);
5723 /* logic taken from mono_reflection_parse_type(): keep in sync */
5727 if (isbyref) { /* only one level allowed by the spec */
5734 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5737 klass = mono_ptr_class_get (&klass->byval_arg);
5738 mono_class_init (klass);
5749 else if (*p != '*') { /* '*' means unknown lower bound */
5760 klass = mono_array_class_get (klass, rank);
5761 mono_class_init (klass);
5768 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5771 ICALL_EXPORT MonoBoolean
5772 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5777 MONO_ARCH_SAVE_REGS;
5780 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5786 check_for_invalid_type (MonoClass *klass)
5790 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5793 name = mono_type_get_full_name (klass);
5794 str = mono_string_new (mono_domain_get (), name);
5796 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5799 ICALL_EXPORT MonoReflectionType *
5800 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5802 MonoClass *klass, *aklass;
5804 MONO_ARCH_SAVE_REGS;
5806 klass = mono_class_from_mono_type (type->type);
5807 check_for_invalid_type (klass);
5809 if (rank == 0) //single dimentional array
5810 aklass = mono_array_class_get (klass, 1);
5812 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5814 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5817 ICALL_EXPORT MonoReflectionType *
5818 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5822 MONO_ARCH_SAVE_REGS;
5824 klass = mono_class_from_mono_type (type->type);
5825 mono_class_init_or_throw (klass);
5826 check_for_invalid_type (klass);
5828 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5831 ICALL_EXPORT MonoReflectionType *
5832 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5834 MonoClass *klass, *pklass;
5836 klass = mono_class_from_mono_type (type->type);
5837 mono_class_init_or_throw (klass);
5838 check_for_invalid_type (klass);
5840 pklass = mono_ptr_class_get (type->type);
5842 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5845 ICALL_EXPORT MonoObject *
5846 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5847 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5849 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5850 MonoObject *delegate;
5852 MonoMethod *method = info->method;
5854 MONO_ARCH_SAVE_REGS;
5856 mono_class_init_or_throw (delegate_class);
5858 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5860 if (mono_security_core_clr_enabled ()) {
5861 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5865 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5867 if (method_is_dynamic (method)) {
5868 /* Creating a trampoline would leak memory */
5869 func = mono_compile_method (method);
5871 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5872 method = mono_object_get_virtual_method (target, method);
5873 func = mono_create_ftnptr (mono_domain_get (),
5874 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5877 mono_delegate_ctor_with_method (delegate, target, func, method);
5883 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5885 /* Reset the invoke impl to the default one */
5886 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5890 * Magic number to convert a time which is relative to
5891 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5893 #define EPOCH_ADJUST ((guint64)62135596800LL)
5896 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5898 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5901 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5903 convert_to_absolute_date(SYSTEMTIME *date)
5905 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5906 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5907 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5908 /* from the calendar FAQ */
5909 int a = (14 - date->wMonth) / 12;
5910 int y = date->wYear - a;
5911 int m = date->wMonth + 12 * a - 2;
5912 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5914 /* d is now the day of the week for the first of the month (0 == Sunday) */
5916 int day_of_week = date->wDayOfWeek;
5918 /* set day_in_month to the first day in the month which falls on day_of_week */
5919 int day_in_month = 1 + (day_of_week - d);
5920 if (day_in_month <= 0)
5923 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5924 date->wDay = day_in_month + (date->wDay - 1) * 7;
5925 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5932 * Return's the offset from GMT of a local time.
5934 * tm is a local time
5935 * t is the same local time as seconds.
5938 gmt_offset(struct tm *tm, time_t t)
5940 #if defined (HAVE_TM_GMTOFF)
5941 return tm->tm_gmtoff;
5946 g.tm_isdst = tm->tm_isdst;
5948 return (int)difftime(t, t2);
5953 * This is heavily based on zdump.c from glibc 2.2.
5955 * * data[0]: start of daylight saving time (in DateTime ticks).
5956 * * data[1]: end of daylight saving time (in DateTime ticks).
5957 * * data[2]: utcoffset (in TimeSpan ticks).
5958 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5959 * * name[0]: name of this timezone when not daylight saving.
5960 * * name[1]: name of this timezone when daylight saving.
5962 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5963 * the class library allows years between 1 and 9999.
5965 * Returns true on success and zero on failure.
5967 ICALL_EXPORT guint32
5968 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5971 MonoDomain *domain = mono_domain_get ();
5972 struct tm start, tt;
5975 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5976 int day, transitioned;
5979 gmtoff_st = gmtoff_ds = transitioned = 0;
5981 MONO_ARCH_SAVE_REGS;
5983 MONO_CHECK_ARG_NULL (data);
5984 MONO_CHECK_ARG_NULL (names);
5986 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5987 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5990 * no info is better than crashing: we'll need our own tz data
5991 * to make this work properly, anyway. The range is probably
5992 * reduced to 1970 .. 2037 because that is what mktime is
5993 * guaranteed to support (we get into an infinite loop
5997 memset (&start, 0, sizeof (start));
6000 start.tm_year = year-1900;
6002 t = mktime (&start);
6004 if ((year < 1970) || (year > 2037) || (t == -1)) {
6006 tt = *localtime (&t);
6007 strftime (tzone, sizeof (tzone), "%Z", &tt);
6008 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6009 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6013 gmtoff = gmt_offset (&start, t);
6015 /* For each day of the year, calculate the tm_gmtoff. */
6016 for (day = 0; day < 365 && transitioned < 2; day++) {
6019 tt = *localtime (&t);
6021 gmtoff_after = gmt_offset(&tt, t);
6023 /* Daylight saving starts or ends here. */
6024 if (gmtoff_after != gmtoff) {
6028 /* Try to find the exact hour when daylight saving starts/ends. */
6032 tt1 = *localtime (&t1);
6033 } while (gmt_offset (&tt1, t1) != gmtoff);
6035 /* Try to find the exact minute when daylight saving starts/ends. */
6038 tt1 = *localtime (&t1);
6039 } while (gmt_offset (&tt1, t1) == gmtoff);
6041 strftime (tzone, sizeof (tzone), "%Z", &tt);
6043 /* Write data, if we're already in daylight saving, we're done. */
6045 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6046 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6047 if (gmtoff_ds == 0) {
6049 gmtoff_ds = gmtoff_after;
6056 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6057 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6058 if (gmtoff_ds == 0) {
6059 gmtoff_st = gmtoff_after;
6065 /* This is only set once when we enter daylight saving. */
6067 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6068 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6070 gmtoff = gmt_offset (&tt, t);
6074 if (transitioned < 2) {
6075 strftime (tzone, sizeof (tzone), "%Z", &tt);
6076 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6077 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6078 mono_array_set ((*data), gint64, 0, 0);
6079 mono_array_set ((*data), gint64, 1, 0);
6080 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6081 mono_array_set ((*data), gint64, 3, 0);
6086 MonoDomain *domain = mono_domain_get ();
6087 TIME_ZONE_INFORMATION tz_info;
6092 tz_id = GetTimeZoneInformation (&tz_info);
6093 if (tz_id == TIME_ZONE_ID_INVALID)
6096 MONO_CHECK_ARG_NULL (data);
6097 MONO_CHECK_ARG_NULL (names);
6099 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6100 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6102 for (i = 0; i < 32; ++i)
6103 if (!tz_info.DaylightName [i])
6105 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6106 for (i = 0; i < 32; ++i)
6107 if (!tz_info.StandardName [i])
6109 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6111 if ((year <= 1601) || (year > 30827)) {
6113 * According to MSDN, the MS time functions can't handle dates outside
6119 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6120 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6121 tz_info.StandardDate.wYear = year;
6122 convert_to_absolute_date(&tz_info.StandardDate);
6123 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6128 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6129 tz_info.DaylightDate.wYear = year;
6130 convert_to_absolute_date(&tz_info.DaylightDate);
6131 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6136 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6138 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6139 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6147 static inline gint32
6148 mono_array_get_byte_length (MonoArray *array)
6154 klass = array->obj.vtable->klass;
6156 if (array->bounds == NULL)
6157 length = array->max_length;
6160 for (i = 0; i < klass->rank; ++ i)
6161 length *= array->bounds [i].length;
6164 switch (klass->element_class->byval_arg.type) {
6167 case MONO_TYPE_BOOLEAN:
6171 case MONO_TYPE_CHAR:
6179 return length * sizeof (gpointer);
6190 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6192 MONO_ARCH_SAVE_REGS;
6194 return mono_array_get_byte_length (array);
6198 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6200 MONO_ARCH_SAVE_REGS;
6202 return mono_array_get (array, gint8, idx);
6206 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6208 MONO_ARCH_SAVE_REGS;
6210 mono_array_set (array, gint8, idx, value);
6213 ICALL_EXPORT MonoBoolean
6214 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6216 guint8 *src_buf, *dest_buf;
6218 MONO_ARCH_SAVE_REGS;
6220 /* This is called directly from the class libraries without going through the managed wrapper */
6221 MONO_CHECK_ARG_NULL (src);
6222 MONO_CHECK_ARG_NULL (dest);
6224 /* watch out for integer overflow */
6225 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6228 src_buf = (guint8 *)src->vector + src_offset;
6229 dest_buf = (guint8 *)dest->vector + dest_offset;
6232 memcpy (dest_buf, src_buf, count);
6234 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6239 #ifndef DISABLE_REMOTING
6240 ICALL_EXPORT MonoObject *
6241 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6243 MonoDomain *domain = mono_object_domain (this);
6245 MonoRealProxy *rp = ((MonoRealProxy *)this);
6246 MonoTransparentProxy *tp;
6250 MONO_ARCH_SAVE_REGS;
6252 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6253 tp = (MonoTransparentProxy*) res;
6255 MONO_OBJECT_SETREF (tp, rp, rp);
6256 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6257 klass = mono_class_from_mono_type (type);
6259 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6260 tp->remote_class = mono_remote_class (domain, class_name, klass);
6262 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6266 ICALL_EXPORT MonoReflectionType *
6267 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6269 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6273 /* System.Environment */
6276 ves_icall_System_Environment_get_UserName (void)
6278 MONO_ARCH_SAVE_REGS;
6280 /* using glib is more portable */
6281 return mono_string_new (mono_domain_get (), g_get_user_name ());
6285 ICALL_EXPORT MonoString *
6286 ves_icall_System_Environment_get_MachineName (void)
6288 #if defined (HOST_WIN32)
6293 len = MAX_COMPUTERNAME_LENGTH + 1;
6294 buf = g_new (gunichar2, len);
6297 if (GetComputerName (buf, (PDWORD) &len))
6298 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6302 #elif !defined(DISABLE_SOCKETS)
6306 if (gethostname (buf, sizeof (buf)) == 0)
6307 result = mono_string_new (mono_domain_get (), buf);
6313 return mono_string_new (mono_domain_get (), "mono");
6318 ves_icall_System_Environment_get_Platform (void)
6320 #if defined (TARGET_WIN32)
6323 #elif defined(__MACH__)
6326 // Notice that the value is hidden from user code, and only exposed
6327 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6328 // define and making assumptions based on Unix/128/4 values before there
6329 // was a MacOS define. Lots of code would assume that not-Unix meant
6330 // Windows, but in this case, it would be OSX.
6339 ICALL_EXPORT MonoString *
6340 ves_icall_System_Environment_get_NewLine (void)
6342 MONO_ARCH_SAVE_REGS;
6344 #if defined (HOST_WIN32)
6345 return mono_string_new (mono_domain_get (), "\r\n");
6347 return mono_string_new (mono_domain_get (), "\n");
6351 ICALL_EXPORT MonoString *
6352 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6357 MONO_ARCH_SAVE_REGS;
6362 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6363 value = g_getenv (utf8_name);
6370 return mono_string_new (mono_domain_get (), value);
6374 * There is no standard way to get at environ.
6377 #ifndef __MINGW32_VERSION
6378 #if defined(__APPLE__) && !defined (__arm__)
6379 /* Apple defines this in crt_externs.h but doesn't provide that header for
6380 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6381 * in fact exist on all implementations (so far)
6383 gchar ***_NSGetEnviron(void);
6384 #define environ (*_NSGetEnviron())
6392 ICALL_EXPORT MonoArray *
6393 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6404 env_strings = GetEnvironmentStrings();
6407 env_string = env_strings;
6408 while (*env_string != '\0') {
6409 /* weird case that MS seems to skip */
6410 if (*env_string != '=')
6412 while (*env_string != '\0')
6418 domain = mono_domain_get ();
6419 names = mono_array_new (domain, mono_defaults.string_class, n);
6423 env_string = env_strings;
6424 while (*env_string != '\0') {
6425 /* weird case that MS seems to skip */
6426 if (*env_string != '=') {
6427 equal_str = wcschr(env_string, '=');
6428 g_assert(equal_str);
6429 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6430 mono_array_setref (names, n, str);
6433 while (*env_string != '\0')
6438 FreeEnvironmentStrings (env_strings);
6450 MONO_ARCH_SAVE_REGS;
6453 for (e = environ; *e != 0; ++ e)
6456 domain = mono_domain_get ();
6457 names = mono_array_new (domain, mono_defaults.string_class, n);
6460 for (e = environ; *e != 0; ++ e) {
6461 parts = g_strsplit (*e, "=", 2);
6463 str = mono_string_new (domain, *parts);
6464 mono_array_setref (names, n, str);
6477 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6479 #if !GLIB_CHECK_VERSION(2,4,0)
6480 #define g_setenv(a,b,c) setenv(a,b,c)
6481 #define g_unsetenv(a) unsetenv(a)
6485 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6488 gunichar2 *utf16_name, *utf16_value;
6490 gchar *utf8_name, *utf8_value;
6494 MONO_ARCH_SAVE_REGS;
6497 utf16_name = mono_string_to_utf16 (name);
6498 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6499 SetEnvironmentVariable (utf16_name, NULL);
6500 g_free (utf16_name);
6504 utf16_value = mono_string_to_utf16 (value);
6506 SetEnvironmentVariable (utf16_name, utf16_value);
6508 g_free (utf16_name);
6509 g_free (utf16_value);
6511 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6513 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6514 g_unsetenv (utf8_name);
6519 utf8_value = mono_string_to_utf8_checked (value, &error);
6520 if (!mono_error_ok (&error)) {
6522 mono_error_raise_exception (&error);
6524 g_setenv (utf8_name, utf8_value, TRUE);
6527 g_free (utf8_value);
6532 ves_icall_System_Environment_Exit (int result)
6534 MONO_ARCH_SAVE_REGS;
6536 mono_environment_exitcode_set (result);
6538 /* FIXME: There are some cleanup hangs that should be worked out, but
6539 * if the program is going to exit, everything will be cleaned up when
6540 * NaCl exits anyway.
6542 #ifndef __native_client__
6543 if (!mono_runtime_try_shutdown ())
6544 mono_thread_exit ();
6546 /* Suspend all managed threads since the runtime is going away */
6547 mono_thread_suspend_all_other_threads ();
6549 mono_runtime_quit ();
6552 /* we may need to do some cleanup here... */
6556 ICALL_EXPORT MonoString*
6557 ves_icall_System_Environment_GetGacPath (void)
6559 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6562 ICALL_EXPORT MonoString*
6563 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6565 #if defined (HOST_WIN32)
6566 #ifndef CSIDL_FLAG_CREATE
6567 #define CSIDL_FLAG_CREATE 0x8000
6570 WCHAR path [MAX_PATH];
6571 /* Create directory if no existing */
6572 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6576 return mono_string_new_utf16 (mono_domain_get (), path, len);
6579 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6581 return mono_string_new (mono_domain_get (), "");
6584 ICALL_EXPORT MonoArray *
6585 ves_icall_System_Environment_GetLogicalDrives (void)
6587 gunichar2 buf [256], *ptr, *dname;
6589 guint initial_size = 127, size = 128;
6592 MonoString *drivestr;
6593 MonoDomain *domain = mono_domain_get ();
6596 MONO_ARCH_SAVE_REGS;
6601 while (size > initial_size) {
6602 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6603 if (size > initial_size) {
6606 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6607 initial_size = size;
6621 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6626 while (*u16) { u16++; len ++; }
6627 drivestr = mono_string_new_utf16 (domain, dname, len);
6628 mono_array_setref (result, ndrives++, drivestr);
6638 ICALL_EXPORT MonoString *
6639 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6641 gunichar2 volume_name [MAX_PATH + 1];
6643 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6645 return mono_string_from_utf16 (volume_name);
6648 ICALL_EXPORT MonoString *
6649 ves_icall_System_Environment_InternalGetHome (void)
6651 MONO_ARCH_SAVE_REGS;
6653 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6656 static const char *encodings [] = {
6658 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6659 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6660 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6662 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6663 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6664 "x_unicode_2_0_utf_7",
6666 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6667 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6669 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6672 "unicodefffe", "utf_16be",
6679 * Returns the internal codepage, if the value of "int_code_page" is
6680 * 1 at entry, and we can not compute a suitable code page number,
6681 * returns the code page as a string
6683 ICALL_EXPORT MonoString*
6684 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6689 char *codepage = NULL;
6691 int want_name = *int_code_page;
6694 *int_code_page = -1;
6695 MONO_ARCH_SAVE_REGS;
6697 g_get_charset (&cset);
6698 c = codepage = strdup (cset);
6699 for (c = codepage; *c; c++){
6700 if (isascii (*c) && isalpha (*c))
6705 /* g_print ("charset: %s\n", cset); */
6707 /* handle some common aliases */
6710 for (i = 0; p != 0; ){
6711 if ((gssize) p < 7){
6713 p = encodings [++i];
6716 if (strcmp (p, codepage) == 0){
6717 *int_code_page = code;
6720 p = encodings [++i];
6723 if (strstr (codepage, "utf_8") != NULL)
6724 *int_code_page |= 0x10000000;
6727 if (want_name && *int_code_page == -1)
6728 return mono_string_new (mono_domain_get (), cset);
6733 ICALL_EXPORT MonoBoolean
6734 ves_icall_System_Environment_get_HasShutdownStarted (void)
6736 if (mono_runtime_is_shutting_down ())
6739 if (mono_domain_is_unloading (mono_domain_get ()))
6746 ves_icall_System_Environment_BroadcastSettingChange (void)
6749 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6754 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6755 MonoReflectionMethod *method,
6756 MonoArray *out_args)
6758 MONO_ARCH_SAVE_REGS;
6760 mono_message_init (mono_object_domain (this), this, method, out_args);
6763 #ifndef DISABLE_REMOTING
6764 ICALL_EXPORT MonoBoolean
6765 ves_icall_IsTransparentProxy (MonoObject *proxy)
6767 MONO_ARCH_SAVE_REGS;
6772 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6778 ICALL_EXPORT MonoReflectionMethod *
6779 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6780 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6784 MonoMethod **vtable;
6785 MonoMethod *res = NULL;
6787 MONO_CHECK_ARG_NULL (rtype);
6788 MONO_CHECK_ARG_NULL (rmethod);
6790 method = rmethod->method;
6791 klass = mono_class_from_mono_type (rtype->type);
6792 mono_class_init_or_throw (klass);
6794 if (MONO_CLASS_IS_INTERFACE (klass))
6797 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6800 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6801 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6807 mono_class_setup_vtable (klass);
6808 vtable = klass->vtable;
6810 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6811 gboolean variance_used = FALSE;
6812 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6813 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6815 res = vtable [offs + method->slot];
6817 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6820 if (method->slot != -1)
6821 res = vtable [method->slot];
6827 return mono_method_get_object (mono_domain_get (), res, NULL);
6831 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6836 MONO_ARCH_SAVE_REGS;
6838 klass = mono_class_from_mono_type (type->type);
6839 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6841 mono_vtable_set_is_remote (vtable, enable);
6844 #else /* DISABLE_REMOTING */
6847 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6849 g_assert_not_reached ();
6854 ICALL_EXPORT MonoObject *
6855 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6860 MONO_ARCH_SAVE_REGS;
6862 domain = mono_object_domain (type);
6863 klass = mono_class_from_mono_type (type->type);
6864 mono_class_init_or_throw (klass);
6866 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6867 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6869 if (klass->rank >= 1) {
6870 g_assert (klass->rank == 1);
6871 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6873 /* Bypass remoting object creation check */
6874 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6878 ICALL_EXPORT MonoString *
6879 ves_icall_System_IO_get_temp_path (void)
6881 MONO_ARCH_SAVE_REGS;
6883 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6886 #ifndef PLATFORM_NO_DRIVEINFO
6887 ICALL_EXPORT MonoBoolean
6888 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6889 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6893 ULARGE_INTEGER wapi_free_bytes_avail;
6894 ULARGE_INTEGER wapi_total_number_of_bytes;
6895 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6897 MONO_ARCH_SAVE_REGS;
6899 *error = ERROR_SUCCESS;
6900 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6901 &wapi_total_number_of_free_bytes);
6904 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6905 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6906 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6908 *free_bytes_avail = 0;
6909 *total_number_of_bytes = 0;
6910 *total_number_of_free_bytes = 0;
6911 *error = GetLastError ();
6917 ICALL_EXPORT guint32
6918 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6920 MONO_ARCH_SAVE_REGS;
6922 return GetDriveType (mono_string_chars (root_path_name));
6926 ICALL_EXPORT gpointer
6927 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6929 MONO_ARCH_SAVE_REGS;
6931 return mono_compile_method (method);
6934 ICALL_EXPORT MonoString *
6935 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6940 MONO_ARCH_SAVE_REGS;
6942 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6944 #if defined (HOST_WIN32)
6945 /* Avoid mixing '/' and '\\' */
6948 for (i = strlen (path) - 1; i >= 0; i--)
6949 if (path [i] == '/')
6953 mcpath = mono_string_new (mono_domain_get (), path);
6960 get_bundled_app_config (void)
6962 const gchar *app_config;
6965 gchar *config_file_name, *config_file_path;
6969 MONO_ARCH_SAVE_REGS;
6971 domain = mono_domain_get ();
6972 file = domain->setup->configuration_file;
6976 // Retrieve config file and remove the extension
6977 config_file_name = mono_string_to_utf8 (file);
6978 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6979 if (!config_file_path)
6980 config_file_path = config_file_name;
6981 len = strlen (config_file_path) - strlen (".config");
6982 module = g_malloc0 (len + 1);
6983 memcpy (module, config_file_path, len);
6984 // Get the config file from the module name
6985 app_config = mono_config_string_for_assembly_file (module);
6988 if (config_file_name != config_file_path)
6989 g_free (config_file_name);
6990 g_free (config_file_path);
6995 return mono_string_new (mono_domain_get (), app_config);
6999 get_bundled_machine_config (void)
7001 const gchar *machine_config;
7003 MONO_ARCH_SAVE_REGS;
7005 machine_config = mono_get_machine_config ();
7007 if (!machine_config)
7010 return mono_string_new (mono_domain_get (), machine_config);
7013 ICALL_EXPORT MonoString *
7014 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7019 MONO_ARCH_SAVE_REGS;
7021 path = g_path_get_dirname (mono_get_config_dir ());
7023 #if defined (HOST_WIN32)
7024 /* Avoid mixing '/' and '\\' */
7027 for (i = strlen (path) - 1; i >= 0; i--)
7028 if (path [i] == '/')
7032 ipath = mono_string_new (mono_domain_get (), path);
7038 ICALL_EXPORT gboolean
7039 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7041 MonoPEResourceDataEntry *entry;
7044 MONO_ARCH_SAVE_REGS;
7046 if (!assembly || !result || !size)
7051 image = assembly->assembly->image;
7052 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7056 *result = mono_image_rva_map (image, entry->rde_data_offset);
7061 *size = entry->rde_size;
7066 ICALL_EXPORT MonoBoolean
7067 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7069 return mono_is_debugger_attached ();
7072 ICALL_EXPORT MonoBoolean
7073 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7075 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7076 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7082 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7084 if (mono_get_runtime_callbacks ()->debug_log)
7085 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7089 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7091 #if defined (HOST_WIN32)
7092 OutputDebugString (mono_string_chars (message));
7094 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7098 /* Only used for value types */
7099 ICALL_EXPORT MonoObject *
7100 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7105 MONO_ARCH_SAVE_REGS;
7107 domain = mono_object_domain (type);
7108 klass = mono_class_from_mono_type (type->type);
7109 mono_class_init_or_throw (klass);
7111 if (mono_class_is_nullable (klass))
7112 /* No arguments -> null */
7115 return mono_object_new (domain, klass);
7118 ICALL_EXPORT MonoReflectionMethod *
7119 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7121 MonoClass *klass, *parent;
7122 MonoMethod *method = m->method;
7123 MonoMethod *result = NULL;
7126 MONO_ARCH_SAVE_REGS;
7128 if (method->klass == NULL)
7131 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7132 MONO_CLASS_IS_INTERFACE (method->klass) ||
7133 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7136 slot = mono_method_get_vtable_slot (method);
7140 klass = method->klass;
7141 if (klass->generic_class)
7142 klass = klass->generic_class->container_class;
7145 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7146 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7147 mono_class_setup_vtable (parent);
7148 if (parent->vtable_size <= slot)
7153 klass = klass->parent;
7158 if (klass == method->klass)
7161 /*This is possible if definition == FALSE.
7162 * Do it here to be really sure we don't read invalid memory.
7164 if (slot >= klass->vtable_size)
7167 mono_class_setup_vtable (klass);
7169 result = klass->vtable [slot];
7170 if (result == NULL) {
7171 /* It is an abstract method */
7172 gpointer iter = NULL;
7173 while ((result = mono_class_get_methods (klass, &iter)))
7174 if (result->slot == slot)
7181 return mono_method_get_object (mono_domain_get (), result, NULL);
7184 ICALL_EXPORT MonoString*
7185 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7187 MonoMethod *method = m->method;
7189 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7194 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7196 MONO_ARCH_SAVE_REGS;
7198 iter->sig = *(MonoMethodSignature**)argsp;
7200 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7201 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7204 /* FIXME: it's not documented what start is exactly... */
7208 iter->args = argsp + sizeof (gpointer);
7210 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7212 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7215 ICALL_EXPORT MonoTypedRef
7216 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7218 guint32 i, arg_size;
7221 MONO_ARCH_SAVE_REGS;
7223 i = iter->sig->sentinelpos + iter->next_arg;
7225 g_assert (i < iter->sig->param_count);
7227 res.type = iter->sig->params [i];
7228 res.klass = mono_class_from_mono_type (res.type);
7229 arg_size = mono_type_stack_size (res.type, &align);
7230 #if defined(__arm__) || defined(__mips__)
7231 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7233 res.value = iter->args;
7234 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7235 /* Values are stored as 8 byte register sized objects, but 'value'
7236 * is dereferenced as a pointer in other routines.
7238 res.value = (char*)res.value + 4;
7240 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7241 if (arg_size <= sizeof (gpointer)) {
7243 int padding = arg_size - mono_type_size (res.type, &dummy);
7244 res.value = (guint8*)res.value + padding;
7247 iter->args = (char*)iter->args + arg_size;
7250 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7255 ICALL_EXPORT MonoTypedRef
7256 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7258 guint32 i, arg_size;
7261 MONO_ARCH_SAVE_REGS;
7263 i = iter->sig->sentinelpos + iter->next_arg;
7265 g_assert (i < iter->sig->param_count);
7267 while (i < iter->sig->param_count) {
7268 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7270 res.type = iter->sig->params [i];
7271 res.klass = mono_class_from_mono_type (res.type);
7272 /* FIXME: endianess issue... */
7273 arg_size = mono_type_stack_size (res.type, &align);
7274 #if defined(__arm__) || defined(__mips__)
7275 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7277 res.value = iter->args;
7278 iter->args = (char*)iter->args + arg_size;
7280 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7283 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7291 ICALL_EXPORT MonoType*
7292 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7295 MONO_ARCH_SAVE_REGS;
7297 i = iter->sig->sentinelpos + iter->next_arg;
7299 g_assert (i < iter->sig->param_count);
7301 return iter->sig->params [i];
7304 ICALL_EXPORT MonoObject*
7305 mono_TypedReference_ToObject (MonoTypedRef tref)
7307 MONO_ARCH_SAVE_REGS;
7309 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7310 MonoObject** objp = tref.value;
7314 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7317 ICALL_EXPORT MonoObject*
7318 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7320 MONO_ARCH_SAVE_REGS;
7322 if (MONO_TYPE_IS_REFERENCE (type)) {
7323 MonoObject** objp = value;
7327 return mono_value_box (mono_domain_get (), klass, value);
7331 prelink_method (MonoMethod *method)
7333 const char *exc_class, *exc_arg;
7334 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7336 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7338 mono_raise_exception(
7339 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7341 /* create the wrapper, too? */
7345 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7347 MONO_ARCH_SAVE_REGS;
7348 prelink_method (method->method);
7352 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7354 MonoClass *klass = mono_class_from_mono_type (type->type);
7356 gpointer iter = NULL;
7357 MONO_ARCH_SAVE_REGS;
7359 mono_class_init_or_throw (klass);
7361 while ((m = mono_class_get_methods (klass, &iter)))
7365 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7367 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7368 gint32 const **exponents,
7369 gunichar2 const **digitLowerTable,
7370 gunichar2 const **digitUpperTable,
7371 gint64 const **tenPowersList,
7372 gint32 const **decHexDigits)
7374 *mantissas = Formatter_MantissaBitsTable;
7375 *exponents = Formatter_TensExponentTable;
7376 *digitLowerTable = Formatter_DigitLowerTable;
7377 *digitUpperTable = Formatter_DigitUpperTable;
7378 *tenPowersList = Formatter_TenPowersList;
7379 *decHexDigits = Formatter_DecHexDigits;
7383 get_category_data (int version,
7384 guint8 const **category_data,
7385 guint16 const **category_astral_index)
7387 *category_astral_index = NULL;
7389 #ifndef DISABLE_NET_4_0
7391 *category_data = CategoryData_v4;
7392 #ifndef DISABLE_ASTRAL
7393 *category_astral_index = CategoryData_v4_astral_index;
7399 *category_data = CategoryData_v2;
7400 #ifndef DISABLE_ASTRAL
7401 *category_astral_index = CategoryData_v2_astral_index;
7405 /* These parameters are "readonly" in corlib/System/Char.cs */
7407 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7408 guint8 const **category_data,
7409 guint16 const **category_astral_index,
7410 guint8 const **numeric_data,
7411 gdouble const **numeric_data_values,
7412 guint16 const **to_lower_data_low,
7413 guint16 const **to_lower_data_high,
7414 guint16 const **to_upper_data_low,
7415 guint16 const **to_upper_data_high)
7417 get_category_data (category_data_version, category_data, category_astral_index);
7418 *numeric_data = NumericData;
7419 *numeric_data_values = NumericDataValues;
7420 *to_lower_data_low = ToLowerDataLow;
7421 *to_lower_data_high = ToLowerDataHigh;
7422 *to_upper_data_low = ToUpperDataLow;
7423 *to_upper_data_high = ToUpperDataHigh;
7427 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7428 * and avoid useless allocations.
7433 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7437 for (i = 0; i < type->num_mods; ++i) {
7438 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7443 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7445 for (i = 0; i < type->num_mods; ++i) {
7446 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7448 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7449 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7450 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7457 ICALL_EXPORT MonoArray*
7458 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7460 MonoType *type = param->ClassImpl->type;
7461 MonoClass *member_class = mono_object_class (param->MemberImpl);
7462 MonoMethod *method = NULL;
7465 MonoMethodSignature *sig;
7467 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7468 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7469 method = rmethod->method;
7470 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7471 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7472 if (!(method = prop->property->get))
7473 method = prop->property->set;
7476 char *type_name = mono_type_get_full_name (member_class);
7477 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7478 MonoException *ex = mono_get_exception_not_supported (msg);
7481 mono_raise_exception (ex);
7484 image = method->klass->image;
7485 pos = param->PositionImpl;
7486 sig = mono_method_signature (method);
7490 type = sig->params [pos];
7492 return type_array_from_modifiers (image, type, optional);
7496 get_property_type (MonoProperty *prop)
7498 MonoMethodSignature *sig;
7500 sig = mono_method_signature (prop->get);
7502 } else if (prop->set) {
7503 sig = mono_method_signature (prop->set);
7504 return sig->params [sig->param_count - 1];
7509 ICALL_EXPORT MonoArray*
7510 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7512 MonoType *type = get_property_type (property->property);
7513 MonoImage *image = property->klass->image;
7517 return type_array_from_modifiers (image, type, optional);
7521 *Construct a MonoType suited to be used to decode a constant blob object.
7523 * @type is the target type which will be constructed
7524 * @blob_type is the blob type, for example, that comes from the constant table
7525 * @real_type is the expected constructed type.
7528 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7530 type->type = blob_type;
7531 type->data.klass = NULL;
7532 if (blob_type == MONO_TYPE_CLASS)
7533 type->data.klass = mono_defaults.object_class;
7534 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7535 /* For enums, we need to use the base type */
7536 type->type = MONO_TYPE_VALUETYPE;
7537 type->data.klass = mono_class_from_mono_type (real_type);
7539 type->data.klass = mono_class_from_mono_type (real_type);
7542 ICALL_EXPORT MonoObject*
7543 property_info_get_default_value (MonoReflectionProperty *property)
7546 MonoProperty *prop = property->property;
7547 MonoType *type = get_property_type (prop);
7548 MonoDomain *domain = mono_object_domain (property);
7549 MonoTypeEnum def_type;
7550 const char *def_value;
7553 mono_class_init (prop->parent);
7555 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7556 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7558 def_value = mono_class_get_property_default_value (prop, &def_type);
7560 mono_type_from_blob_type (&blob_type, def_type, type);
7561 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7566 ICALL_EXPORT MonoBoolean
7567 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7569 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7570 MonoCustomAttrInfo *cinfo;
7573 mono_class_init_or_throw (attr_class);
7575 cinfo = mono_reflection_get_custom_attrs_info (obj);
7578 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7580 mono_custom_attrs_free (cinfo);
7584 ICALL_EXPORT MonoArray*
7585 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7587 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7592 mono_class_init_or_throw (attr_class);
7594 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7595 mono_error_raise_exception (&error);
7597 if (mono_loader_get_last_error ()) {
7598 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7599 g_assert_not_reached ();
7607 ICALL_EXPORT MonoString*
7608 ves_icall_Mono_Runtime_GetDisplayName (void)
7611 MonoString *display_name;
7613 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7614 display_name = mono_string_new (mono_domain_get (), info);
7616 return display_name;
7619 ICALL_EXPORT MonoString*
7620 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7622 MonoString *message;
7626 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7627 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7630 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7632 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7640 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7641 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7642 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7643 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7644 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7645 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7646 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7647 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7651 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7656 gunichar2 last, prev_last, prev2_last;
7663 int havePadding = 0;
7665 last = prev_last = 0, prev2_last = 0;
7666 for (i = 0; i < ilength; i++) {
7668 if (c >= sizeof (dbase64)) {
7669 exc = mono_exception_from_name_msg (mono_get_corlib (),
7670 "System", "FormatException",
7671 "Invalid character found.");
7672 mono_raise_exception (exc);
7673 } else if (isspace (c)) {
7675 } else if (havePadding && c != '=') {
7676 exc = mono_exception_from_name_msg (mono_get_corlib (),
7677 "System", "FormatException",
7678 "Invalid character found.");
7679 mono_raise_exception (exc);
7681 if (c == '=') havePadding = 1;
7682 prev2_last = prev_last;
7688 olength = ilength - ignored;
7690 if (allowWhitespaceOnly && olength == 0) {
7691 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7694 if ((olength & 3) != 0 || olength <= 0) {
7695 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7696 "FormatException", "Invalid length.");
7697 mono_raise_exception (exc);
7700 if (prev2_last == '=') {
7701 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7702 mono_raise_exception (exc);
7705 olength = (olength * 3) / 4;
7709 if (prev_last == '=')
7712 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7713 res_ptr = mono_array_addr (result, guchar, 0);
7714 for (i = 0; i < ilength; ) {
7717 for (k = 0; k < 4 && i < ilength;) {
7723 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7724 exc = mono_exception_from_name_msg (mono_get_corlib (),
7725 "System", "FormatException",
7726 "Invalid character found.");
7727 mono_raise_exception (exc);
7732 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7734 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7736 *res_ptr++ = (b [2] << 6) | b [3];
7738 while (i < ilength && isspace (start [i]))
7745 ICALL_EXPORT MonoArray *
7746 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7748 MONO_ARCH_SAVE_REGS;
7750 return base64_to_byte_array (mono_string_chars (str),
7751 mono_string_length (str), allowWhitespaceOnly);
7754 ICALL_EXPORT MonoArray *
7755 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7757 MONO_ARCH_SAVE_REGS;
7759 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7763 #ifndef DISABLE_ICALL_TABLES
7765 #define ICALL_TYPE(id,name,first)
7766 #define ICALL(id,name,func) Icall_ ## id,
7769 #include "metadata/icall-def.h"
7775 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7776 #define ICALL(id,name,func)
7778 #include "metadata/icall-def.h"
7784 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7785 #define ICALL(id,name,func)
7787 guint16 first_icall;
7790 static const IcallTypeDesc
7791 icall_type_descs [] = {
7792 #include "metadata/icall-def.h"
7796 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7799 #define ICALL_TYPE(id,name,first)
7802 #ifdef HAVE_ARRAY_ELEM_INIT
7803 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7804 #define MSGSTRFIELD1(line) str##line
7806 static const struct msgstrtn_t {
7807 #define ICALL(id,name,func)
7809 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7810 #include "metadata/icall-def.h"
7812 } icall_type_names_str = {
7813 #define ICALL_TYPE(id,name,first) (name),
7814 #include "metadata/icall-def.h"
7817 static const guint16 icall_type_names_idx [] = {
7818 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7819 #include "metadata/icall-def.h"
7822 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7824 static const struct msgstr_t {
7826 #define ICALL_TYPE(id,name,first)
7827 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7828 #include "metadata/icall-def.h"
7830 } icall_names_str = {
7831 #define ICALL(id,name,func) (name),
7832 #include "metadata/icall-def.h"
7835 static const guint16 icall_names_idx [] = {
7836 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7837 #include "metadata/icall-def.h"
7840 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7846 #define ICALL_TYPE(id,name,first) name,
7847 #define ICALL(id,name,func)
7848 static const char* const
7849 icall_type_names [] = {
7850 #include "metadata/icall-def.h"
7854 #define icall_type_name_get(id) (icall_type_names [(id)])
7858 #define ICALL_TYPE(id,name,first)
7859 #define ICALL(id,name,func) name,
7860 static const char* const
7862 #include "metadata/icall-def.h"
7865 #define icall_name_get(id) icall_names [(id)]
7867 #endif /* !HAVE_ARRAY_ELEM_INIT */
7871 #define ICALL_TYPE(id,name,first)
7872 #define ICALL(id,name,func) func,
7873 static const gconstpointer
7874 icall_functions [] = {
7875 #include "metadata/icall-def.h"
7879 #ifdef ENABLE_ICALL_SYMBOL_MAP
7882 #define ICALL_TYPE(id,name,first)
7883 #define ICALL(id,name,func) #func,
7884 static const gconstpointer
7885 icall_symbols [] = {
7886 #include "metadata/icall-def.h"
7891 #endif /* DISABLE_ICALL_TABLES */
7893 static mono_mutex_t icall_mutex;
7894 static GHashTable *icall_hash = NULL;
7895 static GHashTable *jit_icall_hash_name = NULL;
7896 static GHashTable *jit_icall_hash_addr = NULL;
7899 mono_icall_init (void)
7901 #ifndef DISABLE_ICALL_TABLES
7904 /* check that tables are sorted: disable in release */
7907 const char *prev_class = NULL;
7908 const char *prev_method;
7910 for (i = 0; i < Icall_type_num; ++i) {
7911 const IcallTypeDesc *desc;
7914 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7915 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7916 prev_class = icall_type_name_get (i);
7917 desc = &icall_type_descs [i];
7918 num_icalls = icall_desc_num_icalls (desc);
7919 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7920 for (j = 0; j < num_icalls; ++j) {
7921 const char *methodn = icall_name_get (desc->first_icall + j);
7922 if (prev_method && strcmp (prev_method, methodn) >= 0)
7923 g_print ("method %s should come before method %s\n", methodn, prev_method);
7924 prev_method = methodn;
7930 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7931 mono_mutex_init (&icall_mutex);
7935 mono_icall_lock (void)
7937 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7941 mono_icall_unlock (void)
7943 mono_locks_mutex_release (&icall_mutex, IcallLock);
7947 mono_icall_cleanup (void)
7949 g_hash_table_destroy (icall_hash);
7950 g_hash_table_destroy (jit_icall_hash_name);
7951 g_hash_table_destroy (jit_icall_hash_addr);
7952 mono_mutex_destroy (&icall_mutex);
7956 mono_add_internal_call (const char *name, gconstpointer method)
7960 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7962 mono_icall_unlock ();
7965 #ifndef DISABLE_ICALL_TABLES
7967 #ifdef HAVE_ARRAY_ELEM_INIT
7969 compare_method_imap (const void *key, const void *elem)
7971 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7972 return strcmp (key, method_name);
7976 find_method_icall (const IcallTypeDesc *imap, const char *name)
7978 const guint16 *nameslot = mono_binary_search (name, icall_names_idx + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names_idx [0]), compare_method_imap);
7981 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7985 compare_class_imap (const void *key, const void *elem)
7987 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7988 return strcmp (key, class_name);
7991 static const IcallTypeDesc*
7992 find_class_icalls (const char *name)
7994 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7997 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8000 #else /* HAVE_ARRAY_ELEM_INIT */
8003 compare_method_imap (const void *key, const void *elem)
8005 const char** method_name = (const char**)elem;
8006 return strcmp (key, *method_name);
8010 find_method_icall (const IcallTypeDesc *imap, const char *name)
8012 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8015 return (gpointer)icall_functions [(nameslot - icall_names)];
8019 compare_class_imap (const void *key, const void *elem)
8021 const char** class_name = (const char**)elem;
8022 return strcmp (key, *class_name);
8025 static const IcallTypeDesc*
8026 find_class_icalls (const char *name)
8028 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8031 return &icall_type_descs [nameslot - icall_type_names];
8034 #endif /* HAVE_ARRAY_ELEM_INIT */
8036 #endif /* DISABLE_ICALL_TABLES */
8039 * we should probably export this as an helper (handle nested types).
8040 * Returns the number of chars written in buf.
8043 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8045 int nspacelen, cnamelen;
8046 nspacelen = strlen (klass->name_space);
8047 cnamelen = strlen (klass->name);
8048 if (nspacelen + cnamelen + 2 > bufsize)
8051 memcpy (buf, klass->name_space, nspacelen);
8052 buf [nspacelen ++] = '.';
8054 memcpy (buf + nspacelen, klass->name, cnamelen);
8055 buf [nspacelen + cnamelen] = 0;
8056 return nspacelen + cnamelen;
8059 #ifdef DISABLE_ICALL_TABLES
8061 no_icall_table (void)
8063 g_assert_not_reached ();
8068 mono_lookup_internal_call (MonoMethod *method)
8073 int typelen = 0, mlen, siglen;
8075 #ifndef DISABLE_ICALL_TABLES
8076 const IcallTypeDesc *imap = NULL;
8079 g_assert (method != NULL);
8081 if (method->is_inflated)
8082 method = ((MonoMethodInflated *) method)->declaring;
8084 if (method->klass->nested_in) {
8085 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8089 mname [pos++] = '/';
8092 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8098 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8103 #ifndef DISABLE_ICALL_TABLES
8104 imap = find_class_icalls (mname);
8107 mname [typelen] = ':';
8108 mname [typelen + 1] = ':';
8110 mlen = strlen (method->name);
8111 memcpy (mname + typelen + 2, method->name, mlen);
8112 sigstart = mname + typelen + 2 + mlen;
8115 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8116 siglen = strlen (tmpsig);
8117 if (typelen + mlen + siglen + 6 > sizeof (mname))
8120 memcpy (sigstart + 1, tmpsig, siglen);
8121 sigstart [siglen + 1] = ')';
8122 sigstart [siglen + 2] = 0;
8127 res = g_hash_table_lookup (icall_hash, mname);
8129 mono_icall_unlock ();;
8132 /* try without signature */
8134 res = g_hash_table_lookup (icall_hash, mname);
8136 mono_icall_unlock ();
8140 #ifdef DISABLE_ICALL_TABLES
8141 mono_icall_unlock ();
8142 /* Fail only when the result is actually used */
8143 /* mono_marshal_get_native_wrapper () depends on this */
8144 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8145 return ves_icall_System_String_ctor_RedirectToCreateString;
8147 return no_icall_table;
8149 /* it wasn't found in the static call tables */
8151 mono_icall_unlock ();
8154 res = find_method_icall (imap, sigstart - mlen);
8156 mono_icall_unlock ();
8159 /* try _with_ signature */
8161 res = find_method_icall (imap, sigstart - mlen);
8163 mono_icall_unlock ();
8167 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8168 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8169 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8170 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8171 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");
8172 g_print ("If you see other errors or faults after this message they are probably related\n");
8173 g_print ("and you need to fix your mono install first.\n");
8175 mono_icall_unlock ();
8181 #ifdef ENABLE_ICALL_SYMBOL_MAP
8183 func_cmp (gconstpointer key, gconstpointer p)
8185 return (gsize)key - (gsize)*(gsize*)p;
8190 * mono_lookup_icall_symbol:
8192 * Given the icall METHOD, returns its C symbol.
8195 mono_lookup_icall_symbol (MonoMethod *m)
8197 #ifdef DISABLE_ICALL_TABLES
8198 g_assert_not_reached ();
8201 #ifdef ENABLE_ICALL_SYMBOL_MAP
8205 static gconstpointer *functions_sorted;
8206 static const char**symbols_sorted;
8207 static gboolean inited;
8212 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8213 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8214 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8215 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8216 /* Bubble sort the two arrays */
8220 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8221 if (functions_sorted [i] > functions_sorted [i + 1]) {
8224 tmp = functions_sorted [i];
8225 functions_sorted [i] = functions_sorted [i + 1];
8226 functions_sorted [i + 1] = tmp;
8227 tmp = symbols_sorted [i];
8228 symbols_sorted [i] = symbols_sorted [i + 1];
8229 symbols_sorted [i + 1] = tmp;
8236 func = mono_lookup_internal_call (m);
8239 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8243 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8245 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8246 g_assert_not_reached ();
8253 type_from_typename (char *typename)
8255 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8257 if (!strcmp (typename, "int"))
8258 klass = mono_defaults.int_class;
8259 else if (!strcmp (typename, "ptr"))
8260 klass = mono_defaults.int_class;
8261 else if (!strcmp (typename, "void"))
8262 klass = mono_defaults.void_class;
8263 else if (!strcmp (typename, "int32"))
8264 klass = mono_defaults.int32_class;
8265 else if (!strcmp (typename, "uint32"))
8266 klass = mono_defaults.uint32_class;
8267 else if (!strcmp (typename, "int8"))
8268 klass = mono_defaults.sbyte_class;
8269 else if (!strcmp (typename, "uint8"))
8270 klass = mono_defaults.byte_class;
8271 else if (!strcmp (typename, "int16"))
8272 klass = mono_defaults.int16_class;
8273 else if (!strcmp (typename, "uint16"))
8274 klass = mono_defaults.uint16_class;
8275 else if (!strcmp (typename, "long"))
8276 klass = mono_defaults.int64_class;
8277 else if (!strcmp (typename, "ulong"))
8278 klass = mono_defaults.uint64_class;
8279 else if (!strcmp (typename, "float"))
8280 klass = mono_defaults.single_class;
8281 else if (!strcmp (typename, "double"))
8282 klass = mono_defaults.double_class;
8283 else if (!strcmp (typename, "object"))
8284 klass = mono_defaults.object_class;
8285 else if (!strcmp (typename, "obj"))
8286 klass = mono_defaults.object_class;
8287 else if (!strcmp (typename, "string"))
8288 klass = mono_defaults.string_class;
8289 else if (!strcmp (typename, "bool"))
8290 klass = mono_defaults.boolean_class;
8291 else if (!strcmp (typename, "boolean"))
8292 klass = mono_defaults.boolean_class;
8294 g_error ("%s", typename);
8295 g_assert_not_reached ();
8297 return &klass->byval_arg;
8301 * LOCKING: Take the corlib image lock.
8303 MonoMethodSignature*
8304 mono_create_icall_signature (const char *sigstr)
8309 MonoMethodSignature *res, *res2;
8310 MonoImage *corlib = mono_defaults.corlib;
8312 mono_image_lock (corlib);
8313 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8314 mono_image_unlock (corlib);
8319 parts = g_strsplit (sigstr, " ", 256);
8328 res = mono_metadata_signature_alloc (corlib, len - 1);
8333 * Under windows, the default pinvoke calling convention is STDCALL but
8336 res->call_convention = MONO_CALL_C;
8339 res->ret = type_from_typename (parts [0]);
8340 for (i = 1; i < len; ++i) {
8341 res->params [i - 1] = type_from_typename (parts [i]);
8346 mono_image_lock (corlib);
8347 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8349 res = res2; /*Value is allocated in the image pool*/
8351 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8352 mono_image_unlock (corlib);
8358 mono_find_jit_icall_by_name (const char *name)
8360 MonoJitICallInfo *info;
8361 g_assert (jit_icall_hash_name);
8364 info = g_hash_table_lookup (jit_icall_hash_name, name);
8365 mono_icall_unlock ();
8370 mono_find_jit_icall_by_addr (gconstpointer addr)
8372 MonoJitICallInfo *info;
8373 g_assert (jit_icall_hash_addr);
8376 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8377 mono_icall_unlock ();
8383 * mono_get_jit_icall_info:
8385 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8386 * caller should access it while holding the icall lock.
8389 mono_get_jit_icall_info (void)
8391 return jit_icall_hash_name;
8395 * mono_lookup_jit_icall_symbol:
8397 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8400 mono_lookup_jit_icall_symbol (const char *name)
8402 MonoJitICallInfo *info;
8403 const char *res = NULL;
8406 info = g_hash_table_lookup (jit_icall_hash_name, name);
8408 res = info->c_symbol;
8409 mono_icall_unlock ();
8414 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8417 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8418 mono_icall_unlock ();
8422 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8424 MonoJitICallInfo *info;
8431 if (!jit_icall_hash_name) {
8432 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8433 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8436 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8437 g_warning ("jit icall already defined \"%s\"\n", name);
8438 g_assert_not_reached ();
8441 info = g_new0 (MonoJitICallInfo, 1);
8446 info->c_symbol = c_symbol;
8449 info->wrapper = func;
8451 info->wrapper = NULL;
8454 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8455 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8457 mono_icall_unlock ();
8462 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8464 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);