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)) {
1901 MonoClass *klass = field->parent;
1902 int fidx = field - klass->fields;
1904 g_assert (fidx >= 0 && fidx < klass->field.count);
1905 g_assert (klass->ext);
1906 g_assert (klass->ext->field_def_values);
1907 def_type = klass->ext->field_def_values [fidx].def_type;
1908 def_value = klass->ext->field_def_values [fidx].data;
1909 if (def_type == MONO_TYPE_END)
1910 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1912 def_value = mono_class_get_field_default_value (field, &def_type);
1913 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1915 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1918 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1922 case MONO_TYPE_BOOLEAN:
1925 case MONO_TYPE_CHAR:
1933 case MONO_TYPE_R8: {
1936 /* boxed value type */
1937 t = g_new0 (MonoType, 1);
1939 klass = mono_class_from_mono_type (t);
1941 o = mono_object_new (domain, klass);
1942 v = ((gchar *) o) + sizeof (MonoObject);
1943 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1946 case MONO_TYPE_STRING:
1947 case MONO_TYPE_CLASS:
1948 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1951 g_assert_not_reached ();
1957 ICALL_EXPORT MonoReflectionType*
1958 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1961 MonoClassField *field = ref_field->field;
1962 MonoType *type = mono_field_get_type_checked (field, &error);
1963 if (!mono_error_ok (&error))
1964 mono_error_raise_exception (&error);
1965 return mono_type_get_object (mono_object_domain (ref_field), type);
1968 ICALL_EXPORT MonoReflectionType*
1969 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1971 MonoMethod *method = rmethod->method.method;
1973 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1976 /* From MonoProperty.cs */
1978 PInfo_Attributes = 1,
1979 PInfo_GetMethod = 1 << 1,
1980 PInfo_SetMethod = 1 << 2,
1981 PInfo_ReflectedType = 1 << 3,
1982 PInfo_DeclaringType = 1 << 4,
1987 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1989 MonoDomain *domain = mono_object_domain (property);
1991 MONO_ARCH_SAVE_REGS;
1993 if ((req_info & PInfo_ReflectedType) != 0)
1994 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1995 if ((req_info & PInfo_DeclaringType) != 0)
1996 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1998 if ((req_info & PInfo_Name) != 0)
1999 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
2001 if ((req_info & PInfo_Attributes) != 0)
2002 info->attrs = property->property->attrs;
2004 if ((req_info & PInfo_GetMethod) != 0)
2005 MONO_STRUCT_SETREF (info, get, property->property->get ?
2006 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2008 if ((req_info & PInfo_SetMethod) != 0)
2009 MONO_STRUCT_SETREF (info, set, property->property->set ?
2010 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2012 * There may be other methods defined for properties, though, it seems they are not exposed
2013 * in the reflection API
2018 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2020 MonoDomain *domain = mono_object_domain (event);
2022 MONO_ARCH_SAVE_REGS;
2024 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2025 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2027 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2028 info->attrs = event->event->attrs;
2029 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2030 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2031 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2033 #ifndef MONO_SMALL_CONFIG
2034 if (event->event->other) {
2036 while (event->event->other [n])
2038 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2040 for (i = 0; i < n; i++)
2041 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2047 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2052 mono_class_setup_interfaces (klass, error);
2053 if (!mono_error_ok (error))
2056 for (i = 0; i < klass->interface_count; i++) {
2057 ic = klass->interfaces [i];
2058 g_hash_table_insert (ifaces, ic, ic);
2060 collect_interfaces (ic, ifaces, error);
2061 if (!mono_error_ok (error))
2067 MonoArray *iface_array;
2068 MonoGenericContext *context;
2072 } FillIfaceArrayData;
2075 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2077 FillIfaceArrayData *data = user_data;
2078 MonoClass *ic = key;
2079 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2081 if (!mono_error_ok (data->error))
2084 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2085 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2086 if (!mono_error_ok (data->error))
2090 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2093 mono_metadata_free_type (inflated);
2096 ICALL_EXPORT MonoArray*
2097 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2100 MonoClass *class = mono_class_from_mono_type (type->type);
2102 FillIfaceArrayData data = { 0 };
2105 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2107 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2108 data.context = mono_class_get_context (class);
2109 class = class->generic_class->container_class;
2112 for (parent = class; parent; parent = parent->parent) {
2113 mono_class_setup_interfaces (parent, &error);
2114 if (!mono_error_ok (&error))
2116 collect_interfaces (parent, iface_hash, &error);
2117 if (!mono_error_ok (&error))
2121 data.error = &error;
2122 data.domain = mono_object_domain (type);
2124 len = g_hash_table_size (iface_hash);
2126 g_hash_table_destroy (iface_hash);
2127 if (!data.domain->empty_types)
2128 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2129 return data.domain->empty_types;
2132 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2133 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2134 if (!mono_error_ok (&error))
2137 g_hash_table_destroy (iface_hash);
2138 return data.iface_array;
2141 g_hash_table_destroy (iface_hash);
2142 mono_error_raise_exception (&error);
2147 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2149 gboolean variance_used;
2150 MonoClass *class = mono_class_from_mono_type (type->type);
2151 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2152 MonoReflectionMethod *member;
2155 int i = 0, len, ioffset;
2158 MONO_ARCH_SAVE_REGS;
2159 mono_class_init_or_throw (class);
2160 mono_class_init_or_throw (iclass);
2162 mono_class_setup_vtable (class);
2164 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2168 len = mono_class_num_methods (iclass);
2169 domain = mono_object_domain (type);
2170 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2171 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2173 while ((method = mono_class_get_methods (iclass, &iter))) {
2174 member = mono_method_get_object (domain, method, iclass);
2175 mono_array_setref (*methods, i, member);
2176 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2177 mono_array_setref (*targets, i, member);
2184 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2186 MonoClass *klass = mono_class_from_mono_type (type->type);
2187 mono_class_init_or_throw (klass);
2189 if (image_is_dynamic (klass->image)) {
2190 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2191 *packing = tb->packing_size;
2192 *size = tb->class_size;
2194 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2198 ICALL_EXPORT MonoReflectionType*
2199 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2203 MONO_ARCH_SAVE_REGS;
2205 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2206 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2208 class = mono_class_from_mono_type (type->type);
2209 mono_class_init_or_throw (class);
2211 // GetElementType should only return a type for:
2212 // Array Pointer PassedByRef
2213 if (type->type->byref)
2214 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2215 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2216 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2217 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2218 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2223 ICALL_EXPORT MonoReflectionType*
2224 ves_icall_get_type_parent (MonoReflectionType *type)
2226 MonoClass *class = mono_class_from_mono_type (type->type);
2227 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2230 ICALL_EXPORT MonoBoolean
2231 ves_icall_type_ispointer (MonoReflectionType *type)
2233 MONO_ARCH_SAVE_REGS;
2235 return type->type->type == MONO_TYPE_PTR;
2238 ICALL_EXPORT MonoBoolean
2239 ves_icall_type_isprimitive (MonoReflectionType *type)
2241 MONO_ARCH_SAVE_REGS;
2243 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)));
2246 ICALL_EXPORT MonoBoolean
2247 ves_icall_type_isbyref (MonoReflectionType *type)
2249 MONO_ARCH_SAVE_REGS;
2251 return type->type->byref;
2254 ICALL_EXPORT MonoBoolean
2255 ves_icall_type_iscomobject (MonoReflectionType *type)
2257 MonoClass *klass = mono_class_from_mono_type (type->type);
2258 mono_class_init_or_throw (klass);
2260 return mono_class_is_com_object (klass);
2263 ICALL_EXPORT MonoReflectionModule*
2264 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2266 MonoClass *class = mono_class_from_mono_type (type->type);
2267 return mono_module_get_object (mono_object_domain (type), class->image);
2270 ICALL_EXPORT MonoReflectionAssembly*
2271 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2273 MonoDomain *domain = mono_domain_get ();
2274 MonoClass *class = mono_class_from_mono_type (type->type);
2275 return mono_assembly_get_object (domain, class->image->assembly);
2278 ICALL_EXPORT MonoReflectionType*
2279 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2281 MonoDomain *domain = mono_domain_get ();
2284 MONO_ARCH_SAVE_REGS;
2286 if (type->type->byref)
2288 if (type->type->type == MONO_TYPE_VAR) {
2289 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2290 class = param ? param->owner.klass : NULL;
2291 } else if (type->type->type == MONO_TYPE_MVAR) {
2292 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2293 class = param ? param->owner.method->klass : NULL;
2295 class = mono_class_from_mono_type (type->type)->nested_in;
2298 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2301 ICALL_EXPORT MonoString*
2302 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2304 MonoDomain *domain = mono_domain_get ();
2305 MonoClass *class = mono_class_from_mono_type (type->type);
2307 if (type->type->byref) {
2308 char *n = g_strdup_printf ("%s&", class->name);
2309 MonoString *res = mono_string_new (domain, n);
2315 return mono_string_new (domain, class->name);
2319 ICALL_EXPORT MonoString*
2320 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2322 MonoDomain *domain = mono_domain_get ();
2323 MonoClass *class = mono_class_from_mono_type (type->type);
2325 while (class->nested_in)
2326 class = class->nested_in;
2328 if (class->name_space [0] == '\0')
2331 return mono_string_new (domain, class->name_space);
2335 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2339 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2340 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2342 class = mono_class_from_mono_type (type->type);
2347 ICALL_EXPORT MonoArray*
2348 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2351 MonoClass *klass, *pklass;
2352 MonoDomain *domain = mono_object_domain (type);
2353 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2355 MONO_ARCH_SAVE_REGS;
2357 klass = mono_class_from_mono_type (type->type);
2359 if (klass->generic_container) {
2360 MonoGenericContainer *container = klass->generic_container;
2361 res = mono_array_new_specific (array_vtable, container->type_argc);
2362 for (i = 0; i < container->type_argc; ++i) {
2363 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2364 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2366 } else if (klass->generic_class) {
2367 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2368 res = mono_array_new_specific (array_vtable, inst->type_argc);
2369 for (i = 0; i < inst->type_argc; ++i)
2370 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2372 res = mono_array_new_specific (array_vtable, 0);
2377 ICALL_EXPORT gboolean
2378 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2381 MONO_ARCH_SAVE_REGS;
2383 if (!IS_MONOTYPE (type))
2386 if (type->type->byref)
2389 klass = mono_class_from_mono_type (type->type);
2390 return klass->generic_container != NULL;
2393 ICALL_EXPORT MonoReflectionType*
2394 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2397 MONO_ARCH_SAVE_REGS;
2399 if (type->type->byref)
2402 klass = mono_class_from_mono_type (type->type);
2404 if (klass->generic_container) {
2405 return type; /* check this one */
2407 if (klass->generic_class) {
2408 MonoClass *generic_class = klass->generic_class->container_class;
2411 tb = mono_class_get_ref_info (generic_class);
2413 if (generic_class->wastypebuilder && tb)
2416 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2421 ICALL_EXPORT MonoReflectionType*
2422 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2425 MonoType *geninst, **types;
2428 g_assert (IS_MONOTYPE (type));
2429 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2431 count = mono_array_length (type_array);
2432 types = g_new0 (MonoType *, count);
2434 for (i = 0; i < count; i++) {
2435 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2436 types [i] = t->type;
2439 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2444 class = mono_class_from_mono_type (geninst);
2446 /*we might inflate to the GTD*/
2447 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2448 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2450 return mono_type_get_object (mono_object_domain (type), geninst);
2453 ICALL_EXPORT gboolean
2454 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2457 MONO_ARCH_SAVE_REGS;
2459 if (type->type->byref)
2462 klass = mono_class_from_mono_type (type->type);
2464 return klass->generic_class != NULL;
2467 ICALL_EXPORT gboolean
2468 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2471 MONO_ARCH_SAVE_REGS;
2473 if (!IS_MONOTYPE (type))
2476 if (type->type->byref)
2479 klass = mono_class_from_mono_type (type->type);
2480 return klass->generic_class != NULL || klass->generic_container != NULL;
2484 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2486 MONO_ARCH_SAVE_REGS;
2488 if (!IS_MONOTYPE (type))
2491 if (is_generic_parameter (type->type))
2492 return mono_type_get_generic_param_num (type->type);
2496 ICALL_EXPORT GenericParameterAttributes
2497 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2499 MONO_ARCH_SAVE_REGS;
2501 g_assert (IS_MONOTYPE (type));
2502 g_assert (is_generic_parameter (type->type));
2503 return mono_generic_param_info (type->type->data.generic_param)->flags;
2506 ICALL_EXPORT MonoArray *
2507 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2509 MonoGenericParamInfo *param_info;
2515 MONO_ARCH_SAVE_REGS;
2517 g_assert (IS_MONOTYPE (type));
2519 domain = mono_object_domain (type);
2520 param_info = mono_generic_param_info (type->type->data.generic_param);
2521 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2524 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2525 for (i = 0; i < count; i++)
2526 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2532 ICALL_EXPORT MonoBoolean
2533 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2535 MONO_ARCH_SAVE_REGS;
2536 return is_generic_parameter (type->type);
2539 ICALL_EXPORT MonoBoolean
2540 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2542 MONO_ARCH_SAVE_REGS;
2543 return is_generic_parameter (tb->type.type);
2547 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2548 MonoReflectionType *t)
2550 enumtype->type = t->type;
2553 ICALL_EXPORT MonoReflectionMethod*
2554 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2555 MonoReflectionMethod* generic)
2562 MONO_ARCH_SAVE_REGS;
2564 domain = ((MonoObject *)type)->vtable->domain;
2566 klass = mono_class_from_mono_type (type->type);
2567 mono_class_init_or_throw (klass);
2570 while ((method = mono_class_get_methods (klass, &iter))) {
2571 if (method->token == generic->method->token)
2572 return mono_method_get_object (domain, method, klass);
2580 ICALL_EXPORT MonoReflectionMethod *
2581 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2584 MonoType *type = ref_type->type;
2586 MONO_ARCH_SAVE_REGS;
2588 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2589 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2590 if (type->type == MONO_TYPE_VAR)
2593 method = mono_type_get_generic_param_owner (type)->owner.method;
2595 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2598 ICALL_EXPORT MonoReflectionDllImportAttribute*
2599 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2601 static MonoClass *DllImportAttributeClass = NULL;
2602 MonoDomain *domain = mono_domain_get ();
2603 MonoReflectionDllImportAttribute *attr;
2604 MonoImage *image = method->klass->image;
2605 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2606 MonoTableInfo *tables = image->tables;
2607 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2608 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2609 guint32 im_cols [MONO_IMPLMAP_SIZE];
2610 guint32 scope_token;
2611 const char *import = NULL;
2612 const char *scope = NULL;
2615 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2618 if (!DllImportAttributeClass) {
2619 DllImportAttributeClass =
2620 mono_class_from_name (mono_defaults.corlib,
2621 "System.Runtime.InteropServices", "DllImportAttribute");
2622 g_assert (DllImportAttributeClass);
2625 if (image_is_dynamic (method->klass->image)) {
2626 MonoReflectionMethodAux *method_aux =
2627 g_hash_table_lookup (
2628 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2630 import = method_aux->dllentry;
2631 scope = method_aux->dll;
2634 if (!import || !scope) {
2635 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2640 if (piinfo->implmap_idx) {
2641 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2643 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2644 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2645 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2646 scope = mono_metadata_string_heap (image, scope_token);
2649 flags = piinfo->piflags;
2651 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2653 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2654 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2655 attr->call_conv = (flags & 0x700) >> 8;
2656 attr->charset = ((flags & 0x6) >> 1) + 1;
2657 if (attr->charset == 1)
2659 attr->exact_spelling = (flags & 0x1) != 0;
2660 attr->set_last_error = (flags & 0x40) != 0;
2661 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2662 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2663 attr->preserve_sig = FALSE;
2668 ICALL_EXPORT MonoReflectionMethod *
2669 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2671 MonoMethodInflated *imethod;
2674 MONO_ARCH_SAVE_REGS;
2676 if (method->method->is_generic)
2679 if (!method->method->is_inflated)
2682 imethod = (MonoMethodInflated *) method->method;
2684 result = imethod->declaring;
2685 /* Not a generic method. */
2686 if (!result->is_generic)
2689 if (image_is_dynamic (method->method->klass->image)) {
2690 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2691 MonoReflectionMethod *res;
2694 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2695 * the dynamic case as well ?
2697 mono_image_lock ((MonoImage*)image);
2698 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2699 mono_image_unlock ((MonoImage*)image);
2705 if (imethod->context.class_inst) {
2706 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2707 /*Generic methods gets the context of the GTD.*/
2708 if (mono_class_get_context (klass))
2709 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2712 return mono_method_get_object (mono_object_domain (method), result, NULL);
2715 ICALL_EXPORT gboolean
2716 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2718 MONO_ARCH_SAVE_REGS;
2720 return mono_method_signature (method->method)->generic_param_count != 0;
2723 ICALL_EXPORT gboolean
2724 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2726 MONO_ARCH_SAVE_REGS;
2728 return method->method->is_generic;
2731 ICALL_EXPORT MonoArray*
2732 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2737 MONO_ARCH_SAVE_REGS;
2739 domain = mono_object_domain (method);
2741 if (method->method->is_inflated) {
2742 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2745 count = inst->type_argc;
2746 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2748 for (i = 0; i < count; i++)
2749 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2755 count = mono_method_signature (method->method)->generic_param_count;
2756 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2758 for (i = 0; i < count; i++) {
2759 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2760 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2761 MonoClass *pklass = mono_class_from_generic_parameter (
2762 param, method->method->klass->image, TRUE);
2763 mono_array_setref (res, i,
2764 mono_type_get_object (domain, &pklass->byval_arg));
2770 ICALL_EXPORT MonoObject *
2771 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2774 * Invoke from reflection is supposed to always be a virtual call (the API
2775 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2776 * greater flexibility.
2778 MonoMethod *m = method->method;
2779 MonoMethodSignature *sig = mono_method_signature (m);
2784 MONO_ARCH_SAVE_REGS;
2788 if (mono_security_core_clr_enabled ())
2789 mono_security_core_clr_ensure_reflection_access_method (m);
2791 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2792 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2793 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2798 if (!mono_object_isinst (this, m->klass)) {
2799 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2800 char *target_name = mono_type_get_full_name (m->klass);
2801 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2802 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2804 g_free (target_name);
2808 m = mono_object_get_virtual_method (this, m);
2809 /* must pass the pointer to the value for valuetype methods */
2810 if (m->klass->valuetype)
2811 obj = mono_object_unbox (this);
2812 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2813 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2818 if (sig->ret->byref) {
2819 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"));
2823 pcount = params? mono_array_length (params): 0;
2824 if (pcount != sig->param_count) {
2825 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2829 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2830 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."));
2834 image = m->klass->image;
2835 if (image->assembly->ref_only) {
2836 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."));
2840 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2841 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2845 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2848 intptr_t *lower_bounds;
2849 pcount = mono_array_length (params);
2850 lengths = alloca (sizeof (uintptr_t) * pcount);
2851 /* Note: the synthetized array .ctors have int32 as argument type */
2852 for (i = 0; i < pcount; ++i)
2853 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2855 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2856 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2857 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2859 for (i = 0; i < mono_array_length (arr); ++i) {
2860 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2862 mono_array_setref_fast (arr, i, subarray);
2864 return (MonoObject*)arr;
2867 if (m->klass->rank == pcount) {
2868 /* Only lengths provided. */
2869 lower_bounds = NULL;
2871 g_assert (pcount == (m->klass->rank * 2));
2872 /* lower bounds are first. */
2873 lower_bounds = (intptr_t*)lengths;
2874 lengths += m->klass->rank;
2877 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2879 return mono_runtime_invoke_array (m, obj, params, NULL);
2882 #ifndef DISABLE_REMOTING
2883 ICALL_EXPORT MonoObject *
2884 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2886 MonoDomain *domain = mono_object_domain (method);
2887 MonoMethod *m = method->method;
2888 MonoMethodSignature *sig = mono_method_signature (m);
2889 MonoArray *out_args;
2891 int i, j, outarg_count = 0;
2893 MONO_ARCH_SAVE_REGS;
2895 if (m->klass == mono_defaults.object_class) {
2897 if (!strcmp (m->name, "FieldGetter")) {
2898 MonoClass *k = this->vtable->klass;
2902 /* If this is a proxy, then it must be a CBO */
2903 if (k == mono_defaults.transparent_proxy_class) {
2904 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2905 this = tp->rp->unwrapped_server;
2907 k = this->vtable->klass;
2910 name = mono_array_get (params, MonoString *, 1);
2911 str = mono_string_to_utf8 (name);
2914 MonoClassField* field = mono_class_get_field_from_name (k, str);
2916 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2917 if (field_klass->valuetype)
2918 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2920 result = *((gpointer *)((char *)this + field->offset));
2922 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2923 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2924 mono_array_setref (out_args, 0, result);
2932 g_assert_not_reached ();
2934 } else if (!strcmp (m->name, "FieldSetter")) {
2935 MonoClass *k = this->vtable->klass;
2941 /* If this is a proxy, then it must be a CBO */
2942 if (k == mono_defaults.transparent_proxy_class) {
2943 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2944 this = tp->rp->unwrapped_server;
2946 k = this->vtable->klass;
2949 name = mono_array_get (params, MonoString *, 1);
2950 str = mono_string_to_utf8 (name);
2953 MonoClassField* field = mono_class_get_field_from_name (k, str);
2955 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2956 MonoObject *val = mono_array_get (params, gpointer, 2);
2958 if (field_klass->valuetype) {
2959 size = mono_type_size (field->type, &align);
2960 g_assert (size == mono_class_value_size (field_klass, NULL));
2961 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2963 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2966 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2967 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2977 g_assert_not_reached ();
2982 for (i = 0; i < mono_array_length (params); i++) {
2983 if (sig->params [i]->byref)
2987 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2989 /* handle constructors only for objects already allocated */
2990 if (!strcmp (method->method->name, ".ctor"))
2993 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2994 g_assert (!method->method->klass->valuetype);
2995 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2997 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2998 if (sig->params [i]->byref) {
3000 arg = mono_array_get (params, gpointer, i);
3001 mono_array_setref (out_args, j, arg);
3006 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3013 read_enum_value (char *mem, int type)
3016 case MONO_TYPE_BOOLEAN:
3018 return *(guint8*)mem;
3020 return *(gint8*)mem;
3021 case MONO_TYPE_CHAR:
3023 return *(guint16*)mem;
3025 return *(gint16*)mem;
3027 return *(guint32*)mem;
3029 return *(gint32*)mem;
3031 return *(guint64*)mem;
3033 return *(gint64*)mem;
3035 g_assert_not_reached ();
3041 write_enum_value (char *mem, int type, guint64 value)
3045 case MONO_TYPE_I1: {
3046 guint8 *p = (guint8*)mem;
3051 case MONO_TYPE_I2: {
3052 guint16 *p = (void*)mem;
3057 case MONO_TYPE_I4: {
3058 guint32 *p = (void*)mem;
3063 case MONO_TYPE_I8: {
3064 guint64 *p = (void*)mem;
3069 g_assert_not_reached ();
3074 ICALL_EXPORT MonoObject *
3075 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3078 MonoClass *enumc, *objc;
3083 MONO_ARCH_SAVE_REGS;
3085 MONO_CHECK_ARG_NULL (enumType);
3086 MONO_CHECK_ARG_NULL (value);
3088 domain = mono_object_domain (enumType);
3089 enumc = mono_class_from_mono_type (enumType->type);
3091 mono_class_init_or_throw (enumc);
3093 objc = value->vtable->klass;
3095 if (!enumc->enumtype)
3096 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3097 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_BOOLEAN && objc->byval_arg.type <= MONO_TYPE_U8)))
3098 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."));
3100 etype = mono_class_enum_basetype (enumc);
3102 /* MS throws this for typebuilders */
3103 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3105 res = mono_object_new (domain, enumc);
3106 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3107 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3112 ICALL_EXPORT MonoObject *
3113 ves_icall_System_Enum_get_value (MonoObject *this)
3121 MONO_ARCH_SAVE_REGS;
3126 g_assert (this->vtable->klass->enumtype);
3128 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3129 res = mono_object_new (mono_object_domain (this), enumc);
3130 dst = (char *)res + sizeof (MonoObject);
3131 src = (char *)this + sizeof (MonoObject);
3132 size = mono_class_value_size (enumc, NULL);
3134 memcpy (dst, src, size);
3139 ICALL_EXPORT MonoReflectionType *
3140 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3145 MONO_ARCH_SAVE_REGS;
3147 klass = mono_class_from_mono_type (type->type);
3148 mono_class_init_or_throw (klass);
3150 etype = mono_class_enum_basetype (klass);
3152 /* MS throws this for typebuilders */
3153 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3155 return mono_type_get_object (mono_object_domain (type), etype);
3159 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3161 gpointer tdata = (char *)this + sizeof (MonoObject);
3162 gpointer odata = (char *)other + sizeof (MonoObject);
3163 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3164 g_assert (basetype);
3166 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3167 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3168 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3171 return me > other ? 1 : -1; \
3174 switch (basetype->type) {
3176 COMPARE_ENUM_VALUES (guint8);
3178 COMPARE_ENUM_VALUES (gint8);
3179 case MONO_TYPE_CHAR:
3181 COMPARE_ENUM_VALUES (guint16);
3183 COMPARE_ENUM_VALUES (gint16);
3185 COMPARE_ENUM_VALUES (guint32);
3187 COMPARE_ENUM_VALUES (gint32);
3189 COMPARE_ENUM_VALUES (guint64);
3191 COMPARE_ENUM_VALUES (gint64);
3193 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3195 #undef COMPARE_ENUM_VALUES
3200 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3202 gpointer data = (char *)this + sizeof (MonoObject);
3203 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3204 g_assert (basetype);
3206 switch (basetype->type) {
3208 return *((gint8*)data);
3210 return *((guint8*)data);
3211 case MONO_TYPE_CHAR:
3213 return *((guint16*)data);
3216 return *((gint16*)data);
3218 return *((guint32*)data);
3220 return *((gint32*)data);
3222 case MONO_TYPE_I8: {
3223 gint64 value = *((gint64*)data);
3224 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3227 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3233 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3235 MonoDomain *domain = mono_object_domain (type);
3236 MonoClass *enumc = mono_class_from_mono_type (type->type);
3237 guint j = 0, nvalues, crow;
3239 MonoClassField *field;
3241 MONO_ARCH_SAVE_REGS;
3243 mono_class_init_or_throw (enumc);
3245 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3246 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3247 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3248 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3252 while ((field = mono_class_get_fields (enumc, &iter))) {
3255 MonoTypeEnum def_type;
3257 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3259 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3261 if (mono_field_is_deleted (field))
3263 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3265 p = mono_class_get_field_default_value (field, &def_type);
3266 len = mono_metadata_decode_blob_size (p, &p);
3267 switch (mono_class_enum_basetype (enumc)->type) {
3270 mono_array_set (info->values, gchar, j, *p);
3272 case MONO_TYPE_CHAR:
3275 mono_array_set (info->values, gint16, j, read16 (p));
3279 mono_array_set (info->values, gint32, j, read32 (p));
3283 mono_array_set (info->values, gint64, j, read64 (p));
3286 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3293 BFLAGS_IgnoreCase = 1,
3294 BFLAGS_DeclaredOnly = 2,
3295 BFLAGS_Instance = 4,
3297 BFLAGS_Public = 0x10,
3298 BFLAGS_NonPublic = 0x20,
3299 BFLAGS_FlattenHierarchy = 0x40,
3300 BFLAGS_InvokeMethod = 0x100,
3301 BFLAGS_CreateInstance = 0x200,
3302 BFLAGS_GetField = 0x400,
3303 BFLAGS_SetField = 0x800,
3304 BFLAGS_GetProperty = 0x1000,
3305 BFLAGS_SetProperty = 0x2000,
3306 BFLAGS_ExactBinding = 0x10000,
3307 BFLAGS_SuppressChangeType = 0x20000,
3308 BFLAGS_OptionalParamBinding = 0x40000
3311 ICALL_EXPORT MonoReflectionField *
3312 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3315 MonoClass *startklass, *klass;
3317 MonoClassField *field;
3320 int (*compare_func) (const char *s1, const char *s2) = NULL;
3321 domain = ((MonoObject *)type)->vtable->domain;
3322 klass = startklass = mono_class_from_mono_type (type->type);
3325 mono_raise_exception (mono_get_exception_argument_null ("name"));
3326 if (type->type->byref)
3329 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3332 if (klass->exception_type != MONO_EXCEPTION_NONE)
3333 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3336 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3337 guint32 flags = mono_field_get_flags (field);
3340 if (mono_field_is_deleted_with_flags (field, flags))
3342 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3343 if (bflags & BFLAGS_Public)
3345 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3346 if (bflags & BFLAGS_NonPublic) {
3353 if (flags & FIELD_ATTRIBUTE_STATIC) {
3354 if (bflags & BFLAGS_Static)
3355 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3358 if (bflags & BFLAGS_Instance)
3365 utf8_name = mono_string_to_utf8 (name);
3367 if (compare_func (mono_field_get_name (field), utf8_name)) {
3373 return mono_field_get_object (domain, klass, field);
3375 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3381 ICALL_EXPORT MonoArray*
3382 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3385 MonoClass *startklass, *klass, *refklass;
3390 MonoClassField *field;
3391 MonoPtrArray tmp_array;
3393 MONO_ARCH_SAVE_REGS;
3395 domain = ((MonoObject *)type)->vtable->domain;
3396 if (type->type->byref)
3397 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3398 klass = startklass = mono_class_from_mono_type (type->type);
3399 refklass = mono_class_from_mono_type (reftype->type);
3401 mono_ptr_array_init (tmp_array, 2);
3404 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3405 mono_ptr_array_destroy (tmp_array);
3406 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3410 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3411 guint32 flags = mono_field_get_flags (field);
3413 if (mono_field_is_deleted_with_flags (field, flags))
3415 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3416 if (bflags & BFLAGS_Public)
3418 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3419 if (bflags & BFLAGS_NonPublic) {
3426 if (flags & FIELD_ATTRIBUTE_STATIC) {
3427 if (bflags & BFLAGS_Static)
3428 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3431 if (bflags & BFLAGS_Instance)
3437 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3438 mono_ptr_array_append (tmp_array, member);
3440 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3443 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3445 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3446 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3448 mono_ptr_array_destroy (tmp_array);
3454 method_nonpublic (MonoMethod* method, gboolean start_klass)
3456 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3457 case METHOD_ATTRIBUTE_ASSEM:
3458 return (start_klass || mono_defaults.generic_ilist_class);
3459 case METHOD_ATTRIBUTE_PRIVATE:
3461 case METHOD_ATTRIBUTE_PUBLIC:
3469 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3472 MonoClass *startklass;
3475 int len, match, nslots;
3476 /*FIXME, use MonoBitSet*/
3477 guint32 method_slots_default [8];
3478 guint32 *method_slots = NULL;
3479 int (*compare_func) (const char *s1, const char *s2) = NULL;
3481 array = g_ptr_array_new ();
3487 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3489 /* An optimization for calls made from Delegate:CreateDelegate () */
3490 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3491 method = mono_get_delegate_invoke (klass);
3492 if (mono_loader_get_last_error ())
3495 g_ptr_array_add (array, method);
3499 mono_class_setup_vtable (klass);
3500 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3503 if (is_generic_parameter (&klass->byval_arg))
3504 nslots = mono_class_get_vtable_size (klass->parent);
3506 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3507 if (nslots >= sizeof (method_slots_default) * 8) {
3508 method_slots = g_new0 (guint32, nslots / 32 + 1);
3510 method_slots = method_slots_default;
3511 memset (method_slots, 0, sizeof (method_slots_default));
3514 mono_class_setup_vtable (klass);
3515 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3519 while ((method = mono_class_get_methods (klass, &iter))) {
3521 if (method->slot != -1) {
3522 g_assert (method->slot < nslots);
3523 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3525 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3526 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3529 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3531 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3532 if (bflags & BFLAGS_Public)
3534 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3540 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3541 if (bflags & BFLAGS_Static)
3542 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3545 if (bflags & BFLAGS_Instance)
3553 if (compare_func (name, method->name))
3558 g_ptr_array_add (array, method);
3560 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3562 if (method_slots != method_slots_default)
3563 g_free (method_slots);
3568 if (method_slots != method_slots_default)
3569 g_free (method_slots);
3570 g_ptr_array_free (array, TRUE);
3572 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3573 *ex = mono_class_get_exception_for_failure (klass);
3575 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3576 mono_loader_clear_error ();
3581 ICALL_EXPORT MonoArray*
3582 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3584 static MonoClass *MethodInfo_array;
3587 MonoVTable *array_vtable;
3588 MonoException *ex = NULL;
3589 const char *mname = NULL;
3590 GPtrArray *method_array;
3591 MonoClass *klass, *refklass;
3594 if (!MethodInfo_array) {
3595 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3596 mono_memory_barrier ();
3597 MethodInfo_array = klass;
3600 klass = mono_class_from_mono_type (type->type);
3601 refklass = mono_class_from_mono_type (reftype->type);
3602 domain = ((MonoObject *)type)->vtable->domain;
3603 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3604 if (type->type->byref)
3605 return mono_array_new_specific (array_vtable, 0);
3608 mname = mono_string_to_utf8 (name);
3610 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3611 g_free ((char*)mname);
3613 mono_raise_exception (ex);
3615 res = mono_array_new_specific (array_vtable, method_array->len);
3618 for (i = 0; i < method_array->len; ++i) {
3619 MonoMethod *method = g_ptr_array_index (method_array, i);
3620 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3623 g_ptr_array_free (method_array, TRUE);
3627 ICALL_EXPORT MonoArray*
3628 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3631 static MonoClass *System_Reflection_ConstructorInfo;
3632 MonoClass *startklass, *klass, *refklass;
3637 gpointer iter = NULL;
3638 MonoPtrArray tmp_array;
3640 MONO_ARCH_SAVE_REGS;
3642 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3644 domain = ((MonoObject *)type)->vtable->domain;
3645 if (type->type->byref)
3646 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3647 klass = startklass = mono_class_from_mono_type (type->type);
3648 refklass = mono_class_from_mono_type (reftype->type);
3650 if (!System_Reflection_ConstructorInfo)
3651 System_Reflection_ConstructorInfo = mono_class_from_name (
3652 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3655 while ((method = mono_class_get_methods (klass, &iter))) {
3657 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3659 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3660 if (bflags & BFLAGS_Public)
3663 if (bflags & BFLAGS_NonPublic)
3669 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3670 if (bflags & BFLAGS_Static)
3671 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3674 if (bflags & BFLAGS_Instance)
3680 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3682 mono_ptr_array_append (tmp_array, member);
3685 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3687 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3688 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3690 mono_ptr_array_destroy (tmp_array);
3696 property_hash (gconstpointer data)
3698 MonoProperty *prop = (MonoProperty*)data;
3700 return g_str_hash (prop->name);
3704 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3706 // Properties are hide-by-name-and-signature
3707 if (!g_str_equal (prop1->name, prop2->name))
3710 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3712 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3718 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3723 return method_nonpublic (accessor, start_klass);
3726 ICALL_EXPORT MonoArray*
3727 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3731 static MonoClass *System_Reflection_PropertyInfo;
3732 MonoClass *startklass, *klass;
3738 gchar *propname = NULL;
3739 int (*compare_func) (const char *s1, const char *s2) = NULL;
3741 GHashTable *properties = NULL;
3742 MonoPtrArray tmp_array;
3744 MONO_ARCH_SAVE_REGS;
3746 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3748 if (!System_Reflection_PropertyInfo)
3749 System_Reflection_PropertyInfo = mono_class_from_name (
3750 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3752 domain = ((MonoObject *)type)->vtable->domain;
3753 if (type->type->byref)
3754 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3755 klass = startklass = mono_class_from_mono_type (type->type);
3758 propname = mono_string_to_utf8 (name);
3759 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3762 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3764 mono_class_setup_vtable (klass);
3765 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3769 while ((prop = mono_class_get_properties (klass, &iter))) {
3775 flags = method->flags;
3778 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3779 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3780 if (bflags & BFLAGS_Public)
3782 } else if (bflags & BFLAGS_NonPublic) {
3783 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3784 property_accessor_nonpublic(prop->set, startklass == klass)) {
3791 if (flags & METHOD_ATTRIBUTE_STATIC) {
3792 if (bflags & BFLAGS_Static)
3793 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3796 if (bflags & BFLAGS_Instance)
3805 if (compare_func (propname, prop->name))
3809 if (g_hash_table_lookup (properties, prop))
3812 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3814 g_hash_table_insert (properties, prop, prop);
3816 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3819 g_hash_table_destroy (properties);
3822 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3823 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3824 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3826 mono_ptr_array_destroy (tmp_array);
3832 g_hash_table_destroy (properties);
3835 mono_ptr_array_destroy (tmp_array);
3837 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3838 ex = mono_class_get_exception_for_failure (klass);
3840 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3841 mono_loader_clear_error ();
3843 mono_raise_exception (ex);
3847 ICALL_EXPORT MonoReflectionEvent *
3848 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3851 MonoClass *klass, *startklass;
3856 int (*compare_func) (const char *s1, const char *s2);
3858 MONO_ARCH_SAVE_REGS;
3860 event_name = mono_string_to_utf8 (name);
3861 if (type->type->byref)
3863 klass = startklass = mono_class_from_mono_type (type->type);
3864 domain = mono_object_domain (type);
3866 mono_class_init_or_throw (klass);
3868 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3870 if (klass->exception_type != MONO_EXCEPTION_NONE)
3871 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3874 while ((event = mono_class_get_events (klass, &iter))) {
3875 if (compare_func (event->name, event_name))
3878 method = event->add;
3880 method = event->remove;
3882 method = event->raise;
3884 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3885 if (!(bflags & BFLAGS_Public))
3888 if (!(bflags & BFLAGS_NonPublic))
3890 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3894 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3895 if (!(bflags & BFLAGS_Static))
3897 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3900 if (!(bflags & BFLAGS_Instance))
3904 if (!(bflags & BFLAGS_NonPublic))
3907 g_free (event_name);
3908 return mono_event_get_object (domain, startklass, event);
3911 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3914 g_free (event_name);
3919 event_hash (gconstpointer data)
3921 MonoEvent *event = (MonoEvent*)data;
3923 return g_str_hash (event->name);
3927 event_equal (MonoEvent *event1, MonoEvent *event2)
3929 // Events are hide-by-name
3930 return g_str_equal (event1->name, event2->name);
3933 ICALL_EXPORT MonoArray*
3934 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3938 static MonoClass *System_Reflection_EventInfo;
3939 MonoClass *startklass, *klass;
3945 GHashTable *events = NULL;
3946 MonoPtrArray tmp_array;
3948 MONO_ARCH_SAVE_REGS;
3950 mono_ptr_array_init (tmp_array, 4);
3952 if (!System_Reflection_EventInfo)
3953 System_Reflection_EventInfo = mono_class_from_name (
3954 mono_defaults.corlib, "System.Reflection", "EventInfo");
3956 domain = mono_object_domain (type);
3957 if (type->type->byref)
3958 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3959 klass = startklass = mono_class_from_mono_type (type->type);
3961 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3963 mono_class_setup_vtable (klass);
3964 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3968 while ((event = mono_class_get_events (klass, &iter))) {
3970 method = event->add;
3972 method = event->remove;
3974 method = event->raise;
3976 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3977 if (bflags & BFLAGS_Public)
3979 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3980 if (bflags & BFLAGS_NonPublic)
3985 if (bflags & BFLAGS_NonPublic)
3991 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3992 if (bflags & BFLAGS_Static)
3993 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3996 if (bflags & BFLAGS_Instance)
4001 if (bflags & BFLAGS_Instance)
4006 if (g_hash_table_lookup (events, event))
4009 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4011 g_hash_table_insert (events, event, event);
4013 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4016 g_hash_table_destroy (events);
4018 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4020 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4021 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4023 mono_ptr_array_destroy (tmp_array);
4028 mono_ptr_array_destroy (tmp_array);
4029 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4030 ex = mono_class_get_exception_for_failure (klass);
4032 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4033 mono_loader_clear_error ();
4035 mono_raise_exception (ex);
4039 ICALL_EXPORT MonoReflectionType *
4040 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4048 MONO_ARCH_SAVE_REGS;
4051 mono_raise_exception (mono_get_exception_argument_null ("name"));
4053 domain = ((MonoObject *)type)->vtable->domain;
4054 if (type->type->byref)
4056 klass = mono_class_from_mono_type (type->type);
4058 str = mono_string_to_utf8 (name);
4061 if (klass->exception_type != MONO_EXCEPTION_NONE)
4062 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4065 * If a nested type is generic, return its generic type definition.
4066 * Note that this means that the return value is essentially a
4067 * nested type of the generic type definition of @klass.
4069 * A note in MSDN claims that a generic type definition can have
4070 * nested types that aren't generic. In any case, the container of that
4071 * nested type would be the generic type definition.
4073 if (klass->generic_class)
4074 klass = klass->generic_class->container_class;
4077 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4079 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4080 if (bflags & BFLAGS_Public)
4083 if (bflags & BFLAGS_NonPublic)
4088 if (strcmp (nested->name, str) == 0){
4090 return mono_type_get_object (domain, &nested->byval_arg);
4093 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4099 ICALL_EXPORT MonoArray*
4100 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4109 MonoPtrArray tmp_array;
4111 MONO_ARCH_SAVE_REGS;
4113 domain = ((MonoObject *)type)->vtable->domain;
4114 if (type->type->byref)
4115 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4116 klass = mono_class_from_mono_type (type->type);
4119 * If a nested type is generic, return its generic type definition.
4120 * Note that this means that the return value is essentially the set
4121 * of nested types of the generic type definition of @klass.
4123 * A note in MSDN claims that a generic type definition can have
4124 * nested types that aren't generic. In any case, the container of that
4125 * nested type would be the generic type definition.
4127 if (klass->generic_class)
4128 klass = klass->generic_class->container_class;
4130 mono_ptr_array_init (tmp_array, 1);
4132 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4134 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4135 if (bflags & BFLAGS_Public)
4138 if (bflags & BFLAGS_NonPublic)
4143 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4144 mono_ptr_array_append (tmp_array, member);
4147 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4149 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4150 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4152 mono_ptr_array_destroy (tmp_array);
4157 ICALL_EXPORT MonoReflectionType*
4158 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4161 MonoType *type = NULL;
4162 MonoTypeNameParse info;
4163 gboolean type_resolve;
4165 MONO_ARCH_SAVE_REGS;
4167 /* On MS.NET, this does not fire a TypeResolve event */
4168 type_resolve = TRUE;
4169 str = mono_string_to_utf8 (name);
4170 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4171 if (!mono_reflection_parse_type (str, &info)) {
4173 mono_reflection_free_type_info (&info);
4174 if (throwOnError) /* uhm: this is a parse error, though... */
4175 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4176 /*g_print ("failed parse\n");*/
4180 if (info.assembly.name) {
4182 mono_reflection_free_type_info (&info);
4184 /* 1.0 and 2.0 throw different exceptions */
4185 if (mono_defaults.generic_ilist_class)
4186 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4188 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4193 if (module != NULL) {
4195 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4200 if (assembly_is_dynamic (assembly->assembly)) {
4201 /* Enumerate all modules */
4202 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4206 if (abuilder->modules) {
4207 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4208 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4209 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4215 if (!type && abuilder->loaded_modules) {
4216 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4217 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4218 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4225 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4227 mono_reflection_free_type_info (&info);
4229 MonoException *e = NULL;
4232 e = mono_get_exception_type_load (name, NULL);
4234 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4235 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4237 mono_loader_clear_error ();
4240 mono_raise_exception (e);
4243 } else if (mono_loader_get_last_error ()) {
4245 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4246 mono_loader_clear_error ();
4249 if (type->type == MONO_TYPE_CLASS) {
4250 MonoClass *klass = mono_type_get_class (type);
4252 if (mono_security_enabled () && !klass->exception_type)
4253 /* Some security problems are detected during generic vtable construction */
4254 mono_class_setup_vtable (klass);
4256 /* need to report exceptions ? */
4257 if (throwOnError && klass->exception_type) {
4258 /* report SecurityException (or others) that occured when loading the assembly */
4259 MonoException *exc = mono_class_get_exception_for_failure (klass);
4260 mono_loader_clear_error ();
4261 mono_raise_exception (exc);
4262 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4267 /* g_print ("got it\n"); */
4268 return mono_type_get_object (mono_object_domain (assembly), type);
4272 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4275 gchar *shadow_ini_file;
4278 /* Check for shadow-copied assembly */
4279 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4280 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4282 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4283 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4289 g_free (shadow_ini_file);
4290 if (content != NULL) {
4293 *filename = content;
4300 ICALL_EXPORT MonoString *
4301 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4303 MonoDomain *domain = mono_object_domain (assembly);
4304 MonoAssembly *mass = assembly->assembly;
4305 MonoString *res = NULL;
4310 MONO_ARCH_SAVE_REGS;
4312 if (g_path_is_absolute (mass->image->name)) {
4313 absolute = g_strdup (mass->image->name);
4314 dirname = g_path_get_dirname (absolute);
4316 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4317 dirname = g_strdup (mass->basedir);
4320 replace_shadow_path (domain, dirname, &absolute);
4325 for (i = strlen (absolute) - 1; i >= 0; i--)
4326 if (absolute [i] == '\\')
4331 uri = g_filename_to_uri (absolute, NULL, NULL);
4333 const char *prepend = "file://";
4335 if (*absolute == '/' && *(absolute + 1) == '/') {
4338 prepend = "file:///";
4341 uri = g_strconcat (prepend, absolute, NULL);
4345 res = mono_string_new (domain, uri);
4352 ICALL_EXPORT MonoBoolean
4353 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4355 MonoAssembly *mass = assembly->assembly;
4357 MONO_ARCH_SAVE_REGS;
4359 return mass->in_gac;
4362 ICALL_EXPORT MonoReflectionAssembly*
4363 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4367 MonoImageOpenStatus status;
4369 MONO_ARCH_SAVE_REGS;
4371 name = mono_string_to_utf8 (mname);
4372 res = mono_assembly_load_with_partial_name (name, &status);
4378 return mono_assembly_get_object (mono_domain_get (), res);
4381 ICALL_EXPORT MonoString *
4382 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4384 MonoDomain *domain = mono_object_domain (assembly);
4387 MONO_ARCH_SAVE_REGS;
4389 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4394 ICALL_EXPORT MonoBoolean
4395 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4397 MONO_ARCH_SAVE_REGS;
4399 return assembly->assembly->ref_only;
4402 ICALL_EXPORT MonoString *
4403 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4405 MonoDomain *domain = mono_object_domain (assembly);
4407 MONO_ARCH_SAVE_REGS;
4409 return mono_string_new (domain, assembly->assembly->image->version);
4412 ICALL_EXPORT MonoReflectionMethod*
4413 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4415 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4417 MONO_ARCH_SAVE_REGS;
4421 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4424 ICALL_EXPORT MonoReflectionModule*
4425 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4427 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4430 ICALL_EXPORT MonoArray*
4431 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4433 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4434 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4438 MONO_ARCH_SAVE_REGS;
4440 for (i = 0; i < table->rows; ++i) {
4441 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4442 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4448 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4450 static MonoClass *System_Version = NULL;
4451 static MonoMethod *create_version = NULL;
4455 if (!System_Version) {
4456 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4457 g_assert (System_Version);
4460 if (!create_version) {
4461 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4462 create_version = mono_method_desc_search_in_class (desc, System_Version);
4463 g_assert (create_version);
4464 mono_method_desc_free (desc);
4470 args [3] = &revision;
4471 result = mono_object_new (domain, System_Version);
4472 mono_runtime_invoke (create_version, result, args, NULL);
4477 ICALL_EXPORT MonoArray*
4478 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4480 static MonoClass *System_Reflection_AssemblyName;
4482 MonoDomain *domain = mono_object_domain (assembly);
4484 static MonoMethod *create_culture = NULL;
4485 MonoImage *image = assembly->assembly->image;
4488 MONO_ARCH_SAVE_REGS;
4490 if (!System_Reflection_AssemblyName)
4491 System_Reflection_AssemblyName = mono_class_from_name (
4492 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4494 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4497 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4499 if (count > 0 && !create_culture) {
4500 MonoMethodDesc *desc = mono_method_desc_new (
4501 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4502 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4503 g_assert (create_culture);
4504 mono_method_desc_free (desc);
4507 for (i = 0; i < count; i++) {
4508 MonoReflectionAssemblyName *aname;
4509 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4511 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4513 aname = (MonoReflectionAssemblyName *) mono_object_new (
4514 domain, System_Reflection_AssemblyName);
4516 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4518 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4519 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4520 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4521 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4522 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4523 aname->versioncompat = 1; /* SameMachine (default) */
4524 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4525 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4527 if (create_culture) {
4529 MonoBoolean assembly_ref = 1;
4530 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4531 args [1] = &assembly_ref;
4532 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4535 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4536 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4537 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4539 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4540 /* public key token isn't copied - the class library will
4541 automatically generate it from the public key if required */
4542 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4543 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4545 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4546 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4549 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4552 /* note: this function doesn't return the codebase on purpose (i.e. it can
4553 be used under partial trust as path information isn't present). */
4555 mono_array_setref (result, i, aname);
4560 /* move this in some file in mono/util/ */
4562 g_concat_dir_and_file (const char *dir, const char *file)
4564 g_return_val_if_fail (dir != NULL, NULL);
4565 g_return_val_if_fail (file != NULL, NULL);
4568 * If the directory name doesn't have a / on the end, we need
4569 * to add one so we get a proper path to the file
4571 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4572 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4574 return g_strconcat (dir, file, NULL);
4578 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4580 char *n = mono_string_to_utf8 (name);
4581 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4583 guint32 cols [MONO_MANIFEST_SIZE];
4584 guint32 impl, file_idx;
4588 MONO_ARCH_SAVE_REGS;
4590 for (i = 0; i < table->rows; ++i) {
4591 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4592 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4593 if (strcmp (val, n) == 0)
4597 if (i == table->rows)
4600 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4603 * this code should only be called after obtaining the
4604 * ResourceInfo and handling the other cases.
4606 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4607 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4609 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4614 module = assembly->assembly->image;
4616 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4618 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4621 ICALL_EXPORT gboolean
4622 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4624 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4626 guint32 cols [MONO_MANIFEST_SIZE];
4627 guint32 file_cols [MONO_FILE_SIZE];
4631 MONO_ARCH_SAVE_REGS;
4633 n = mono_string_to_utf8 (name);
4634 for (i = 0; i < table->rows; ++i) {
4635 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4636 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4637 if (strcmp (val, n) == 0)
4641 if (i == table->rows)
4644 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4645 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4648 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4649 case MONO_IMPLEMENTATION_FILE:
4650 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4651 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4652 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4653 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4654 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4655 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4658 info->location = RESOURCE_LOCATION_EMBEDDED;
4661 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4662 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4663 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4664 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4665 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4666 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4668 mono_raise_exception (ex);
4670 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4672 /* Obtain info recursively */
4673 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4674 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4677 case MONO_IMPLEMENTATION_EXP_TYPE:
4678 g_assert_not_reached ();
4686 ICALL_EXPORT MonoObject*
4687 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4689 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4690 MonoArray *result = NULL;
4695 MONO_ARCH_SAVE_REGS;
4697 /* check hash if needed */
4699 n = mono_string_to_utf8 (name);
4700 for (i = 0; i < table->rows; ++i) {
4701 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4702 if (strcmp (val, n) == 0) {
4705 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4706 fn = mono_string_new (mono_object_domain (assembly), n);
4708 return (MonoObject*)fn;
4716 for (i = 0; i < table->rows; ++i) {
4717 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4721 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4724 for (i = 0; i < table->rows; ++i) {
4725 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4726 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4727 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4728 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4733 return (MonoObject*)result;
4736 ICALL_EXPORT MonoArray*
4737 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4739 MonoDomain *domain = mono_domain_get();
4742 int i, j, file_count = 0;
4743 MonoImage **modules;
4744 guint32 module_count, real_module_count;
4745 MonoTableInfo *table;
4746 guint32 cols [MONO_FILE_SIZE];
4747 MonoImage *image = assembly->assembly->image;
4749 g_assert (image != NULL);
4750 g_assert (!assembly_is_dynamic (assembly->assembly));
4752 table = &image->tables [MONO_TABLE_FILE];
4753 file_count = table->rows;
4755 modules = image->modules;
4756 module_count = image->module_count;
4758 real_module_count = 0;
4759 for (i = 0; i < module_count; ++i)
4761 real_module_count ++;
4763 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4764 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4766 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4768 for (i = 0; i < module_count; ++i)
4770 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4774 for (i = 0; i < file_count; ++i, ++j) {
4775 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4776 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4777 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4779 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4781 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4782 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4784 mono_array_setref (res, j, mono_module_get_object (domain, m));
4791 ICALL_EXPORT MonoReflectionMethod*
4792 ves_icall_GetCurrentMethod (void)
4794 MonoMethod *m = mono_method_get_last_managed ();
4796 while (m->is_inflated)
4797 m = ((MonoMethodInflated*)m)->declaring;
4799 return mono_method_get_object (mono_domain_get (), m, NULL);
4804 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4807 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4808 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4809 //method is inflated, we should inflate it on the other class
4810 MonoGenericContext ctx;
4811 ctx.method_inst = inflated->context.method_inst;
4812 ctx.class_inst = inflated->context.class_inst;
4813 if (klass->generic_class)
4814 ctx.class_inst = klass->generic_class->context.class_inst;
4815 else if (klass->generic_container)
4816 ctx.class_inst = klass->generic_container->context.class_inst;
4817 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4820 mono_class_setup_methods (method->klass);
4821 if (method->klass->exception_type)
4823 for (i = 0; i < method->klass->method.count; ++i) {
4824 if (method->klass->methods [i] == method) {
4829 mono_class_setup_methods (klass);
4830 if (klass->exception_type)
4832 g_assert (offset >= 0 && offset < klass->method.count);
4833 return klass->methods [offset];
4836 ICALL_EXPORT MonoReflectionMethod*
4837 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4841 klass = mono_class_from_mono_type (type);
4842 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4844 if (method->klass != klass) {
4845 method = mono_method_get_equivalent_method (method, klass);
4850 klass = method->klass;
4851 return mono_method_get_object (mono_domain_get (), method, klass);
4854 ICALL_EXPORT MonoReflectionMethod*
4855 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4857 return mono_method_get_object (mono_domain_get (), method, NULL);
4860 ICALL_EXPORT MonoReflectionMethodBody*
4861 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4863 return mono_method_body_get_object (mono_domain_get (), method);
4866 ICALL_EXPORT MonoReflectionAssembly*
4867 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4869 MonoMethod *dest = NULL;
4871 MONO_ARCH_SAVE_REGS;
4873 mono_stack_walk_no_il (get_executing, &dest);
4875 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4879 ICALL_EXPORT MonoReflectionAssembly*
4880 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4882 MonoDomain* domain = mono_domain_get ();
4884 MONO_ARCH_SAVE_REGS;
4886 if (!domain->entry_assembly)
4889 return mono_assembly_get_object (domain, domain->entry_assembly);
4892 ICALL_EXPORT MonoReflectionAssembly*
4893 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4898 MONO_ARCH_SAVE_REGS;
4901 mono_stack_walk_no_il (get_executing, &dest);
4903 mono_stack_walk_no_il (get_caller, &dest);
4906 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4909 ICALL_EXPORT MonoString *
4910 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4911 gboolean assembly_qualified)
4913 MonoDomain *domain = mono_object_domain (object);
4914 MonoTypeNameFormat format;
4919 format = assembly_qualified ?
4920 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4921 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4923 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4925 name = mono_type_get_name_full (object->type, format);
4929 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4934 res = mono_string_new (domain, name);
4941 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4943 MonoClass *klass = mono_class_from_mono_type (this->type);
4944 mono_class_init_or_throw (klass);
4945 return mono_security_core_clr_class_level (klass);
4949 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4951 static MonoMethod *create_culture = NULL;
4954 const char *pkey_ptr;
4956 MonoBoolean assembly_ref = 0;
4958 MONO_ARCH_SAVE_REGS;
4960 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4961 aname->major = name->major;
4962 aname->minor = name->minor;
4963 aname->build = name->build;
4964 aname->flags = name->flags;
4965 aname->revision = name->revision;
4966 aname->hashalg = name->hash_alg;
4967 aname->versioncompat = 1; /* SameMachine (default) */
4968 aname->processor_architecture = name->arch;
4970 if (by_default_version)
4971 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4974 if (absolute != NULL && *absolute != '\0') {
4975 const gchar *prepend = "file://";
4978 codebase = g_strdup (absolute);
4983 for (i = strlen (codebase) - 1; i >= 0; i--)
4984 if (codebase [i] == '\\')
4987 if (*codebase == '/' && *(codebase + 1) == '/') {
4990 prepend = "file:///";
4994 result = g_strconcat (prepend, codebase, NULL);
5000 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5004 if (!create_culture) {
5005 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5006 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5007 g_assert (create_culture);
5008 mono_method_desc_free (desc);
5011 if (name->culture) {
5012 args [0] = mono_string_new (domain, name->culture);
5013 args [1] = &assembly_ref;
5014 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5017 if (name->public_key) {
5018 pkey_ptr = (char*)name->public_key;
5019 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5021 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5022 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5023 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5024 } else if (default_publickey) {
5025 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5026 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5029 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5030 if (name->public_key_token [0]) {
5034 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5035 p = mono_array_addr (aname->keyToken, char, 0);
5037 for (i = 0, j = 0; i < 8; i++) {
5038 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5039 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5042 } else if (default_token) {
5043 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5047 ICALL_EXPORT MonoString *
5048 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5050 MonoDomain *domain = mono_object_domain (assembly);
5051 MonoAssembly *mass = assembly->assembly;
5055 name = mono_stringify_assembly_name (&mass->aname);
5056 res = mono_string_new (domain, name);
5063 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5066 MonoAssembly *mass = assembly->assembly;
5068 MONO_ARCH_SAVE_REGS;
5070 if (g_path_is_absolute (mass->image->name)) {
5071 fill_reflection_assembly_name (mono_object_domain (assembly),
5072 aname, &mass->aname, mass->image->name, TRUE,
5076 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5078 fill_reflection_assembly_name (mono_object_domain (assembly),
5079 aname, &mass->aname, absolute, TRUE, TRUE,
5086 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5089 MonoImageOpenStatus status = MONO_IMAGE_OK;
5092 MonoAssemblyName name;
5095 MONO_ARCH_SAVE_REGS;
5097 filename = mono_string_to_utf8 (fname);
5099 dirname = g_path_get_dirname (filename);
5100 replace_shadow_path (mono_domain_get (), dirname, &filename);
5103 image = mono_image_open (filename, &status);
5109 if (status == MONO_IMAGE_IMAGE_INVALID)
5110 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5112 exc = mono_get_exception_file_not_found2 (NULL, fname);
5113 mono_raise_exception (exc);
5116 res = mono_assembly_fill_assembly_name (image, &name);
5118 mono_image_close (image);
5120 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5123 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5127 mono_image_close (image);
5130 ICALL_EXPORT MonoBoolean
5131 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5132 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5134 MonoBoolean result = FALSE;
5135 MonoDeclSecurityEntry entry;
5137 /* SecurityAction.RequestMinimum */
5138 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5139 *minimum = entry.blob;
5140 *minLength = entry.size;
5143 /* SecurityAction.RequestOptional */
5144 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5145 *optional = entry.blob;
5146 *optLength = entry.size;
5149 /* SecurityAction.RequestRefuse */
5150 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5151 *refused = entry.blob;
5152 *refLength = entry.size;
5160 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5164 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5166 guint32 attrs, visibility;
5168 /* we start the count from 1 because we skip the special type <Module> */
5171 for (i = 1; i < tdef->rows; ++i) {
5172 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5173 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5174 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5178 count = tdef->rows - 1;
5180 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5181 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5183 for (i = 1; i < tdef->rows; ++i) {
5184 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5185 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5186 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5188 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5189 g_assert (!mono_loader_get_last_error ()); /* Plug any leaks */
5192 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5194 MonoException *ex = mono_error_convert_to_exception (&error);
5195 mono_array_setref (*exceptions, count, ex);
5204 ICALL_EXPORT MonoArray*
5205 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5207 MonoArray *res = NULL;
5208 MonoArray *exceptions = NULL;
5209 MonoImage *image = NULL;
5210 MonoTableInfo *table = NULL;
5213 int i, len, ex_count;
5215 MONO_ARCH_SAVE_REGS;
5217 domain = mono_object_domain (assembly);
5219 g_assert (!assembly_is_dynamic (assembly->assembly));
5220 image = assembly->assembly->image;
5221 table = &image->tables [MONO_TABLE_FILE];
5222 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5224 /* Append data from all modules in the assembly */
5225 for (i = 0; i < table->rows; ++i) {
5226 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5227 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5230 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5231 /* Append the new types to the end of the array */
5232 if (mono_array_length (res2) > 0) {
5234 MonoArray *res3, *ex3;
5236 len1 = mono_array_length (res);
5237 len2 = mono_array_length (res2);
5239 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5240 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5241 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5244 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5245 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5246 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5253 /* the ReflectionTypeLoadException must have all the types (Types property),
5254 * NULL replacing types which throws an exception. The LoaderException must
5255 * contain all exceptions for NULL items.
5258 len = mono_array_length (res);
5261 for (i = 0; i < len; i++) {
5262 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5266 klass = mono_type_get_class (t->type);
5267 if ((klass != NULL) && klass->exception_type) {
5268 /* keep the class in the list */
5269 list = g_list_append (list, klass);
5270 /* and replace Type with NULL */
5271 mono_array_setref (res, i, NULL);
5278 if (list || ex_count) {
5280 MonoException *exc = NULL;
5281 MonoArray *exl = NULL;
5282 int j, length = g_list_length (list) + ex_count;
5284 mono_loader_clear_error ();
5286 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5287 /* Types for which mono_class_get_checked () succeeded */
5288 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5289 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5290 mono_array_setref (exl, i, exc);
5292 /* Types for which it don't */
5293 for (j = 0; j < mono_array_length (exceptions); ++j) {
5294 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5296 g_assert (i < length);
5297 mono_array_setref (exl, i, exc);
5304 exc = mono_get_exception_reflection_type_load (res, exl);
5305 mono_loader_clear_error ();
5306 mono_raise_exception (exc);
5312 ICALL_EXPORT gboolean
5313 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5315 MonoAssemblyName aname;
5316 MonoDomain *domain = mono_object_domain (name);
5318 gboolean is_version_defined;
5319 gboolean is_token_defined;
5321 aname.public_key = NULL;
5322 val = mono_string_to_utf8 (assname);
5323 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5324 g_free ((guint8*) aname.public_key);
5329 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5330 FALSE, is_token_defined);
5332 mono_assembly_name_free (&aname);
5333 g_free ((guint8*) aname.public_key);
5339 ICALL_EXPORT MonoReflectionType*
5340 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5343 MonoDomain *domain = mono_object_domain (module);
5346 MONO_ARCH_SAVE_REGS;
5348 g_assert (module->image);
5350 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5351 /* These images do not have a global type */
5354 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5355 mono_error_raise_exception (&error);
5356 return mono_type_get_object (domain, &klass->byval_arg);
5360 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5362 /*if (module->image)
5363 mono_image_close (module->image);*/
5366 ICALL_EXPORT MonoString*
5367 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5369 MonoDomain *domain = mono_object_domain (module);
5371 MONO_ARCH_SAVE_REGS;
5373 g_assert (module->image);
5374 return mono_string_new (domain, module->image->guid);
5377 ICALL_EXPORT gpointer
5378 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5381 if (module->image && module->image->is_module_handle)
5382 return module->image->raw_data;
5385 return (gpointer) (-1);
5389 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5391 if (image_is_dynamic (image)) {
5392 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5393 *pe_kind = dyn->pe_kind;
5394 *machine = dyn->machine;
5397 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5398 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5403 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5405 return (image->md_version_major << 16) | (image->md_version_minor);
5408 ICALL_EXPORT MonoArray*
5409 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5411 MonoArray *exceptions;
5414 MONO_ARCH_SAVE_REGS;
5417 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5419 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5420 for (i = 0; i < mono_array_length (exceptions); ++i) {
5421 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5423 mono_raise_exception (ex);
5430 mono_memberref_is_method (MonoImage *image, guint32 token)
5432 if (!image_is_dynamic (image)) {
5433 guint32 cols [MONO_MEMBERREF_SIZE];
5435 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5436 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5437 mono_metadata_decode_blob_size (sig, &sig);
5438 return (*sig != 0x6);
5440 MonoClass *handle_class;
5442 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5445 return mono_defaults.methodhandle_class == handle_class;
5450 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5453 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5454 mono_array_addr (type_args, MonoType*, 0));
5456 context->class_inst = NULL;
5458 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5459 mono_array_addr (method_args, MonoType*, 0));
5461 context->method_inst = NULL;
5464 ICALL_EXPORT MonoType*
5465 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5468 int table = mono_metadata_token_table (token);
5469 int index = mono_metadata_token_index (token);
5470 MonoGenericContext context;
5473 *resolve_error = ResolveTokenError_Other;
5475 /* Validate token */
5476 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5477 (table != MONO_TABLE_TYPESPEC)) {
5478 *resolve_error = ResolveTokenError_BadTable;
5482 if (image_is_dynamic (image)) {
5483 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5484 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5485 return klass ? &klass->byval_arg : NULL;
5488 init_generic_context_from_args (&context, type_args, method_args);
5489 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5490 return klass ? &klass->byval_arg : NULL;
5493 if ((index <= 0) || (index > image->tables [table].rows)) {
5494 *resolve_error = ResolveTokenError_OutOfRange;
5498 init_generic_context_from_args (&context, type_args, method_args);
5499 klass = mono_class_get_checked (image, token, &error);
5501 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5502 mono_error_raise_exception (&error);
5505 return &klass->byval_arg;
5510 ICALL_EXPORT MonoMethod*
5511 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5513 int table = mono_metadata_token_table (token);
5514 int index = mono_metadata_token_index (token);
5515 MonoGenericContext context;
5518 *error = ResolveTokenError_Other;
5520 /* Validate token */
5521 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5522 (table != MONO_TABLE_MEMBERREF)) {
5523 *error = ResolveTokenError_BadTable;
5527 if (image_is_dynamic (image)) {
5528 if (table == MONO_TABLE_METHOD)
5529 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5531 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5532 *error = ResolveTokenError_BadTable;
5536 init_generic_context_from_args (&context, type_args, method_args);
5537 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5540 if ((index <= 0) || (index > image->tables [table].rows)) {
5541 *error = ResolveTokenError_OutOfRange;
5544 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5545 *error = ResolveTokenError_BadTable;
5549 init_generic_context_from_args (&context, type_args, method_args);
5550 method = mono_get_method_full (image, token, NULL, &context);
5552 if (mono_loader_get_last_error ())
5553 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5558 ICALL_EXPORT MonoString*
5559 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5561 int index = mono_metadata_token_index (token);
5563 *error = ResolveTokenError_Other;
5565 /* Validate token */
5566 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5567 *error = ResolveTokenError_BadTable;
5571 if (image_is_dynamic (image))
5572 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5574 if ((index <= 0) || (index >= image->heap_us.size)) {
5575 *error = ResolveTokenError_OutOfRange;
5579 /* FIXME: What to do if the index points into the middle of a string ? */
5581 return mono_ldstr (mono_domain_get (), image, index);
5584 ICALL_EXPORT MonoClassField*
5585 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5589 int table = mono_metadata_token_table (token);
5590 int index = mono_metadata_token_index (token);
5591 MonoGenericContext context;
5592 MonoClassField *field;
5594 *resolve_error = ResolveTokenError_Other;
5596 /* Validate token */
5597 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5598 *resolve_error = ResolveTokenError_BadTable;
5602 if (image_is_dynamic (image)) {
5603 if (table == MONO_TABLE_FIELD)
5604 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5606 if (mono_memberref_is_method (image, token)) {
5607 *resolve_error = ResolveTokenError_BadTable;
5611 init_generic_context_from_args (&context, type_args, method_args);
5612 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5615 if ((index <= 0) || (index > image->tables [table].rows)) {
5616 *resolve_error = ResolveTokenError_OutOfRange;
5619 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5620 *resolve_error = ResolveTokenError_BadTable;
5624 init_generic_context_from_args (&context, type_args, method_args);
5625 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5626 mono_error_raise_exception (&error);
5632 ICALL_EXPORT MonoObject*
5633 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5635 int table = mono_metadata_token_table (token);
5637 *error = ResolveTokenError_Other;
5640 case MONO_TABLE_TYPEDEF:
5641 case MONO_TABLE_TYPEREF:
5642 case MONO_TABLE_TYPESPEC: {
5643 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5645 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5649 case MONO_TABLE_METHOD:
5650 case MONO_TABLE_METHODSPEC: {
5651 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5653 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5657 case MONO_TABLE_FIELD: {
5658 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5660 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5664 case MONO_TABLE_MEMBERREF:
5665 if (mono_memberref_is_method (image, token)) {
5666 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5668 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5673 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5675 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5682 *error = ResolveTokenError_BadTable;
5688 ICALL_EXPORT MonoArray*
5689 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5691 int table = mono_metadata_token_table (token);
5692 int idx = mono_metadata_token_index (token);
5693 MonoTableInfo *tables = image->tables;
5698 *error = ResolveTokenError_OutOfRange;
5700 /* FIXME: Support other tables ? */
5701 if (table != MONO_TABLE_STANDALONESIG)
5704 if (image_is_dynamic (image))
5707 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5710 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5712 ptr = mono_metadata_blob_heap (image, sig);
5713 len = mono_metadata_decode_blob_size (ptr, &ptr);
5715 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5716 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5720 ICALL_EXPORT MonoReflectionType*
5721 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5724 int isbyref = 0, rank;
5725 char *str = mono_string_to_utf8 (smodifiers);
5728 MONO_ARCH_SAVE_REGS;
5730 klass = mono_class_from_mono_type (tb->type.type);
5732 /* logic taken from mono_reflection_parse_type(): keep in sync */
5736 if (isbyref) { /* only one level allowed by the spec */
5743 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5746 klass = mono_ptr_class_get (&klass->byval_arg);
5747 mono_class_init (klass);
5758 else if (*p != '*') { /* '*' means unknown lower bound */
5769 klass = mono_array_class_get (klass, rank);
5770 mono_class_init (klass);
5777 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5780 ICALL_EXPORT MonoBoolean
5781 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5786 MONO_ARCH_SAVE_REGS;
5789 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5795 check_for_invalid_type (MonoClass *klass)
5799 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5802 name = mono_type_get_full_name (klass);
5803 str = mono_string_new (mono_domain_get (), name);
5805 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5808 ICALL_EXPORT MonoReflectionType *
5809 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5811 MonoClass *klass, *aklass;
5813 MONO_ARCH_SAVE_REGS;
5815 klass = mono_class_from_mono_type (type->type);
5816 check_for_invalid_type (klass);
5818 if (rank == 0) //single dimentional array
5819 aklass = mono_array_class_get (klass, 1);
5821 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5823 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5826 ICALL_EXPORT MonoReflectionType *
5827 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5831 MONO_ARCH_SAVE_REGS;
5833 klass = mono_class_from_mono_type (type->type);
5834 mono_class_init_or_throw (klass);
5835 check_for_invalid_type (klass);
5837 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5840 ICALL_EXPORT MonoReflectionType *
5841 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5843 MonoClass *klass, *pklass;
5845 klass = mono_class_from_mono_type (type->type);
5846 mono_class_init_or_throw (klass);
5847 check_for_invalid_type (klass);
5849 pklass = mono_ptr_class_get (type->type);
5851 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5854 ICALL_EXPORT MonoObject *
5855 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5856 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5858 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5859 MonoObject *delegate;
5861 MonoMethod *method = info->method;
5863 MONO_ARCH_SAVE_REGS;
5865 mono_class_init_or_throw (delegate_class);
5867 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5869 if (mono_security_core_clr_enabled ()) {
5870 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5874 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5876 if (method_is_dynamic (method)) {
5877 /* Creating a trampoline would leak memory */
5878 func = mono_compile_method (method);
5880 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5881 method = mono_object_get_virtual_method (target, method);
5882 func = mono_create_ftnptr (mono_domain_get (),
5883 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5886 mono_delegate_ctor_with_method (delegate, target, func, method);
5892 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5894 /* Reset the invoke impl to the default one */
5895 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5899 * Magic number to convert a time which is relative to
5900 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5902 #define EPOCH_ADJUST ((guint64)62135596800LL)
5905 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5907 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5910 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5912 convert_to_absolute_date(SYSTEMTIME *date)
5914 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5915 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5916 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5917 /* from the calendar FAQ */
5918 int a = (14 - date->wMonth) / 12;
5919 int y = date->wYear - a;
5920 int m = date->wMonth + 12 * a - 2;
5921 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5923 /* d is now the day of the week for the first of the month (0 == Sunday) */
5925 int day_of_week = date->wDayOfWeek;
5927 /* set day_in_month to the first day in the month which falls on day_of_week */
5928 int day_in_month = 1 + (day_of_week - d);
5929 if (day_in_month <= 0)
5932 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5933 date->wDay = day_in_month + (date->wDay - 1) * 7;
5934 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5941 * Return's the offset from GMT of a local time.
5943 * tm is a local time
5944 * t is the same local time as seconds.
5947 gmt_offset(struct tm *tm, time_t t)
5949 #if defined (HAVE_TM_GMTOFF)
5950 return tm->tm_gmtoff;
5955 g.tm_isdst = tm->tm_isdst;
5957 return (int)difftime(t, t2);
5962 * This is heavily based on zdump.c from glibc 2.2.
5964 * * data[0]: start of daylight saving time (in DateTime ticks).
5965 * * data[1]: end of daylight saving time (in DateTime ticks).
5966 * * data[2]: utcoffset (in TimeSpan ticks).
5967 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5968 * * name[0]: name of this timezone when not daylight saving.
5969 * * name[1]: name of this timezone when daylight saving.
5971 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5972 * the class library allows years between 1 and 9999.
5974 * Returns true on success and zero on failure.
5976 ICALL_EXPORT guint32
5977 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5980 MonoDomain *domain = mono_domain_get ();
5981 struct tm start, tt;
5984 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5985 int day, transitioned;
5988 gmtoff_st = gmtoff_ds = transitioned = 0;
5990 MONO_ARCH_SAVE_REGS;
5992 MONO_CHECK_ARG_NULL (data);
5993 MONO_CHECK_ARG_NULL (names);
5995 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5996 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5999 * no info is better than crashing: we'll need our own tz data
6000 * to make this work properly, anyway. The range is probably
6001 * reduced to 1970 .. 2037 because that is what mktime is
6002 * guaranteed to support (we get into an infinite loop
6006 memset (&start, 0, sizeof (start));
6009 start.tm_year = year-1900;
6011 t = mktime (&start);
6013 if ((year < 1970) || (year > 2037) || (t == -1)) {
6015 tt = *localtime (&t);
6016 strftime (tzone, sizeof (tzone), "%Z", &tt);
6017 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6018 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6022 gmtoff = gmt_offset (&start, t);
6024 /* For each day of the year, calculate the tm_gmtoff. */
6025 for (day = 0; day < 365 && transitioned < 2; day++) {
6028 tt = *localtime (&t);
6030 gmtoff_after = gmt_offset(&tt, t);
6032 /* Daylight saving starts or ends here. */
6033 if (gmtoff_after != gmtoff) {
6037 /* Try to find the exact hour when daylight saving starts/ends. */
6041 tt1 = *localtime (&t1);
6042 } while (gmt_offset (&tt1, t1) != gmtoff);
6044 /* Try to find the exact minute when daylight saving starts/ends. */
6047 tt1 = *localtime (&t1);
6048 } while (gmt_offset (&tt1, t1) == gmtoff);
6050 strftime (tzone, sizeof (tzone), "%Z", &tt);
6052 /* Write data, if we're already in daylight saving, we're done. */
6054 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6055 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6056 if (gmtoff_ds == 0) {
6058 gmtoff_ds = gmtoff_after;
6065 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6066 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6067 if (gmtoff_ds == 0) {
6068 gmtoff_st = gmtoff_after;
6074 /* This is only set once when we enter daylight saving. */
6076 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6077 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6079 gmtoff = gmt_offset (&tt, t);
6083 if (transitioned < 2) {
6084 strftime (tzone, sizeof (tzone), "%Z", &tt);
6085 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6086 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6087 mono_array_set ((*data), gint64, 0, 0);
6088 mono_array_set ((*data), gint64, 1, 0);
6089 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6090 mono_array_set ((*data), gint64, 3, 0);
6095 MonoDomain *domain = mono_domain_get ();
6096 TIME_ZONE_INFORMATION tz_info;
6101 tz_id = GetTimeZoneInformation (&tz_info);
6102 if (tz_id == TIME_ZONE_ID_INVALID)
6105 MONO_CHECK_ARG_NULL (data);
6106 MONO_CHECK_ARG_NULL (names);
6108 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6109 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6111 for (i = 0; i < 32; ++i)
6112 if (!tz_info.DaylightName [i])
6114 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6115 for (i = 0; i < 32; ++i)
6116 if (!tz_info.StandardName [i])
6118 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6120 if ((year <= 1601) || (year > 30827)) {
6122 * According to MSDN, the MS time functions can't handle dates outside
6128 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6129 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6130 tz_info.StandardDate.wYear = year;
6131 convert_to_absolute_date(&tz_info.StandardDate);
6132 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6137 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6138 tz_info.DaylightDate.wYear = year;
6139 convert_to_absolute_date(&tz_info.DaylightDate);
6140 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6145 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6147 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6148 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6156 static inline gint32
6157 mono_array_get_byte_length (MonoArray *array)
6163 klass = array->obj.vtable->klass;
6165 if (array->bounds == NULL)
6166 length = array->max_length;
6169 for (i = 0; i < klass->rank; ++ i)
6170 length *= array->bounds [i].length;
6173 switch (klass->element_class->byval_arg.type) {
6176 case MONO_TYPE_BOOLEAN:
6180 case MONO_TYPE_CHAR:
6188 return length * sizeof (gpointer);
6199 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6201 MONO_ARCH_SAVE_REGS;
6203 return mono_array_get_byte_length (array);
6207 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6209 MONO_ARCH_SAVE_REGS;
6211 return mono_array_get (array, gint8, idx);
6215 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6217 MONO_ARCH_SAVE_REGS;
6219 mono_array_set (array, gint8, idx, value);
6222 ICALL_EXPORT MonoBoolean
6223 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6225 guint8 *src_buf, *dest_buf;
6227 MONO_ARCH_SAVE_REGS;
6229 /* This is called directly from the class libraries without going through the managed wrapper */
6230 MONO_CHECK_ARG_NULL (src);
6231 MONO_CHECK_ARG_NULL (dest);
6233 /* watch out for integer overflow */
6234 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6237 src_buf = (guint8 *)src->vector + src_offset;
6238 dest_buf = (guint8 *)dest->vector + dest_offset;
6241 memcpy (dest_buf, src_buf, count);
6243 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6248 #ifndef DISABLE_REMOTING
6249 ICALL_EXPORT MonoObject *
6250 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6252 MonoDomain *domain = mono_object_domain (this);
6254 MonoRealProxy *rp = ((MonoRealProxy *)this);
6255 MonoTransparentProxy *tp;
6259 MONO_ARCH_SAVE_REGS;
6261 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6262 tp = (MonoTransparentProxy*) res;
6264 MONO_OBJECT_SETREF (tp, rp, rp);
6265 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6266 klass = mono_class_from_mono_type (type);
6268 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6269 tp->remote_class = mono_remote_class (domain, class_name, klass);
6271 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6275 ICALL_EXPORT MonoReflectionType *
6276 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6278 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6282 /* System.Environment */
6285 ves_icall_System_Environment_get_UserName (void)
6287 MONO_ARCH_SAVE_REGS;
6289 /* using glib is more portable */
6290 return mono_string_new (mono_domain_get (), g_get_user_name ());
6294 ICALL_EXPORT MonoString *
6295 ves_icall_System_Environment_get_MachineName (void)
6297 #if defined (HOST_WIN32)
6302 len = MAX_COMPUTERNAME_LENGTH + 1;
6303 buf = g_new (gunichar2, len);
6306 if (GetComputerName (buf, (PDWORD) &len))
6307 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6311 #elif !defined(DISABLE_SOCKETS)
6315 if (gethostname (buf, sizeof (buf)) == 0)
6316 result = mono_string_new (mono_domain_get (), buf);
6322 return mono_string_new (mono_domain_get (), "mono");
6327 ves_icall_System_Environment_get_Platform (void)
6329 #if defined (TARGET_WIN32)
6332 #elif defined(__MACH__)
6335 // Notice that the value is hidden from user code, and only exposed
6336 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6337 // define and making assumptions based on Unix/128/4 values before there
6338 // was a MacOS define. Lots of code would assume that not-Unix meant
6339 // Windows, but in this case, it would be OSX.
6348 ICALL_EXPORT MonoString *
6349 ves_icall_System_Environment_get_NewLine (void)
6351 MONO_ARCH_SAVE_REGS;
6353 #if defined (HOST_WIN32)
6354 return mono_string_new (mono_domain_get (), "\r\n");
6356 return mono_string_new (mono_domain_get (), "\n");
6360 ICALL_EXPORT MonoString *
6361 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6366 MONO_ARCH_SAVE_REGS;
6371 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6372 value = g_getenv (utf8_name);
6379 return mono_string_new (mono_domain_get (), value);
6383 * There is no standard way to get at environ.
6386 #ifndef __MINGW32_VERSION
6387 #if defined(__APPLE__) && !defined (__arm__)
6388 /* Apple defines this in crt_externs.h but doesn't provide that header for
6389 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6390 * in fact exist on all implementations (so far)
6392 gchar ***_NSGetEnviron(void);
6393 #define environ (*_NSGetEnviron())
6401 ICALL_EXPORT MonoArray *
6402 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6413 env_strings = GetEnvironmentStrings();
6416 env_string = env_strings;
6417 while (*env_string != '\0') {
6418 /* weird case that MS seems to skip */
6419 if (*env_string != '=')
6421 while (*env_string != '\0')
6427 domain = mono_domain_get ();
6428 names = mono_array_new (domain, mono_defaults.string_class, n);
6432 env_string = env_strings;
6433 while (*env_string != '\0') {
6434 /* weird case that MS seems to skip */
6435 if (*env_string != '=') {
6436 equal_str = wcschr(env_string, '=');
6437 g_assert(equal_str);
6438 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6439 mono_array_setref (names, n, str);
6442 while (*env_string != '\0')
6447 FreeEnvironmentStrings (env_strings);
6459 MONO_ARCH_SAVE_REGS;
6462 for (e = environ; *e != 0; ++ e)
6465 domain = mono_domain_get ();
6466 names = mono_array_new (domain, mono_defaults.string_class, n);
6469 for (e = environ; *e != 0; ++ e) {
6470 parts = g_strsplit (*e, "=", 2);
6472 str = mono_string_new (domain, *parts);
6473 mono_array_setref (names, n, str);
6486 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6488 #if !GLIB_CHECK_VERSION(2,4,0)
6489 #define g_setenv(a,b,c) setenv(a,b,c)
6490 #define g_unsetenv(a) unsetenv(a)
6494 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6497 gunichar2 *utf16_name, *utf16_value;
6499 gchar *utf8_name, *utf8_value;
6503 MONO_ARCH_SAVE_REGS;
6506 utf16_name = mono_string_to_utf16 (name);
6507 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6508 SetEnvironmentVariable (utf16_name, NULL);
6509 g_free (utf16_name);
6513 utf16_value = mono_string_to_utf16 (value);
6515 SetEnvironmentVariable (utf16_name, utf16_value);
6517 g_free (utf16_name);
6518 g_free (utf16_value);
6520 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6522 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6523 g_unsetenv (utf8_name);
6528 utf8_value = mono_string_to_utf8_checked (value, &error);
6529 if (!mono_error_ok (&error)) {
6531 mono_error_raise_exception (&error);
6533 g_setenv (utf8_name, utf8_value, TRUE);
6536 g_free (utf8_value);
6541 ves_icall_System_Environment_Exit (int result)
6543 MONO_ARCH_SAVE_REGS;
6545 mono_environment_exitcode_set (result);
6547 /* FIXME: There are some cleanup hangs that should be worked out, but
6548 * if the program is going to exit, everything will be cleaned up when
6549 * NaCl exits anyway.
6551 #ifndef __native_client__
6552 if (!mono_runtime_try_shutdown ())
6553 mono_thread_exit ();
6555 /* Suspend all managed threads since the runtime is going away */
6556 mono_thread_suspend_all_other_threads ();
6558 mono_runtime_quit ();
6561 /* we may need to do some cleanup here... */
6565 ICALL_EXPORT MonoString*
6566 ves_icall_System_Environment_GetGacPath (void)
6568 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6571 ICALL_EXPORT MonoString*
6572 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6574 #if defined (HOST_WIN32)
6575 #ifndef CSIDL_FLAG_CREATE
6576 #define CSIDL_FLAG_CREATE 0x8000
6579 WCHAR path [MAX_PATH];
6580 /* Create directory if no existing */
6581 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6585 return mono_string_new_utf16 (mono_domain_get (), path, len);
6588 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6590 return mono_string_new (mono_domain_get (), "");
6593 ICALL_EXPORT MonoArray *
6594 ves_icall_System_Environment_GetLogicalDrives (void)
6596 gunichar2 buf [256], *ptr, *dname;
6598 guint initial_size = 127, size = 128;
6601 MonoString *drivestr;
6602 MonoDomain *domain = mono_domain_get ();
6605 MONO_ARCH_SAVE_REGS;
6610 while (size > initial_size) {
6611 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6612 if (size > initial_size) {
6615 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6616 initial_size = size;
6630 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6635 while (*u16) { u16++; len ++; }
6636 drivestr = mono_string_new_utf16 (domain, dname, len);
6637 mono_array_setref (result, ndrives++, drivestr);
6647 ICALL_EXPORT MonoString *
6648 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6650 gunichar2 volume_name [MAX_PATH + 1];
6652 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6654 return mono_string_from_utf16 (volume_name);
6657 ICALL_EXPORT MonoString *
6658 ves_icall_System_Environment_InternalGetHome (void)
6660 MONO_ARCH_SAVE_REGS;
6662 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6665 static const char *encodings [] = {
6667 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6668 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6669 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6671 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6672 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6673 "x_unicode_2_0_utf_7",
6675 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6676 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6678 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6681 "unicodefffe", "utf_16be",
6688 * Returns the internal codepage, if the value of "int_code_page" is
6689 * 1 at entry, and we can not compute a suitable code page number,
6690 * returns the code page as a string
6692 ICALL_EXPORT MonoString*
6693 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6698 char *codepage = NULL;
6700 int want_name = *int_code_page;
6703 *int_code_page = -1;
6704 MONO_ARCH_SAVE_REGS;
6706 g_get_charset (&cset);
6707 c = codepage = strdup (cset);
6708 for (c = codepage; *c; c++){
6709 if (isascii (*c) && isalpha (*c))
6714 /* g_print ("charset: %s\n", cset); */
6716 /* handle some common aliases */
6719 for (i = 0; p != 0; ){
6720 if ((gssize) p < 7){
6722 p = encodings [++i];
6725 if (strcmp (p, codepage) == 0){
6726 *int_code_page = code;
6729 p = encodings [++i];
6732 if (strstr (codepage, "utf_8") != NULL)
6733 *int_code_page |= 0x10000000;
6736 if (want_name && *int_code_page == -1)
6737 return mono_string_new (mono_domain_get (), cset);
6742 ICALL_EXPORT MonoBoolean
6743 ves_icall_System_Environment_get_HasShutdownStarted (void)
6745 if (mono_runtime_is_shutting_down ())
6748 if (mono_domain_is_unloading (mono_domain_get ()))
6755 ves_icall_System_Environment_BroadcastSettingChange (void)
6758 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6763 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6764 MonoReflectionMethod *method,
6765 MonoArray *out_args)
6767 MONO_ARCH_SAVE_REGS;
6769 mono_message_init (mono_object_domain (this), this, method, out_args);
6772 #ifndef DISABLE_REMOTING
6773 ICALL_EXPORT MonoBoolean
6774 ves_icall_IsTransparentProxy (MonoObject *proxy)
6776 MONO_ARCH_SAVE_REGS;
6781 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6787 ICALL_EXPORT MonoReflectionMethod *
6788 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6789 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6793 MonoMethod **vtable;
6794 MonoMethod *res = NULL;
6796 MONO_CHECK_ARG_NULL (rtype);
6797 MONO_CHECK_ARG_NULL (rmethod);
6799 method = rmethod->method;
6800 klass = mono_class_from_mono_type (rtype->type);
6801 mono_class_init_or_throw (klass);
6803 if (MONO_CLASS_IS_INTERFACE (klass))
6806 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6809 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6810 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6816 mono_class_setup_vtable (klass);
6817 vtable = klass->vtable;
6819 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6820 gboolean variance_used = FALSE;
6821 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6822 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6824 res = vtable [offs + method->slot];
6826 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6829 if (method->slot != -1)
6830 res = vtable [method->slot];
6836 return mono_method_get_object (mono_domain_get (), res, NULL);
6840 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6845 MONO_ARCH_SAVE_REGS;
6847 klass = mono_class_from_mono_type (type->type);
6848 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6850 mono_vtable_set_is_remote (vtable, enable);
6853 #else /* DISABLE_REMOTING */
6856 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6858 g_assert_not_reached ();
6863 ICALL_EXPORT MonoObject *
6864 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6869 MONO_ARCH_SAVE_REGS;
6871 domain = mono_object_domain (type);
6872 klass = mono_class_from_mono_type (type->type);
6873 mono_class_init_or_throw (klass);
6875 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6876 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6878 if (klass->rank >= 1) {
6879 g_assert (klass->rank == 1);
6880 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6882 /* Bypass remoting object creation check */
6883 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6887 ICALL_EXPORT MonoString *
6888 ves_icall_System_IO_get_temp_path (void)
6890 MONO_ARCH_SAVE_REGS;
6892 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6895 #ifndef PLATFORM_NO_DRIVEINFO
6896 ICALL_EXPORT MonoBoolean
6897 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6898 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6902 ULARGE_INTEGER wapi_free_bytes_avail;
6903 ULARGE_INTEGER wapi_total_number_of_bytes;
6904 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6906 MONO_ARCH_SAVE_REGS;
6908 *error = ERROR_SUCCESS;
6909 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6910 &wapi_total_number_of_free_bytes);
6913 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6914 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6915 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6917 *free_bytes_avail = 0;
6918 *total_number_of_bytes = 0;
6919 *total_number_of_free_bytes = 0;
6920 *error = GetLastError ();
6926 ICALL_EXPORT guint32
6927 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6929 MONO_ARCH_SAVE_REGS;
6931 return GetDriveType (mono_string_chars (root_path_name));
6935 ICALL_EXPORT gpointer
6936 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6938 MONO_ARCH_SAVE_REGS;
6940 return mono_compile_method (method);
6943 ICALL_EXPORT MonoString *
6944 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6949 MONO_ARCH_SAVE_REGS;
6951 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6953 #if defined (HOST_WIN32)
6954 /* Avoid mixing '/' and '\\' */
6957 for (i = strlen (path) - 1; i >= 0; i--)
6958 if (path [i] == '/')
6962 mcpath = mono_string_new (mono_domain_get (), path);
6969 get_bundled_app_config (void)
6971 const gchar *app_config;
6974 gchar *config_file_name, *config_file_path;
6978 MONO_ARCH_SAVE_REGS;
6980 domain = mono_domain_get ();
6981 file = domain->setup->configuration_file;
6985 // Retrieve config file and remove the extension
6986 config_file_name = mono_string_to_utf8 (file);
6987 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6988 if (!config_file_path)
6989 config_file_path = config_file_name;
6990 len = strlen (config_file_path) - strlen (".config");
6991 module = g_malloc0 (len + 1);
6992 memcpy (module, config_file_path, len);
6993 // Get the config file from the module name
6994 app_config = mono_config_string_for_assembly_file (module);
6997 if (config_file_name != config_file_path)
6998 g_free (config_file_name);
6999 g_free (config_file_path);
7004 return mono_string_new (mono_domain_get (), app_config);
7008 get_bundled_machine_config (void)
7010 const gchar *machine_config;
7012 MONO_ARCH_SAVE_REGS;
7014 machine_config = mono_get_machine_config ();
7016 if (!machine_config)
7019 return mono_string_new (mono_domain_get (), machine_config);
7022 ICALL_EXPORT MonoString *
7023 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7028 MONO_ARCH_SAVE_REGS;
7030 path = g_path_get_dirname (mono_get_config_dir ());
7032 #if defined (HOST_WIN32)
7033 /* Avoid mixing '/' and '\\' */
7036 for (i = strlen (path) - 1; i >= 0; i--)
7037 if (path [i] == '/')
7041 ipath = mono_string_new (mono_domain_get (), path);
7047 ICALL_EXPORT gboolean
7048 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7050 MonoPEResourceDataEntry *entry;
7053 MONO_ARCH_SAVE_REGS;
7055 if (!assembly || !result || !size)
7060 image = assembly->assembly->image;
7061 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7065 *result = mono_image_rva_map (image, entry->rde_data_offset);
7070 *size = entry->rde_size;
7075 ICALL_EXPORT MonoBoolean
7076 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7078 return mono_is_debugger_attached ();
7081 ICALL_EXPORT MonoBoolean
7082 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7084 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7085 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7091 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7093 if (mono_get_runtime_callbacks ()->debug_log)
7094 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7098 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7100 #if defined (HOST_WIN32)
7101 OutputDebugString (mono_string_chars (message));
7103 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7107 /* Only used for value types */
7108 ICALL_EXPORT MonoObject *
7109 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7114 MONO_ARCH_SAVE_REGS;
7116 domain = mono_object_domain (type);
7117 klass = mono_class_from_mono_type (type->type);
7118 mono_class_init_or_throw (klass);
7120 if (mono_class_is_nullable (klass))
7121 /* No arguments -> null */
7124 return mono_object_new (domain, klass);
7127 ICALL_EXPORT MonoReflectionMethod *
7128 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7130 MonoClass *klass, *parent;
7131 MonoMethod *method = m->method;
7132 MonoMethod *result = NULL;
7135 MONO_ARCH_SAVE_REGS;
7137 if (method->klass == NULL)
7140 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7141 MONO_CLASS_IS_INTERFACE (method->klass) ||
7142 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7145 slot = mono_method_get_vtable_slot (method);
7149 klass = method->klass;
7150 if (klass->generic_class)
7151 klass = klass->generic_class->container_class;
7154 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7155 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7156 mono_class_setup_vtable (parent);
7157 if (parent->vtable_size <= slot)
7162 klass = klass->parent;
7167 if (klass == method->klass)
7170 /*This is possible if definition == FALSE.
7171 * Do it here to be really sure we don't read invalid memory.
7173 if (slot >= klass->vtable_size)
7176 mono_class_setup_vtable (klass);
7178 result = klass->vtable [slot];
7179 if (result == NULL) {
7180 /* It is an abstract method */
7181 gpointer iter = NULL;
7182 while ((result = mono_class_get_methods (klass, &iter)))
7183 if (result->slot == slot)
7190 return mono_method_get_object (mono_domain_get (), result, NULL);
7193 ICALL_EXPORT MonoString*
7194 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7196 MonoMethod *method = m->method;
7198 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7203 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7205 MONO_ARCH_SAVE_REGS;
7207 iter->sig = *(MonoMethodSignature**)argsp;
7209 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7210 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7213 /* FIXME: it's not documented what start is exactly... */
7217 iter->args = argsp + sizeof (gpointer);
7219 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7221 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7224 ICALL_EXPORT MonoTypedRef
7225 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7227 guint32 i, arg_size;
7230 MONO_ARCH_SAVE_REGS;
7232 i = iter->sig->sentinelpos + iter->next_arg;
7234 g_assert (i < iter->sig->param_count);
7236 res.type = iter->sig->params [i];
7237 res.klass = mono_class_from_mono_type (res.type);
7238 arg_size = mono_type_stack_size (res.type, &align);
7239 #if defined(__arm__) || defined(__mips__)
7240 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7242 res.value = iter->args;
7243 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7244 /* Values are stored as 8 byte register sized objects, but 'value'
7245 * is dereferenced as a pointer in other routines.
7247 res.value = (char*)res.value + 4;
7249 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7250 if (arg_size <= sizeof (gpointer)) {
7252 int padding = arg_size - mono_type_size (res.type, &dummy);
7253 res.value = (guint8*)res.value + padding;
7256 iter->args = (char*)iter->args + arg_size;
7259 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7264 ICALL_EXPORT MonoTypedRef
7265 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7267 guint32 i, arg_size;
7270 MONO_ARCH_SAVE_REGS;
7272 i = iter->sig->sentinelpos + iter->next_arg;
7274 g_assert (i < iter->sig->param_count);
7276 while (i < iter->sig->param_count) {
7277 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7279 res.type = iter->sig->params [i];
7280 res.klass = mono_class_from_mono_type (res.type);
7281 /* FIXME: endianess issue... */
7282 arg_size = mono_type_stack_size (res.type, &align);
7283 #if defined(__arm__) || defined(__mips__)
7284 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7286 res.value = iter->args;
7287 iter->args = (char*)iter->args + arg_size;
7289 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7292 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7300 ICALL_EXPORT MonoType*
7301 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7304 MONO_ARCH_SAVE_REGS;
7306 i = iter->sig->sentinelpos + iter->next_arg;
7308 g_assert (i < iter->sig->param_count);
7310 return iter->sig->params [i];
7313 ICALL_EXPORT MonoObject*
7314 mono_TypedReference_ToObject (MonoTypedRef tref)
7316 MONO_ARCH_SAVE_REGS;
7318 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7319 MonoObject** objp = tref.value;
7323 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7326 ICALL_EXPORT MonoObject*
7327 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7329 MONO_ARCH_SAVE_REGS;
7331 if (MONO_TYPE_IS_REFERENCE (type)) {
7332 MonoObject** objp = value;
7336 return mono_value_box (mono_domain_get (), klass, value);
7340 prelink_method (MonoMethod *method)
7342 const char *exc_class, *exc_arg;
7343 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7345 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7347 mono_raise_exception(
7348 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7350 /* create the wrapper, too? */
7354 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7356 MONO_ARCH_SAVE_REGS;
7357 prelink_method (method->method);
7361 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7363 MonoClass *klass = mono_class_from_mono_type (type->type);
7365 gpointer iter = NULL;
7366 MONO_ARCH_SAVE_REGS;
7368 mono_class_init_or_throw (klass);
7370 while ((m = mono_class_get_methods (klass, &iter)))
7374 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7376 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7377 gint32 const **exponents,
7378 gunichar2 const **digitLowerTable,
7379 gunichar2 const **digitUpperTable,
7380 gint64 const **tenPowersList,
7381 gint32 const **decHexDigits)
7383 *mantissas = Formatter_MantissaBitsTable;
7384 *exponents = Formatter_TensExponentTable;
7385 *digitLowerTable = Formatter_DigitLowerTable;
7386 *digitUpperTable = Formatter_DigitUpperTable;
7387 *tenPowersList = Formatter_TenPowersList;
7388 *decHexDigits = Formatter_DecHexDigits;
7392 get_category_data (int version,
7393 guint8 const **category_data,
7394 guint16 const **category_astral_index)
7396 *category_astral_index = NULL;
7398 #ifndef DISABLE_NET_4_0
7400 *category_data = CategoryData_v4;
7401 #ifndef DISABLE_ASTRAL
7402 *category_astral_index = CategoryData_v4_astral_index;
7408 *category_data = CategoryData_v2;
7409 #ifndef DISABLE_ASTRAL
7410 *category_astral_index = CategoryData_v2_astral_index;
7414 /* These parameters are "readonly" in corlib/System/Char.cs */
7416 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7417 guint8 const **category_data,
7418 guint16 const **category_astral_index,
7419 guint8 const **numeric_data,
7420 gdouble const **numeric_data_values,
7421 guint16 const **to_lower_data_low,
7422 guint16 const **to_lower_data_high,
7423 guint16 const **to_upper_data_low,
7424 guint16 const **to_upper_data_high)
7426 get_category_data (category_data_version, category_data, category_astral_index);
7427 *numeric_data = NumericData;
7428 *numeric_data_values = NumericDataValues;
7429 *to_lower_data_low = ToLowerDataLow;
7430 *to_lower_data_high = ToLowerDataHigh;
7431 *to_upper_data_low = ToUpperDataLow;
7432 *to_upper_data_high = ToUpperDataHigh;
7436 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7437 * and avoid useless allocations.
7442 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7446 for (i = 0; i < type->num_mods; ++i) {
7447 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7452 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7454 for (i = 0; i < type->num_mods; ++i) {
7455 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7457 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7458 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7459 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7466 ICALL_EXPORT MonoArray*
7467 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7469 MonoType *type = param->ClassImpl->type;
7470 MonoClass *member_class = mono_object_class (param->MemberImpl);
7471 MonoMethod *method = NULL;
7474 MonoMethodSignature *sig;
7476 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7477 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7478 method = rmethod->method;
7479 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7480 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7481 if (!(method = prop->property->get))
7482 method = prop->property->set;
7485 char *type_name = mono_type_get_full_name (member_class);
7486 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7487 MonoException *ex = mono_get_exception_not_supported (msg);
7490 mono_raise_exception (ex);
7493 image = method->klass->image;
7494 pos = param->PositionImpl;
7495 sig = mono_method_signature (method);
7499 type = sig->params [pos];
7501 return type_array_from_modifiers (image, type, optional);
7505 get_property_type (MonoProperty *prop)
7507 MonoMethodSignature *sig;
7509 sig = mono_method_signature (prop->get);
7511 } else if (prop->set) {
7512 sig = mono_method_signature (prop->set);
7513 return sig->params [sig->param_count - 1];
7518 ICALL_EXPORT MonoArray*
7519 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7521 MonoType *type = get_property_type (property->property);
7522 MonoImage *image = property->klass->image;
7526 return type_array_from_modifiers (image, type, optional);
7530 *Construct a MonoType suited to be used to decode a constant blob object.
7532 * @type is the target type which will be constructed
7533 * @blob_type is the blob type, for example, that comes from the constant table
7534 * @real_type is the expected constructed type.
7537 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7539 type->type = blob_type;
7540 type->data.klass = NULL;
7541 if (blob_type == MONO_TYPE_CLASS)
7542 type->data.klass = mono_defaults.object_class;
7543 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7544 /* For enums, we need to use the base type */
7545 type->type = MONO_TYPE_VALUETYPE;
7546 type->data.klass = mono_class_from_mono_type (real_type);
7548 type->data.klass = mono_class_from_mono_type (real_type);
7551 ICALL_EXPORT MonoObject*
7552 property_info_get_default_value (MonoReflectionProperty *property)
7555 MonoProperty *prop = property->property;
7556 MonoType *type = get_property_type (prop);
7557 MonoDomain *domain = mono_object_domain (property);
7558 MonoTypeEnum def_type;
7559 const char *def_value;
7562 mono_class_init (prop->parent);
7564 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7565 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7567 def_value = mono_class_get_property_default_value (prop, &def_type);
7569 mono_type_from_blob_type (&blob_type, def_type, type);
7570 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7575 ICALL_EXPORT MonoBoolean
7576 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7578 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7579 MonoCustomAttrInfo *cinfo;
7582 mono_class_init_or_throw (attr_class);
7584 cinfo = mono_reflection_get_custom_attrs_info (obj);
7587 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7589 mono_custom_attrs_free (cinfo);
7593 ICALL_EXPORT MonoArray*
7594 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7596 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7601 mono_class_init_or_throw (attr_class);
7603 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7604 mono_error_raise_exception (&error);
7606 if (mono_loader_get_last_error ()) {
7607 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7608 g_assert_not_reached ();
7616 ICALL_EXPORT MonoString*
7617 ves_icall_Mono_Runtime_GetDisplayName (void)
7620 MonoString *display_name;
7622 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7623 display_name = mono_string_new (mono_domain_get (), info);
7625 return display_name;
7628 ICALL_EXPORT MonoString*
7629 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7631 MonoString *message;
7635 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7636 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7639 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7641 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7649 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7650 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7651 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7652 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7653 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7654 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7655 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7656 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7660 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7665 gunichar2 last, prev_last, prev2_last;
7672 int havePadding = 0;
7674 last = prev_last = 0, prev2_last = 0;
7675 for (i = 0; i < ilength; i++) {
7677 if (c >= sizeof (dbase64)) {
7678 exc = mono_exception_from_name_msg (mono_get_corlib (),
7679 "System", "FormatException",
7680 "Invalid character found.");
7681 mono_raise_exception (exc);
7682 } else if (isspace (c)) {
7684 } else if (havePadding && c != '=') {
7685 exc = mono_exception_from_name_msg (mono_get_corlib (),
7686 "System", "FormatException",
7687 "Invalid character found.");
7688 mono_raise_exception (exc);
7690 if (c == '=') havePadding = 1;
7691 prev2_last = prev_last;
7697 olength = ilength - ignored;
7699 if (allowWhitespaceOnly && olength == 0) {
7700 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7703 if ((olength & 3) != 0 || olength <= 0) {
7704 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7705 "FormatException", "Invalid length.");
7706 mono_raise_exception (exc);
7709 if (prev2_last == '=') {
7710 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7711 mono_raise_exception (exc);
7714 olength = (olength * 3) / 4;
7718 if (prev_last == '=')
7721 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7722 res_ptr = mono_array_addr (result, guchar, 0);
7723 for (i = 0; i < ilength; ) {
7726 for (k = 0; k < 4 && i < ilength;) {
7732 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7733 exc = mono_exception_from_name_msg (mono_get_corlib (),
7734 "System", "FormatException",
7735 "Invalid character found.");
7736 mono_raise_exception (exc);
7741 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7743 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7745 *res_ptr++ = (b [2] << 6) | b [3];
7747 while (i < ilength && isspace (start [i]))
7754 ICALL_EXPORT MonoArray *
7755 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7757 MONO_ARCH_SAVE_REGS;
7759 return base64_to_byte_array (mono_string_chars (str),
7760 mono_string_length (str), allowWhitespaceOnly);
7763 ICALL_EXPORT MonoArray *
7764 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7766 MONO_ARCH_SAVE_REGS;
7768 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7772 #ifndef DISABLE_ICALL_TABLES
7774 #define ICALL_TYPE(id,name,first)
7775 #define ICALL(id,name,func) Icall_ ## id,
7778 #include "metadata/icall-def.h"
7784 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7785 #define ICALL(id,name,func)
7787 #include "metadata/icall-def.h"
7793 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7794 #define ICALL(id,name,func)
7796 guint16 first_icall;
7799 static const IcallTypeDesc
7800 icall_type_descs [] = {
7801 #include "metadata/icall-def.h"
7805 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7808 #define ICALL_TYPE(id,name,first)
7811 #ifdef HAVE_ARRAY_ELEM_INIT
7812 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7813 #define MSGSTRFIELD1(line) str##line
7815 static const struct msgstrtn_t {
7816 #define ICALL(id,name,func)
7818 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7819 #include "metadata/icall-def.h"
7821 } icall_type_names_str = {
7822 #define ICALL_TYPE(id,name,first) (name),
7823 #include "metadata/icall-def.h"
7826 static const guint16 icall_type_names_idx [] = {
7827 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7828 #include "metadata/icall-def.h"
7831 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7833 static const struct msgstr_t {
7835 #define ICALL_TYPE(id,name,first)
7836 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7837 #include "metadata/icall-def.h"
7839 } icall_names_str = {
7840 #define ICALL(id,name,func) (name),
7841 #include "metadata/icall-def.h"
7844 static const guint16 icall_names_idx [] = {
7845 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7846 #include "metadata/icall-def.h"
7849 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7855 #define ICALL_TYPE(id,name,first) name,
7856 #define ICALL(id,name,func)
7857 static const char* const
7858 icall_type_names [] = {
7859 #include "metadata/icall-def.h"
7863 #define icall_type_name_get(id) (icall_type_names [(id)])
7867 #define ICALL_TYPE(id,name,first)
7868 #define ICALL(id,name,func) name,
7869 static const char* const
7871 #include "metadata/icall-def.h"
7874 #define icall_name_get(id) icall_names [(id)]
7876 #endif /* !HAVE_ARRAY_ELEM_INIT */
7880 #define ICALL_TYPE(id,name,first)
7881 #define ICALL(id,name,func) func,
7882 static const gconstpointer
7883 icall_functions [] = {
7884 #include "metadata/icall-def.h"
7888 #ifdef ENABLE_ICALL_SYMBOL_MAP
7891 #define ICALL_TYPE(id,name,first)
7892 #define ICALL(id,name,func) #func,
7893 static const gconstpointer
7894 icall_symbols [] = {
7895 #include "metadata/icall-def.h"
7900 #endif /* DISABLE_ICALL_TABLES */
7902 static mono_mutex_t icall_mutex;
7903 static GHashTable *icall_hash = NULL;
7904 static GHashTable *jit_icall_hash_name = NULL;
7905 static GHashTable *jit_icall_hash_addr = NULL;
7908 mono_icall_init (void)
7910 #ifndef DISABLE_ICALL_TABLES
7913 /* check that tables are sorted: disable in release */
7916 const char *prev_class = NULL;
7917 const char *prev_method;
7919 for (i = 0; i < Icall_type_num; ++i) {
7920 const IcallTypeDesc *desc;
7923 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7924 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7925 prev_class = icall_type_name_get (i);
7926 desc = &icall_type_descs [i];
7927 num_icalls = icall_desc_num_icalls (desc);
7928 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7929 for (j = 0; j < num_icalls; ++j) {
7930 const char *methodn = icall_name_get (desc->first_icall + j);
7931 if (prev_method && strcmp (prev_method, methodn) >= 0)
7932 g_print ("method %s should come before method %s\n", methodn, prev_method);
7933 prev_method = methodn;
7939 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7940 mono_mutex_init (&icall_mutex);
7944 mono_icall_lock (void)
7946 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7950 mono_icall_unlock (void)
7952 mono_locks_mutex_release (&icall_mutex, IcallLock);
7956 mono_icall_cleanup (void)
7958 g_hash_table_destroy (icall_hash);
7959 g_hash_table_destroy (jit_icall_hash_name);
7960 g_hash_table_destroy (jit_icall_hash_addr);
7961 mono_mutex_destroy (&icall_mutex);
7965 mono_add_internal_call (const char *name, gconstpointer method)
7969 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7971 mono_icall_unlock ();
7974 #ifndef DISABLE_ICALL_TABLES
7976 #ifdef HAVE_ARRAY_ELEM_INIT
7978 compare_method_imap (const void *key, const void *elem)
7980 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7981 return strcmp (key, method_name);
7985 find_method_icall (const IcallTypeDesc *imap, const char *name)
7987 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);
7990 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7994 compare_class_imap (const void *key, const void *elem)
7996 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7997 return strcmp (key, class_name);
8000 static const IcallTypeDesc*
8001 find_class_icalls (const char *name)
8003 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8006 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8009 #else /* HAVE_ARRAY_ELEM_INIT */
8012 compare_method_imap (const void *key, const void *elem)
8014 const char** method_name = (const char**)elem;
8015 return strcmp (key, *method_name);
8019 find_method_icall (const IcallTypeDesc *imap, const char *name)
8021 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8024 return (gpointer)icall_functions [(nameslot - icall_names)];
8028 compare_class_imap (const void *key, const void *elem)
8030 const char** class_name = (const char**)elem;
8031 return strcmp (key, *class_name);
8034 static const IcallTypeDesc*
8035 find_class_icalls (const char *name)
8037 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8040 return &icall_type_descs [nameslot - icall_type_names];
8043 #endif /* HAVE_ARRAY_ELEM_INIT */
8045 #endif /* DISABLE_ICALL_TABLES */
8048 * we should probably export this as an helper (handle nested types).
8049 * Returns the number of chars written in buf.
8052 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8054 int nspacelen, cnamelen;
8055 nspacelen = strlen (klass->name_space);
8056 cnamelen = strlen (klass->name);
8057 if (nspacelen + cnamelen + 2 > bufsize)
8060 memcpy (buf, klass->name_space, nspacelen);
8061 buf [nspacelen ++] = '.';
8063 memcpy (buf + nspacelen, klass->name, cnamelen);
8064 buf [nspacelen + cnamelen] = 0;
8065 return nspacelen + cnamelen;
8068 #ifdef DISABLE_ICALL_TABLES
8070 no_icall_table (void)
8072 g_assert_not_reached ();
8077 mono_lookup_internal_call (MonoMethod *method)
8082 int typelen = 0, mlen, siglen;
8084 #ifndef DISABLE_ICALL_TABLES
8085 const IcallTypeDesc *imap = NULL;
8088 g_assert (method != NULL);
8090 if (method->is_inflated)
8091 method = ((MonoMethodInflated *) method)->declaring;
8093 if (method->klass->nested_in) {
8094 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8098 mname [pos++] = '/';
8101 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8107 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8112 #ifndef DISABLE_ICALL_TABLES
8113 imap = find_class_icalls (mname);
8116 mname [typelen] = ':';
8117 mname [typelen + 1] = ':';
8119 mlen = strlen (method->name);
8120 memcpy (mname + typelen + 2, method->name, mlen);
8121 sigstart = mname + typelen + 2 + mlen;
8124 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8125 siglen = strlen (tmpsig);
8126 if (typelen + mlen + siglen + 6 > sizeof (mname))
8129 memcpy (sigstart + 1, tmpsig, siglen);
8130 sigstart [siglen + 1] = ')';
8131 sigstart [siglen + 2] = 0;
8136 res = g_hash_table_lookup (icall_hash, mname);
8138 mono_icall_unlock ();;
8141 /* try without signature */
8143 res = g_hash_table_lookup (icall_hash, mname);
8145 mono_icall_unlock ();
8149 #ifdef DISABLE_ICALL_TABLES
8150 mono_icall_unlock ();
8151 /* Fail only when the result is actually used */
8152 /* mono_marshal_get_native_wrapper () depends on this */
8153 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8154 return ves_icall_System_String_ctor_RedirectToCreateString;
8156 return no_icall_table;
8158 /* it wasn't found in the static call tables */
8160 mono_icall_unlock ();
8163 res = find_method_icall (imap, sigstart - mlen);
8165 mono_icall_unlock ();
8168 /* try _with_ signature */
8170 res = find_method_icall (imap, sigstart - mlen);
8172 mono_icall_unlock ();
8176 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8177 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8178 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8179 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8180 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");
8181 g_print ("If you see other errors or faults after this message they are probably related\n");
8182 g_print ("and you need to fix your mono install first.\n");
8184 mono_icall_unlock ();
8190 #ifdef ENABLE_ICALL_SYMBOL_MAP
8192 func_cmp (gconstpointer key, gconstpointer p)
8194 return (gsize)key - (gsize)*(gsize*)p;
8199 * mono_lookup_icall_symbol:
8201 * Given the icall METHOD, returns its C symbol.
8204 mono_lookup_icall_symbol (MonoMethod *m)
8206 #ifdef DISABLE_ICALL_TABLES
8207 g_assert_not_reached ();
8210 #ifdef ENABLE_ICALL_SYMBOL_MAP
8214 static gconstpointer *functions_sorted;
8215 static const char**symbols_sorted;
8216 static gboolean inited;
8221 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8222 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8223 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8224 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8225 /* Bubble sort the two arrays */
8229 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8230 if (functions_sorted [i] > functions_sorted [i + 1]) {
8233 tmp = functions_sorted [i];
8234 functions_sorted [i] = functions_sorted [i + 1];
8235 functions_sorted [i + 1] = tmp;
8236 tmp = symbols_sorted [i];
8237 symbols_sorted [i] = symbols_sorted [i + 1];
8238 symbols_sorted [i + 1] = tmp;
8245 func = mono_lookup_internal_call (m);
8248 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8252 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8254 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8255 g_assert_not_reached ();
8262 type_from_typename (char *typename)
8264 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8266 if (!strcmp (typename, "int"))
8267 klass = mono_defaults.int_class;
8268 else if (!strcmp (typename, "ptr"))
8269 klass = mono_defaults.int_class;
8270 else if (!strcmp (typename, "void"))
8271 klass = mono_defaults.void_class;
8272 else if (!strcmp (typename, "int32"))
8273 klass = mono_defaults.int32_class;
8274 else if (!strcmp (typename, "uint32"))
8275 klass = mono_defaults.uint32_class;
8276 else if (!strcmp (typename, "int8"))
8277 klass = mono_defaults.sbyte_class;
8278 else if (!strcmp (typename, "uint8"))
8279 klass = mono_defaults.byte_class;
8280 else if (!strcmp (typename, "int16"))
8281 klass = mono_defaults.int16_class;
8282 else if (!strcmp (typename, "uint16"))
8283 klass = mono_defaults.uint16_class;
8284 else if (!strcmp (typename, "long"))
8285 klass = mono_defaults.int64_class;
8286 else if (!strcmp (typename, "ulong"))
8287 klass = mono_defaults.uint64_class;
8288 else if (!strcmp (typename, "float"))
8289 klass = mono_defaults.single_class;
8290 else if (!strcmp (typename, "double"))
8291 klass = mono_defaults.double_class;
8292 else if (!strcmp (typename, "object"))
8293 klass = mono_defaults.object_class;
8294 else if (!strcmp (typename, "obj"))
8295 klass = mono_defaults.object_class;
8296 else if (!strcmp (typename, "string"))
8297 klass = mono_defaults.string_class;
8298 else if (!strcmp (typename, "bool"))
8299 klass = mono_defaults.boolean_class;
8300 else if (!strcmp (typename, "boolean"))
8301 klass = mono_defaults.boolean_class;
8303 g_error ("%s", typename);
8304 g_assert_not_reached ();
8306 return &klass->byval_arg;
8310 * LOCKING: Take the corlib image lock.
8312 MonoMethodSignature*
8313 mono_create_icall_signature (const char *sigstr)
8318 MonoMethodSignature *res, *res2;
8319 MonoImage *corlib = mono_defaults.corlib;
8321 mono_image_lock (corlib);
8322 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8323 mono_image_unlock (corlib);
8328 parts = g_strsplit (sigstr, " ", 256);
8337 res = mono_metadata_signature_alloc (corlib, len - 1);
8342 * Under windows, the default pinvoke calling convention is STDCALL but
8345 res->call_convention = MONO_CALL_C;
8348 res->ret = type_from_typename (parts [0]);
8349 for (i = 1; i < len; ++i) {
8350 res->params [i - 1] = type_from_typename (parts [i]);
8355 mono_image_lock (corlib);
8356 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8358 res = res2; /*Value is allocated in the image pool*/
8360 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8361 mono_image_unlock (corlib);
8367 mono_find_jit_icall_by_name (const char *name)
8369 MonoJitICallInfo *info;
8370 g_assert (jit_icall_hash_name);
8373 info = g_hash_table_lookup (jit_icall_hash_name, name);
8374 mono_icall_unlock ();
8379 mono_find_jit_icall_by_addr (gconstpointer addr)
8381 MonoJitICallInfo *info;
8382 g_assert (jit_icall_hash_addr);
8385 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8386 mono_icall_unlock ();
8392 * mono_get_jit_icall_info:
8394 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8395 * caller should access it while holding the icall lock.
8398 mono_get_jit_icall_info (void)
8400 return jit_icall_hash_name;
8404 * mono_lookup_jit_icall_symbol:
8406 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8409 mono_lookup_jit_icall_symbol (const char *name)
8411 MonoJitICallInfo *info;
8412 const char *res = NULL;
8415 info = g_hash_table_lookup (jit_icall_hash_name, name);
8417 res = info->c_symbol;
8418 mono_icall_unlock ();
8423 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8426 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8427 mono_icall_unlock ();
8431 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8433 MonoJitICallInfo *info;
8440 if (!jit_icall_hash_name) {
8441 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8442 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8445 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8446 g_warning ("jit icall already defined \"%s\"\n", name);
8447 g_assert_not_reached ();
8450 info = g_new0 (MonoJitICallInfo, 1);
8455 info->c_symbol = c_symbol;
8458 info->wrapper = func;
8460 info->wrapper = NULL;
8463 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8464 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8466 mono_icall_unlock ();
8471 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8473 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);