5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2011-2014 Xamarin Inc (http://www.xamarin.com).
23 #ifdef HAVE_SYS_TIME_H
29 #if defined (HOST_WIN32)
32 #if defined (HAVE_WCHAR_H)
36 #include "mono/utils/mono-membar.h"
37 #include <mono/metadata/object.h>
38 #include <mono/metadata/threads.h>
39 #include <mono/metadata/threads-types.h>
40 #include <mono/metadata/threadpool.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/assembly.h>
44 #include <mono/metadata/tabledefs.h>
45 #include <mono/metadata/exception.h>
46 #include <mono/metadata/file-io.h>
47 #include <mono/metadata/console-io.h>
48 #include <mono/metadata/socket-io.h>
49 #include <mono/metadata/mono-endian.h>
50 #include <mono/metadata/tokentype.h>
51 #include <mono/metadata/domain-internals.h>
52 #include <mono/metadata/metadata-internals.h>
53 #include <mono/metadata/class-internals.h>
54 #include <mono/metadata/marshal.h>
55 #include <mono/metadata/gc-internal.h>
56 #include <mono/metadata/mono-gc.h>
57 #include <mono/metadata/rand.h>
58 #include <mono/metadata/sysmath.h>
59 #include <mono/metadata/string-icalls.h>
60 #include <mono/metadata/debug-helpers.h>
61 #include <mono/metadata/process.h>
62 #include <mono/metadata/environment.h>
63 #include <mono/metadata/profiler-private.h>
64 #include <mono/metadata/locales.h>
65 #include <mono/metadata/filewatcher.h>
66 #include <mono/metadata/char-conversions.h>
67 #include <mono/metadata/security.h>
68 #include <mono/metadata/mono-config.h>
69 #include <mono/metadata/cil-coff.h>
70 #include <mono/metadata/number-formatter.h>
71 #include <mono/metadata/security-manager.h>
72 #include <mono/metadata/security-core-clr.h>
73 #include <mono/metadata/mono-perfcounters.h>
74 #include <mono/metadata/mono-debug.h>
75 #include <mono/metadata/mono-ptr-array.h>
76 #include <mono/metadata/verify-internals.h>
77 #include <mono/metadata/runtime.h>
78 #include <mono/metadata/file-mmap.h>
79 #include <mono/io-layer/io-layer.h>
80 #include <mono/utils/strtod.h>
81 #include <mono/utils/monobitset.h>
82 #include <mono/utils/mono-time.h>
83 #include <mono/utils/mono-proclib.h>
84 #include <mono/utils/mono-string.h>
85 #include <mono/utils/mono-error-internals.h>
86 #include <mono/utils/mono-mmap.h>
87 #include <mono/utils/mono-io-portability.h>
88 #include <mono/utils/mono-digest.h>
89 #include <mono/utils/bsearch.h>
90 #include <mono/utils/mono-mutex.h>
91 #include <mono/utils/mono-threads.h>
93 #if defined (HOST_WIN32)
99 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
101 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
104 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
106 static inline MonoBoolean
107 is_generic_parameter (MonoType *type)
109 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
113 mono_class_init_or_throw (MonoClass *klass)
115 if (!mono_class_init (klass))
116 mono_raise_exception (mono_class_get_exception_for_failure (klass));
120 * We expect a pointer to a char, not a string
122 ICALL_EXPORT gboolean
123 mono_double_ParseImpl (char *ptr, double *result)
125 gchar *endptr = NULL;
131 /* mono_strtod () is not thread-safe */
132 mono_mutex_lock (&mono_strtod_mutex);
133 *result = mono_strtod (ptr, &endptr);
134 mono_mutex_unlock (&mono_strtod_mutex);
137 if (!*ptr || (endptr && *endptr))
143 ICALL_EXPORT MonoObject *
144 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
153 ao = (MonoArray *)this;
154 ac = (MonoClass *)ao->obj.vtable->klass;
156 esize = mono_array_element_size (ac);
157 ea = (gpointer*)((char*)ao->vector + (pos * esize));
159 if (ac->element_class->valuetype)
160 return mono_value_box (this->vtable->domain, ac->element_class, ea);
165 ICALL_EXPORT MonoObject *
166 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
174 MONO_CHECK_ARG_NULL (idxs);
176 io = (MonoArray *)idxs;
177 ic = (MonoClass *)io->obj.vtable->klass;
179 ao = (MonoArray *)this;
180 ac = (MonoClass *)ao->obj.vtable->klass;
182 g_assert (ic->rank == 1);
183 if (io->bounds != NULL || io->max_length != ac->rank)
184 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
186 ind = (gint32 *)io->vector;
188 if (ao->bounds == NULL) {
189 if (*ind < 0 || *ind >= ao->max_length)
190 mono_raise_exception (mono_get_exception_index_out_of_range ());
192 return ves_icall_System_Array_GetValueImpl (this, *ind);
195 for (i = 0; i < ac->rank; i++)
196 if ((ind [i] < ao->bounds [i].lower_bound) ||
197 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
198 mono_raise_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - ao->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos*ao->bounds [i].length + ind [i] -
203 ao->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (this, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
211 MonoClass *ac, *vc, *ec;
223 vc = value->vtable->klass;
227 ac = this->obj.vtable->klass;
228 ec = ac->element_class;
230 esize = mono_array_element_size (ac);
231 ea = (gpointer*)((char*)this->vector + (pos * esize));
232 va = (gpointer*)((char*)value + sizeof (MonoObject));
234 if (mono_class_is_nullable (ec)) {
235 mono_nullable_init ((guint8*)ea, value, ec);
240 mono_gc_bzero_atomic (ea, esize);
244 #define NO_WIDENING_CONVERSION G_STMT_START{\
245 mono_raise_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
249 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
250 if (esize < vsize + (extra)) \
251 mono_raise_exception (mono_get_exception_argument ( \
252 "value", "not a widening conversion")); \
255 #define INVALID_CAST G_STMT_START{ \
256 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
257 mono_raise_exception (mono_get_exception_invalid_cast ()); \
260 /* Check element (destination) type. */
261 switch (ec->byval_arg.type) {
262 case MONO_TYPE_STRING:
263 switch (vc->byval_arg.type) {
264 case MONO_TYPE_STRING:
270 case MONO_TYPE_BOOLEAN:
271 switch (vc->byval_arg.type) {
272 case MONO_TYPE_BOOLEAN:
285 NO_WIDENING_CONVERSION;
292 if (!ec->valuetype) {
293 if (!mono_object_isinst (value, ec))
295 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
299 if (mono_object_isinst (value, ec)) {
300 if (ec->has_references)
301 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
303 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
310 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
312 et = ec->byval_arg.type;
313 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
314 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
316 vt = vc->byval_arg.type;
317 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
318 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
320 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
326 case MONO_TYPE_CHAR: \
327 CHECK_WIDENING_CONVERSION(0); \
328 *(etype *) ea = (etype) u64; \
330 /* You can't assign a signed value to an unsigned array. */ \
335 /* You can't assign a floating point number to an integer array. */ \
338 NO_WIDENING_CONVERSION; \
342 #define ASSIGN_SIGNED(etype) G_STMT_START{\
348 CHECK_WIDENING_CONVERSION(0); \
349 *(etype *) ea = (etype) i64; \
351 /* You can assign an unsigned value to a signed array if the array's */ \
352 /* element size is larger than the value size. */ \
357 case MONO_TYPE_CHAR: \
358 CHECK_WIDENING_CONVERSION(1); \
359 *(etype *) ea = (etype) u64; \
361 /* You can't assign a floating point number to an integer array. */ \
364 NO_WIDENING_CONVERSION; \
368 #define ASSIGN_REAL(etype) G_STMT_START{\
372 CHECK_WIDENING_CONVERSION(0); \
373 *(etype *) ea = (etype) r64; \
375 /* All integer values fit into a floating point array, so we don't */ \
376 /* need to CHECK_WIDENING_CONVERSION here. */ \
381 *(etype *) ea = (etype) i64; \
387 case MONO_TYPE_CHAR: \
388 *(etype *) ea = (etype) u64; \
395 u64 = *(guint8 *) va;
398 u64 = *(guint16 *) va;
401 u64 = *(guint32 *) va;
404 u64 = *(guint64 *) va;
410 i64 = *(gint16 *) va;
413 i64 = *(gint32 *) va;
416 i64 = *(gint64 *) va;
419 r64 = *(gfloat *) va;
422 r64 = *(gdouble *) va;
425 u64 = *(guint16 *) va;
427 case MONO_TYPE_BOOLEAN:
428 /* Boolean is only compatible with itself. */
441 NO_WIDENING_CONVERSION;
448 /* If we can't do a direct copy, let's try a widening conversion. */
451 ASSIGN_UNSIGNED (guint16);
453 ASSIGN_UNSIGNED (guint8);
455 ASSIGN_UNSIGNED (guint16);
457 ASSIGN_UNSIGNED (guint32);
459 ASSIGN_UNSIGNED (guint64);
461 ASSIGN_SIGNED (gint8);
463 ASSIGN_SIGNED (gint16);
465 ASSIGN_SIGNED (gint32);
467 ASSIGN_SIGNED (gint64);
469 ASSIGN_REAL (gfloat);
471 ASSIGN_REAL (gdouble);
475 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
479 #undef NO_WIDENING_CONVERSION
480 #undef CHECK_WIDENING_CONVERSION
481 #undef ASSIGN_UNSIGNED
487 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
495 MONO_CHECK_ARG_NULL (idxs);
497 ic = idxs->obj.vtable->klass;
498 ac = this->obj.vtable->klass;
500 g_assert (ic->rank == 1);
501 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
502 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
504 ind = (gint32 *)idxs->vector;
506 if (this->bounds == NULL) {
507 if (*ind < 0 || *ind >= this->max_length)
508 mono_raise_exception (mono_get_exception_index_out_of_range ());
510 ves_icall_System_Array_SetValueImpl (this, value, *ind);
514 for (i = 0; i < ac->rank; i++)
515 if ((ind [i] < this->bounds [i].lower_bound) ||
516 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
517 mono_raise_exception (mono_get_exception_index_out_of_range ());
519 pos = ind [0] - this->bounds [0].lower_bound;
520 for (i = 1; i < ac->rank; i++)
521 pos = pos * this->bounds [i].length + ind [i] -
522 this->bounds [i].lower_bound;
524 ves_icall_System_Array_SetValueImpl (this, value, pos);
527 ICALL_EXPORT MonoArray *
528 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
530 MonoClass *aklass, *klass;
533 gboolean bounded = FALSE;
537 MONO_CHECK_ARG_NULL (type);
538 MONO_CHECK_ARG_NULL (lengths);
540 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
542 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
544 for (i = 0; i < mono_array_length (lengths); i++)
545 if (mono_array_get (lengths, gint32, i) < 0)
546 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
548 klass = mono_class_from_mono_type (type->type);
549 mono_class_init_or_throw (klass);
551 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
552 /* vectors are not the same as one dimensional arrays with no-zero bounds */
557 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
559 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
560 for (i = 0; i < aklass->rank; ++i) {
561 sizes [i] = mono_array_get (lengths, guint32, i);
563 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
565 sizes [i + aklass->rank] = 0;
568 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
573 ICALL_EXPORT MonoArray *
574 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
576 MonoClass *aklass, *klass;
579 gboolean bounded = FALSE;
583 MONO_CHECK_ARG_NULL (type);
584 MONO_CHECK_ARG_NULL (lengths);
586 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
588 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
590 for (i = 0; i < mono_array_length (lengths); i++)
591 if ((mono_array_get (lengths, gint64, i) < 0) ||
592 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
593 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
595 klass = mono_class_from_mono_type (type->type);
596 mono_class_init_or_throw (klass);
598 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
599 /* vectors are not the same as one dimensional arrays with no-zero bounds */
604 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
606 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
607 for (i = 0; i < aklass->rank; ++i) {
608 sizes [i] = mono_array_get (lengths, guint64, i);
610 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
612 sizes [i + aklass->rank] = 0;
615 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
621 ves_icall_System_Array_GetRank (MonoObject *this)
625 return this->vtable->klass->rank;
629 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
631 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
636 if ((dimension < 0) || (dimension >= rank))
637 mono_raise_exception (mono_get_exception_index_out_of_range ());
639 if (this->bounds == NULL)
640 length = this->max_length;
642 length = this->bounds [dimension].length;
644 #ifdef MONO_BIG_ARRAYS
645 if (length > G_MAXINT32)
646 mono_raise_exception (mono_get_exception_overflow ());
652 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
654 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank))
659 mono_raise_exception (mono_get_exception_index_out_of_range ());
661 if (this->bounds == NULL)
662 return this->max_length;
664 return this->bounds [dimension].length;
668 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
670 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
674 if ((dimension < 0) || (dimension >= rank))
675 mono_raise_exception (mono_get_exception_index_out_of_range ());
677 if (this->bounds == NULL)
680 return this->bounds [dimension].lower_bound;
684 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
686 int sz = mono_array_element_size (mono_object_class (arr));
687 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
690 ICALL_EXPORT gboolean
691 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
696 MonoVTable *src_vtable;
697 MonoVTable *dest_vtable;
698 MonoClass *src_class;
699 MonoClass *dest_class;
701 src_vtable = source->obj.vtable;
702 dest_vtable = dest->obj.vtable;
704 if (src_vtable->rank != dest_vtable->rank)
707 if (source->bounds || dest->bounds)
710 /* there's no integer overflow since mono_array_length returns an unsigned integer */
711 if ((dest_idx + length > mono_array_length_fast (dest)) ||
712 (source_idx + length > mono_array_length_fast (source)))
715 src_class = src_vtable->klass->element_class;
716 dest_class = dest_vtable->klass->element_class;
719 * Handle common cases.
722 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
723 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
725 if (src_class == mono_defaults.object_class && dest_class->valuetype)
728 /* Check if we're copying a char[] <==> (u)short[] */
729 if (src_class != dest_class) {
730 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
733 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
734 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
738 if (dest_class->valuetype) {
739 element_size = mono_array_element_size (source->obj.vtable->klass);
740 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
741 if (dest_class->has_references) {
742 mono_value_copy_array (dest, dest_idx, source_addr, length);
744 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
745 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
748 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
755 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
764 ao = (MonoArray *)this;
765 ac = (MonoClass *)ao->obj.vtable->klass;
767 esize = mono_array_element_size (ac);
768 ea = (gpointer*)((char*)ao->vector + (pos * esize));
770 mono_gc_memmove_atomic (value, ea, esize);
774 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
783 ao = (MonoArray *)this;
784 ac = (MonoClass *)ao->obj.vtable->klass;
785 ec = ac->element_class;
787 esize = mono_array_element_size (ac);
788 ea = (gpointer*)((char*)ao->vector + (pos * esize));
790 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
791 g_assert (esize == sizeof (gpointer));
792 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
794 g_assert (ec->inited);
795 g_assert (esize == mono_class_value_size (ec, NULL));
796 if (ec->has_references)
797 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
799 mono_gc_memmove_atomic (ea, value, esize);
804 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
806 MonoClass *klass = array->obj.vtable->klass;
807 guint32 size = mono_array_element_size (klass);
808 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
810 const char *field_data;
812 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
813 MonoException *exc = mono_get_exception_argument("array",
814 "Cannot initialize array of non-primitive type.");
815 mono_raise_exception (exc);
818 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
819 MonoException *exc = mono_get_exception_argument("field_handle",
820 "Field doesn't have an RVA");
821 mono_raise_exception (exc);
824 size *= array->max_length;
825 field_data = mono_field_get_data (field_handle);
827 if (size > mono_type_size (field_handle->type, &align)) {
828 MonoException *exc = mono_get_exception_argument("field_handle",
829 "Field not large enough to fill array");
830 mono_raise_exception (exc);
833 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
835 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
836 guint ## n *src = (guint ## n *) field_data; \
837 guint ## n *end = (guint ## n *)((char*)src + size); \
839 for (; src < end; data++, src++) { \
840 *data = read ## n (src); \
844 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
846 switch (type->type) {
863 memcpy (mono_array_addr (array, char, 0), field_data, size);
867 memcpy (mono_array_addr (array, char, 0), field_data, size);
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
876 return offsetof (MonoString, chars);
879 ICALL_EXPORT MonoObject *
880 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
884 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
887 return mono_object_clone (obj);
891 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
896 MONO_CHECK_ARG_NULL (handle);
898 klass = mono_class_from_mono_type (handle);
899 MONO_CHECK_ARG (handle, klass);
901 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
903 /* This will call the type constructor */
904 mono_runtime_class_init (vtable);
908 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
912 mono_image_check_for_module_cctor (image);
913 if (image->has_module_cctor) {
914 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
915 mono_error_raise_exception (&error);
916 /*It's fine to raise the exception here*/
917 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
921 ICALL_EXPORT MonoBoolean
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
927 /* later make this configurable and per-arch */
928 int min_size = 4096 * 4 * sizeof (void*);
929 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
930 /* if we have no info we are optimistic and assume there is enough room */
934 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
938 current = (guint8 *)&stack_addr;
939 if (current > stack_addr) {
940 if ((current - stack_addr) < min_size)
943 if (current - (stack_addr - stack_size) < min_size)
949 ICALL_EXPORT MonoObject *
950 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
954 return mono_object_clone (this);
958 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
961 MonoObject **values = NULL;
964 gint32 result = (int)(gsize)mono_defaults.int32_class;
965 MonoClassField* field;
970 klass = mono_object_class (this);
972 if (mono_class_num_fields (klass) == 0)
976 * Compute the starting value of the hashcode for fields of primitive
977 * types, and return the remaining fields in an array to the managed side.
978 * This way, we can avoid costly reflection operations in managed code.
981 while ((field = mono_class_get_fields (klass, &iter))) {
982 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
984 if (mono_field_is_deleted (field))
986 /* FIXME: Add more types */
987 switch (field->type->type) {
989 result ^= *(gint32*)((guint8*)this + field->offset);
991 case MONO_TYPE_STRING: {
993 s = *(MonoString**)((guint8*)this + field->offset);
995 result ^= mono_string_hash (s);
1000 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1001 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1002 values [count++] = o;
1008 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1009 for (i = 0; i < count; ++i)
1010 mono_array_setref (*fields, i, values [i]);
1017 ICALL_EXPORT MonoBoolean
1018 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1021 MonoObject **values = NULL;
1023 MonoClassField* field;
1027 MONO_ARCH_SAVE_REGS;
1029 MONO_CHECK_ARG_NULL (that);
1031 if (this->vtable != that->vtable)
1034 klass = mono_object_class (this);
1036 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1037 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1040 * Do the comparison for fields of primitive type and return a result if
1041 * possible. Otherwise, return the remaining fields in an array to the
1042 * managed side. This way, we can avoid costly reflection operations in
1047 while ((field = mono_class_get_fields (klass, &iter))) {
1048 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1050 if (mono_field_is_deleted (field))
1052 /* FIXME: Add more types */
1053 switch (field->type->type) {
1056 case MONO_TYPE_BOOLEAN:
1057 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1062 case MONO_TYPE_CHAR:
1063 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1068 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1073 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1077 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1081 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1086 case MONO_TYPE_STRING: {
1087 MonoString *s1, *s2;
1088 guint32 s1len, s2len;
1089 s1 = *(MonoString**)((guint8*)this + field->offset);
1090 s2 = *(MonoString**)((guint8*)that + field->offset);
1093 if ((s1 == NULL) || (s2 == NULL))
1095 s1len = mono_string_length (s1);
1096 s2len = mono_string_length (s2);
1100 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1106 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1107 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1108 values [count++] = o;
1109 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1110 values [count++] = o;
1113 if (klass->enumtype)
1114 /* enums only have one non-static field */
1120 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1121 for (i = 0; i < count; ++i)
1122 mono_array_setref_fast (*fields, i, values [i]);
1129 ICALL_EXPORT MonoReflectionType *
1130 ves_icall_System_Object_GetType (MonoObject *obj)
1132 MONO_ARCH_SAVE_REGS;
1134 #ifndef DISABLE_REMOTING
1135 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1136 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1139 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1143 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1145 MONO_ARCH_SAVE_REGS;
1147 mtype->type = &obj->vtable->klass->byval_arg;
1148 g_assert (mtype->type->type);
1152 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1154 MONO_ARCH_SAVE_REGS;
1156 MONO_CHECK_ARG_NULL (obj);
1158 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1162 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1163 MonoReflectionMethod *method,
1164 MonoArray *opt_param_types)
1166 MONO_ARCH_SAVE_REGS;
1168 MONO_CHECK_ARG_NULL (method);
1170 return mono_image_create_method_token (
1171 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1175 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1177 MONO_ARCH_SAVE_REGS;
1179 mono_image_create_pefile (mb, file);
1183 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1185 MONO_ARCH_SAVE_REGS;
1187 mono_image_build_metadata (mb);
1191 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1193 MONO_ARCH_SAVE_REGS;
1195 mono_image_register_token (mb->dynamic_image, token, obj);
1199 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1201 MonoMethod **dest = data;
1203 /* skip unmanaged frames */
1219 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1221 MonoMethod **dest = data;
1223 /* skip unmanaged frames */
1228 if (!strcmp (m->klass->name_space, "System.Reflection"))
1237 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1239 MonoMethod **dest = data;
1241 /* skip unmanaged frames */
1245 if (m->wrapper_type != MONO_WRAPPER_NONE)
1248 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1262 static MonoReflectionType *
1263 type_from_name (const char *str, MonoBoolean ignoreCase)
1265 MonoMethod *m, *dest;
1267 MonoType *type = NULL;
1268 MonoAssembly *assembly = NULL;
1269 MonoTypeNameParse info;
1270 char *temp_str = g_strdup (str);
1271 gboolean type_resolve = FALSE;
1273 MONO_ARCH_SAVE_REGS;
1275 /* mono_reflection_parse_type() mangles the string */
1276 if (!mono_reflection_parse_type (temp_str, &info)) {
1277 mono_reflection_free_type_info (&info);
1284 * We must compute the calling assembly as type loading must happen under a metadata context.
1285 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1286 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1288 m = mono_method_get_last_managed ();
1291 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1296 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1297 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1298 * to crash. This only seems to happen in some strange remoting
1299 * scenarios and I was unable to figure out what's happening there.
1300 * Dec 10, 2005 - Martin.
1304 assembly = dest->klass->image->assembly;
1305 type_resolve = TRUE;
1307 g_warning (G_STRLOC);
1310 if (info.assembly.name)
1311 assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
1315 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1316 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1319 if (!info.assembly.name && !type) /* try mscorlib */
1320 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1322 if (assembly && !type && type_resolve) {
1323 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1324 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1327 mono_reflection_free_type_info (&info);
1333 return mono_type_get_object (mono_domain_get (), type);
1337 MonoReflectionType *
1338 mono_type_get (const char *str)
1340 char *copy = g_strdup (str);
1341 MonoReflectionType *type = type_from_name (copy, FALSE);
1348 ICALL_EXPORT MonoReflectionType*
1349 ves_icall_type_from_name (MonoString *name,
1350 MonoBoolean throwOnError,
1351 MonoBoolean ignoreCase)
1353 char *str = mono_string_to_utf8 (name);
1354 MonoReflectionType *type;
1356 type = type_from_name (str, ignoreCase);
1359 MonoException *e = NULL;
1362 e = mono_get_exception_type_load (name, NULL);
1364 mono_loader_clear_error ();
1366 mono_raise_exception (e);
1373 ICALL_EXPORT MonoReflectionType*
1374 ves_icall_type_from_handle (MonoType *handle)
1376 MonoDomain *domain = mono_domain_get ();
1378 MONO_ARCH_SAVE_REGS;
1380 return mono_type_get_object (domain, handle);
1383 ICALL_EXPORT MonoBoolean
1384 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1386 MONO_ARCH_SAVE_REGS;
1388 if (c && type->type && c->type)
1389 return mono_metadata_type_equal (type->type, c->type);
1391 return (type == c) ? TRUE : FALSE;
1394 /* System.TypeCode */
1413 TYPECODE_STRING = 18
1416 ICALL_EXPORT guint32
1417 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1419 int t = type->type->type;
1421 MONO_ARCH_SAVE_REGS;
1423 if (type->type->byref)
1424 return TYPECODE_OBJECT;
1428 case MONO_TYPE_VOID:
1429 return TYPECODE_OBJECT;
1430 case MONO_TYPE_BOOLEAN:
1431 return TYPECODE_BOOLEAN;
1433 return TYPECODE_BYTE;
1435 return TYPECODE_SBYTE;
1437 return TYPECODE_UINT16;
1439 return TYPECODE_INT16;
1440 case MONO_TYPE_CHAR:
1441 return TYPECODE_CHAR;
1445 return TYPECODE_OBJECT;
1447 return TYPECODE_UINT32;
1449 return TYPECODE_INT32;
1451 return TYPECODE_UINT64;
1453 return TYPECODE_INT64;
1455 return TYPECODE_SINGLE;
1457 return TYPECODE_DOUBLE;
1458 case MONO_TYPE_VALUETYPE: {
1459 MonoClass *klass = type->type->data.klass;
1461 if (klass->enumtype) {
1462 t = mono_class_enum_basetype (klass)->type;
1464 } else if (mono_is_corlib_image (klass->image)) {
1465 if (strcmp (klass->name_space, "System") == 0) {
1466 if (strcmp (klass->name, "Decimal") == 0)
1467 return TYPECODE_DECIMAL;
1468 else if (strcmp (klass->name, "DateTime") == 0)
1469 return TYPECODE_DATETIME;
1472 return TYPECODE_OBJECT;
1474 case MONO_TYPE_STRING:
1475 return TYPECODE_STRING;
1476 case MONO_TYPE_SZARRAY:
1477 case MONO_TYPE_ARRAY:
1478 case MONO_TYPE_OBJECT:
1480 case MONO_TYPE_MVAR:
1481 case MONO_TYPE_TYPEDBYREF:
1482 return TYPECODE_OBJECT;
1483 case MONO_TYPE_CLASS:
1485 MonoClass *klass = type->type->data.klass;
1486 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1487 if (strcmp (klass->name, "DBNull") == 0)
1488 return TYPECODE_DBNULL;
1491 return TYPECODE_OBJECT;
1492 case MONO_TYPE_GENERICINST:
1493 return TYPECODE_OBJECT;
1495 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1500 ICALL_EXPORT guint32
1501 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1507 MONO_ARCH_SAVE_REGS;
1509 g_assert (type != NULL);
1511 domain = ((MonoObject *)type)->vtable->domain;
1513 if (!c) /* FIXME: dont know what do do here */
1516 klass = mono_class_from_mono_type (type->type);
1517 klassc = mono_class_from_mono_type (c->type);
1519 /* Interface check requires a more complex setup so we
1520 * only do for them. Otherwise we simply avoid mono_class_init.
1522 if (check_interfaces) {
1523 mono_class_init_or_throw (klass);
1524 mono_class_init_or_throw (klassc);
1525 } else if (!klass->supertypes || !klassc->supertypes) {
1526 mono_class_setup_supertypes (klass);
1527 mono_class_setup_supertypes (klassc);
1530 if (type->type->byref)
1531 return klassc == mono_defaults.object_class;
1533 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1537 mono_type_is_primitive (MonoType *type)
1539 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1540 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1544 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1546 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1547 return mono_class_enum_basetype (type->data.klass);
1548 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1549 return mono_class_enum_basetype (type->data.generic_class->container_class);
1553 ICALL_EXPORT guint32
1554 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1560 MONO_ARCH_SAVE_REGS;
1562 g_assert (type != NULL);
1564 domain = ((MonoObject *)type)->vtable->domain;
1566 klass = mono_class_from_mono_type (type->type);
1567 klassc = mono_class_from_mono_type (c->type);
1569 if (type->type->byref ^ c->type->byref)
1572 if (type->type->byref) {
1573 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1574 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1576 klass = mono_class_from_mono_type (t);
1577 klassc = mono_class_from_mono_type (ot);
1579 if (mono_type_is_primitive (t)) {
1580 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1581 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1582 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1583 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1584 return t->type == ot->type;
1586 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1589 if (klass->valuetype)
1590 return klass == klassc;
1591 return klass->valuetype == klassc->valuetype;
1594 return mono_class_is_assignable_from (klass, klassc);
1597 ICALL_EXPORT guint32
1598 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1600 MonoClass *klass = mono_class_from_mono_type (type->type);
1601 mono_class_init_or_throw (klass);
1602 return mono_object_isinst (obj, klass) != NULL;
1605 ICALL_EXPORT guint32
1606 ves_icall_get_attributes (MonoReflectionType *type)
1608 MonoClass *klass = mono_class_from_mono_type (type->type);
1609 return klass->flags;
1612 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1613 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1615 MonoClass *klass = field->field->parent;
1616 MonoMarshalType *info;
1620 if (klass->generic_container ||
1621 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1624 ftype = mono_field_get_type (field->field);
1625 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1628 info = mono_marshal_load_type_info (klass);
1630 for (i = 0; i < info->num_fields; ++i) {
1631 if (info->fields [i].field == field->field) {
1632 if (!info->fields [i].mspec)
1635 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1642 ICALL_EXPORT MonoReflectionField*
1643 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1645 gboolean found = FALSE;
1652 klass = handle->parent;
1654 klass = mono_class_from_mono_type (type);
1656 /* Check that the field belongs to the class */
1657 for (k = klass; k; k = k->parent) {
1658 if (k == handle->parent) {
1665 /* The managed code will throw the exception */
1669 return mono_field_get_object (mono_domain_get (), klass, handle);
1672 ICALL_EXPORT MonoArray*
1673 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1676 MonoType *type = mono_field_get_type_checked (field->field, &error);
1677 mono_error_raise_exception (&error);
1679 return type_array_from_modifiers (field->field->parent->image, type, optional);
1683 vell_icall_get_method_attributes (MonoMethod *method)
1685 return method->flags;
1689 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1692 MonoDomain *domain = mono_domain_get ();
1693 MonoMethodSignature* sig;
1694 MONO_ARCH_SAVE_REGS;
1696 sig = mono_method_signature_checked (method, &error);
1697 if (!mono_error_ok (&error))
1698 mono_error_raise_exception (&error);
1701 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1702 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1703 info->attrs = method->flags;
1704 info->implattrs = method->iflags;
1705 if (sig->call_convention == MONO_CALL_DEFAULT)
1706 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1708 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1713 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1716 ICALL_EXPORT MonoArray*
1717 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1719 MonoDomain *domain = mono_domain_get ();
1721 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1724 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1725 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1727 MonoDomain *domain = mono_domain_get ();
1728 MonoReflectionMarshalAsAttribute* res = NULL;
1729 MonoMarshalSpec **mspecs;
1732 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1733 mono_method_get_marshal_info (method, mspecs);
1736 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1738 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1740 mono_metadata_free_marshal_spec (mspecs [i]);
1747 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1749 MonoClass *parent = field->field->parent;
1750 if (!parent->size_inited)
1751 mono_class_init (parent);
1752 mono_class_setup_fields_locking (parent);
1754 return field->field->offset - sizeof (MonoObject);
1757 ICALL_EXPORT MonoReflectionType*
1758 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1761 MONO_ARCH_SAVE_REGS;
1763 parent = declaring? field->field->parent: field->klass;
1765 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1768 ICALL_EXPORT MonoObject *
1769 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1771 MonoClass *fklass = field->klass;
1772 MonoClassField *cf = field->field;
1773 MonoDomain *domain = mono_object_domain (field);
1775 if (fklass->image->assembly->ref_only)
1776 mono_raise_exception (mono_get_exception_invalid_operation (
1777 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1779 if (mono_security_core_clr_enabled ())
1780 mono_security_core_clr_ensure_reflection_access_field (cf);
1782 return mono_field_get_value_object (domain, cf, obj);
1786 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1789 MonoClassField *cf = field->field;
1793 MONO_ARCH_SAVE_REGS;
1795 if (field->klass->image->assembly->ref_only)
1796 mono_raise_exception (mono_get_exception_invalid_operation (
1797 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1799 if (mono_security_core_clr_enabled ())
1800 mono_security_core_clr_ensure_reflection_access_field (cf);
1802 type = mono_field_get_type_checked (cf, &error);
1803 if (!mono_error_ok (&error))
1804 mono_error_raise_exception (&error);
1806 v = (gchar *) value;
1808 switch (type->type) {
1811 case MONO_TYPE_BOOLEAN:
1814 case MONO_TYPE_CHAR:
1823 case MONO_TYPE_VALUETYPE:
1826 v += sizeof (MonoObject);
1828 case MONO_TYPE_STRING:
1829 case MONO_TYPE_OBJECT:
1830 case MONO_TYPE_CLASS:
1831 case MONO_TYPE_ARRAY:
1832 case MONO_TYPE_SZARRAY:
1835 case MONO_TYPE_GENERICINST: {
1836 MonoGenericClass *gclass = type->data.generic_class;
1837 g_assert (!gclass->context.class_inst->is_open);
1839 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1840 MonoClass *nklass = mono_class_from_mono_type (type);
1841 MonoObject *nullable;
1844 * Convert the boxed vtype into a Nullable structure.
1845 * This is complicated by the fact that Nullables have
1846 * a variable structure.
1848 nullable = mono_object_new (mono_domain_get (), nklass);
1850 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1852 v = mono_object_unbox (nullable);
1855 if (gclass->container_class->valuetype && (v != NULL))
1856 v += sizeof (MonoObject);
1860 g_error ("type 0x%x not handled in "
1861 "ves_icall_FieldInfo_SetValueInternal", type->type);
1866 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1867 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1868 if (!vtable->initialized)
1869 mono_runtime_class_init (vtable);
1870 mono_field_static_set_value (vtable, cf, v);
1872 mono_field_set_value (obj, cf, v);
1876 ICALL_EXPORT MonoObject *
1877 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1879 MonoObject *o = NULL;
1880 MonoClassField *field = this->field;
1882 MonoDomain *domain = mono_object_domain (this);
1884 MonoTypeEnum def_type;
1885 const char *def_value;
1889 MONO_ARCH_SAVE_REGS;
1891 mono_class_init (field->parent);
1893 t = mono_field_get_type_checked (field, &error);
1894 if (!mono_error_ok (&error))
1895 mono_error_raise_exception (&error);
1897 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1898 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1900 if (image_is_dynamic (field->parent->image)) {
1902 g_assert_not_reached ();
1905 def_value = mono_class_get_field_default_value (field, &def_type);
1906 if (!def_value) /*FIXME, maybe we should try to raise TLE if field->parent is broken */
1907 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1909 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1913 case MONO_TYPE_BOOLEAN:
1916 case MONO_TYPE_CHAR:
1924 case MONO_TYPE_R8: {
1927 /* boxed value type */
1928 t = g_new0 (MonoType, 1);
1930 klass = mono_class_from_mono_type (t);
1932 o = mono_object_new (domain, klass);
1933 v = ((gchar *) o) + sizeof (MonoObject);
1934 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1937 case MONO_TYPE_STRING:
1938 case MONO_TYPE_CLASS:
1939 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1942 g_assert_not_reached ();
1948 ICALL_EXPORT MonoReflectionType*
1949 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1952 MonoClassField *field = ref_field->field;
1953 MonoType *type = mono_field_get_type_checked (field, &error);
1954 if (!mono_error_ok (&error))
1955 mono_error_raise_exception (&error);
1956 return mono_type_get_object (mono_object_domain (ref_field), type);
1959 ICALL_EXPORT MonoReflectionType*
1960 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1962 MonoMethod *method = rmethod->method.method;
1964 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1967 /* From MonoProperty.cs */
1969 PInfo_Attributes = 1,
1970 PInfo_GetMethod = 1 << 1,
1971 PInfo_SetMethod = 1 << 2,
1972 PInfo_ReflectedType = 1 << 3,
1973 PInfo_DeclaringType = 1 << 4,
1978 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1980 MonoDomain *domain = mono_object_domain (property);
1982 MONO_ARCH_SAVE_REGS;
1984 if ((req_info & PInfo_ReflectedType) != 0)
1985 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1986 if ((req_info & PInfo_DeclaringType) != 0)
1987 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1989 if ((req_info & PInfo_Name) != 0)
1990 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1992 if ((req_info & PInfo_Attributes) != 0)
1993 info->attrs = property->property->attrs;
1995 if ((req_info & PInfo_GetMethod) != 0)
1996 MONO_STRUCT_SETREF (info, get, property->property->get ?
1997 mono_method_get_object (domain, property->property->get, property->klass): NULL);
1999 if ((req_info & PInfo_SetMethod) != 0)
2000 MONO_STRUCT_SETREF (info, set, property->property->set ?
2001 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2003 * There may be other methods defined for properties, though, it seems they are not exposed
2004 * in the reflection API
2009 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2011 MonoDomain *domain = mono_object_domain (event);
2013 MONO_ARCH_SAVE_REGS;
2015 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2016 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2018 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2019 info->attrs = event->event->attrs;
2020 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2021 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2022 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2024 #ifndef MONO_SMALL_CONFIG
2025 if (event->event->other) {
2027 while (event->event->other [n])
2029 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2031 for (i = 0; i < n; i++)
2032 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2038 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2043 mono_class_setup_interfaces (klass, error);
2044 if (!mono_error_ok (error))
2047 for (i = 0; i < klass->interface_count; i++) {
2048 ic = klass->interfaces [i];
2049 g_hash_table_insert (ifaces, ic, ic);
2051 collect_interfaces (ic, ifaces, error);
2052 if (!mono_error_ok (error))
2058 MonoArray *iface_array;
2059 MonoGenericContext *context;
2063 } FillIfaceArrayData;
2066 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2068 FillIfaceArrayData *data = user_data;
2069 MonoClass *ic = key;
2070 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2072 if (!mono_error_ok (data->error))
2075 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2076 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2077 if (!mono_error_ok (data->error))
2081 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2084 mono_metadata_free_type (inflated);
2087 ICALL_EXPORT MonoArray*
2088 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2091 MonoClass *class = mono_class_from_mono_type (type->type);
2093 FillIfaceArrayData data = { 0 };
2096 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2098 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2099 data.context = mono_class_get_context (class);
2100 class = class->generic_class->container_class;
2103 for (parent = class; parent; parent = parent->parent) {
2104 mono_class_setup_interfaces (parent, &error);
2105 if (!mono_error_ok (&error))
2107 collect_interfaces (parent, iface_hash, &error);
2108 if (!mono_error_ok (&error))
2112 data.error = &error;
2113 data.domain = mono_object_domain (type);
2115 len = g_hash_table_size (iface_hash);
2117 g_hash_table_destroy (iface_hash);
2118 if (!data.domain->empty_types)
2119 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2120 return data.domain->empty_types;
2123 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2124 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2125 if (!mono_error_ok (&error))
2128 g_hash_table_destroy (iface_hash);
2129 return data.iface_array;
2132 g_hash_table_destroy (iface_hash);
2133 mono_error_raise_exception (&error);
2138 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2140 gboolean variance_used;
2141 MonoClass *class = mono_class_from_mono_type (type->type);
2142 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2143 MonoReflectionMethod *member;
2146 int i = 0, len, ioffset;
2149 MONO_ARCH_SAVE_REGS;
2150 mono_class_init_or_throw (class);
2151 mono_class_init_or_throw (iclass);
2153 mono_class_setup_vtable (class);
2155 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2159 len = mono_class_num_methods (iclass);
2160 domain = mono_object_domain (type);
2161 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2162 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2164 while ((method = mono_class_get_methods (iclass, &iter))) {
2165 member = mono_method_get_object (domain, method, iclass);
2166 mono_array_setref (*methods, i, member);
2167 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2168 mono_array_setref (*targets, i, member);
2175 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2177 MonoClass *klass = mono_class_from_mono_type (type->type);
2178 mono_class_init_or_throw (klass);
2180 if (image_is_dynamic (klass->image)) {
2181 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2182 *packing = tb->packing_size;
2183 *size = tb->class_size;
2185 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2189 ICALL_EXPORT MonoReflectionType*
2190 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2194 MONO_ARCH_SAVE_REGS;
2196 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2197 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2199 class = mono_class_from_mono_type (type->type);
2200 mono_class_init_or_throw (class);
2202 // GetElementType should only return a type for:
2203 // Array Pointer PassedByRef
2204 if (type->type->byref)
2205 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2206 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2207 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2208 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2209 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2214 ICALL_EXPORT MonoReflectionType*
2215 ves_icall_get_type_parent (MonoReflectionType *type)
2217 MonoClass *class = mono_class_from_mono_type (type->type);
2218 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2221 ICALL_EXPORT MonoBoolean
2222 ves_icall_type_ispointer (MonoReflectionType *type)
2224 MONO_ARCH_SAVE_REGS;
2226 return type->type->type == MONO_TYPE_PTR;
2229 ICALL_EXPORT MonoBoolean
2230 ves_icall_type_isprimitive (MonoReflectionType *type)
2232 MONO_ARCH_SAVE_REGS;
2234 return (!type->type->byref && (((type->type->type >= MONO_TYPE_BOOLEAN) && (type->type->type <= MONO_TYPE_R8)) || (type->type->type == MONO_TYPE_I) || (type->type->type == MONO_TYPE_U)));
2237 ICALL_EXPORT MonoBoolean
2238 ves_icall_type_isbyref (MonoReflectionType *type)
2240 MONO_ARCH_SAVE_REGS;
2242 return type->type->byref;
2245 ICALL_EXPORT MonoBoolean
2246 ves_icall_type_iscomobject (MonoReflectionType *type)
2248 MonoClass *klass = mono_class_from_mono_type (type->type);
2249 mono_class_init_or_throw (klass);
2251 return mono_class_is_com_object (klass);
2254 ICALL_EXPORT MonoReflectionModule*
2255 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2257 MonoClass *class = mono_class_from_mono_type (type->type);
2258 return mono_module_get_object (mono_object_domain (type), class->image);
2261 ICALL_EXPORT MonoReflectionAssembly*
2262 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2264 MonoDomain *domain = mono_domain_get ();
2265 MonoClass *class = mono_class_from_mono_type (type->type);
2266 return mono_assembly_get_object (domain, class->image->assembly);
2269 ICALL_EXPORT MonoReflectionType*
2270 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2272 MonoDomain *domain = mono_domain_get ();
2275 MONO_ARCH_SAVE_REGS;
2277 if (type->type->byref)
2279 if (type->type->type == MONO_TYPE_VAR) {
2280 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2281 class = param ? param->owner.klass : NULL;
2282 } else if (type->type->type == MONO_TYPE_MVAR) {
2283 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2284 class = param ? param->owner.method->klass : NULL;
2286 class = mono_class_from_mono_type (type->type)->nested_in;
2289 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2292 ICALL_EXPORT MonoString*
2293 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2295 MonoDomain *domain = mono_domain_get ();
2296 MonoClass *class = mono_class_from_mono_type (type->type);
2298 if (type->type->byref) {
2299 char *n = g_strdup_printf ("%s&", class->name);
2300 MonoString *res = mono_string_new (domain, n);
2306 return mono_string_new (domain, class->name);
2310 ICALL_EXPORT MonoString*
2311 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2313 MonoDomain *domain = mono_domain_get ();
2314 MonoClass *class = mono_class_from_mono_type (type->type);
2316 while (class->nested_in)
2317 class = class->nested_in;
2319 if (class->name_space [0] == '\0')
2322 return mono_string_new (domain, class->name_space);
2326 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2330 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2331 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2333 class = mono_class_from_mono_type (type->type);
2338 ICALL_EXPORT MonoArray*
2339 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2342 MonoClass *klass, *pklass;
2343 MonoDomain *domain = mono_object_domain (type);
2344 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2346 MONO_ARCH_SAVE_REGS;
2348 klass = mono_class_from_mono_type (type->type);
2350 if (klass->generic_container) {
2351 MonoGenericContainer *container = klass->generic_container;
2352 res = mono_array_new_specific (array_vtable, container->type_argc);
2353 for (i = 0; i < container->type_argc; ++i) {
2354 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2355 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2357 } else if (klass->generic_class) {
2358 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2359 res = mono_array_new_specific (array_vtable, inst->type_argc);
2360 for (i = 0; i < inst->type_argc; ++i)
2361 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2363 res = mono_array_new_specific (array_vtable, 0);
2368 ICALL_EXPORT gboolean
2369 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2372 MONO_ARCH_SAVE_REGS;
2374 if (!IS_MONOTYPE (type))
2377 if (type->type->byref)
2380 klass = mono_class_from_mono_type (type->type);
2381 return klass->generic_container != NULL;
2384 ICALL_EXPORT MonoReflectionType*
2385 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2388 MONO_ARCH_SAVE_REGS;
2390 if (type->type->byref)
2393 klass = mono_class_from_mono_type (type->type);
2395 if (klass->generic_container) {
2396 return type; /* check this one */
2398 if (klass->generic_class) {
2399 MonoClass *generic_class = klass->generic_class->container_class;
2402 tb = mono_class_get_ref_info (generic_class);
2404 if (generic_class->wastypebuilder && tb)
2407 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2412 ICALL_EXPORT MonoReflectionType*
2413 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2416 MonoType *geninst, **types;
2419 g_assert (IS_MONOTYPE (type));
2420 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2422 count = mono_array_length (type_array);
2423 types = g_new0 (MonoType *, count);
2425 for (i = 0; i < count; i++) {
2426 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2427 types [i] = t->type;
2430 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2435 class = mono_class_from_mono_type (geninst);
2437 /*we might inflate to the GTD*/
2438 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2439 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2441 return mono_type_get_object (mono_object_domain (type), geninst);
2444 ICALL_EXPORT gboolean
2445 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2448 MONO_ARCH_SAVE_REGS;
2450 if (type->type->byref)
2453 klass = mono_class_from_mono_type (type->type);
2455 return klass->generic_class != NULL;
2458 ICALL_EXPORT gboolean
2459 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2462 MONO_ARCH_SAVE_REGS;
2464 if (!IS_MONOTYPE (type))
2467 if (type->type->byref)
2470 klass = mono_class_from_mono_type (type->type);
2471 return klass->generic_class != NULL || klass->generic_container != NULL;
2475 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2477 MONO_ARCH_SAVE_REGS;
2479 if (!IS_MONOTYPE (type))
2482 if (is_generic_parameter (type->type))
2483 return mono_type_get_generic_param_num (type->type);
2487 ICALL_EXPORT GenericParameterAttributes
2488 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2490 MONO_ARCH_SAVE_REGS;
2492 g_assert (IS_MONOTYPE (type));
2493 g_assert (is_generic_parameter (type->type));
2494 return mono_generic_param_info (type->type->data.generic_param)->flags;
2497 ICALL_EXPORT MonoArray *
2498 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2500 MonoGenericParamInfo *param_info;
2506 MONO_ARCH_SAVE_REGS;
2508 g_assert (IS_MONOTYPE (type));
2510 domain = mono_object_domain (type);
2511 param_info = mono_generic_param_info (type->type->data.generic_param);
2512 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2515 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2516 for (i = 0; i < count; i++)
2517 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2523 ICALL_EXPORT MonoBoolean
2524 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2526 MONO_ARCH_SAVE_REGS;
2527 return is_generic_parameter (type->type);
2530 ICALL_EXPORT MonoBoolean
2531 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2533 MONO_ARCH_SAVE_REGS;
2534 return is_generic_parameter (tb->type.type);
2538 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2539 MonoReflectionType *t)
2541 enumtype->type = t->type;
2544 ICALL_EXPORT MonoReflectionMethod*
2545 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2546 MonoReflectionMethod* generic)
2553 MONO_ARCH_SAVE_REGS;
2555 domain = ((MonoObject *)type)->vtable->domain;
2557 klass = mono_class_from_mono_type (type->type);
2558 mono_class_init_or_throw (klass);
2561 while ((method = mono_class_get_methods (klass, &iter))) {
2562 if (method->token == generic->method->token)
2563 return mono_method_get_object (domain, method, klass);
2571 ICALL_EXPORT MonoReflectionMethod *
2572 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2575 MonoType *type = ref_type->type;
2577 MONO_ARCH_SAVE_REGS;
2579 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2580 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2581 if (type->type == MONO_TYPE_VAR)
2584 method = mono_type_get_generic_param_owner (type)->owner.method;
2586 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2589 ICALL_EXPORT MonoReflectionDllImportAttribute*
2590 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2592 static MonoClass *DllImportAttributeClass = NULL;
2593 MonoDomain *domain = mono_domain_get ();
2594 MonoReflectionDllImportAttribute *attr;
2595 MonoImage *image = method->klass->image;
2596 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2597 MonoTableInfo *tables = image->tables;
2598 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2599 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2600 guint32 im_cols [MONO_IMPLMAP_SIZE];
2601 guint32 scope_token;
2602 const char *import = NULL;
2603 const char *scope = NULL;
2606 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2609 if (!DllImportAttributeClass) {
2610 DllImportAttributeClass =
2611 mono_class_from_name (mono_defaults.corlib,
2612 "System.Runtime.InteropServices", "DllImportAttribute");
2613 g_assert (DllImportAttributeClass);
2616 if (image_is_dynamic (method->klass->image)) {
2617 MonoReflectionMethodAux *method_aux =
2618 g_hash_table_lookup (
2619 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2621 import = method_aux->dllentry;
2622 scope = method_aux->dll;
2625 if (!import || !scope) {
2626 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2631 if (piinfo->implmap_idx) {
2632 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2634 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2635 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2636 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2637 scope = mono_metadata_string_heap (image, scope_token);
2640 flags = piinfo->piflags;
2642 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2644 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2645 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2646 attr->call_conv = (flags & 0x700) >> 8;
2647 attr->charset = ((flags & 0x6) >> 1) + 1;
2648 if (attr->charset == 1)
2650 attr->exact_spelling = (flags & 0x1) != 0;
2651 attr->set_last_error = (flags & 0x40) != 0;
2652 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2653 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2654 attr->preserve_sig = FALSE;
2659 ICALL_EXPORT MonoReflectionMethod *
2660 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2662 MonoMethodInflated *imethod;
2665 MONO_ARCH_SAVE_REGS;
2667 if (method->method->is_generic)
2670 if (!method->method->is_inflated)
2673 imethod = (MonoMethodInflated *) method->method;
2675 result = imethod->declaring;
2676 /* Not a generic method. */
2677 if (!result->is_generic)
2680 if (image_is_dynamic (method->method->klass->image)) {
2681 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2682 MonoReflectionMethod *res;
2685 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2686 * the dynamic case as well ?
2688 mono_image_lock ((MonoImage*)image);
2689 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2690 mono_image_unlock ((MonoImage*)image);
2696 if (imethod->context.class_inst) {
2697 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2698 /*Generic methods gets the context of the GTD.*/
2699 if (mono_class_get_context (klass))
2700 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2703 return mono_method_get_object (mono_object_domain (method), result, NULL);
2706 ICALL_EXPORT gboolean
2707 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2709 MONO_ARCH_SAVE_REGS;
2711 return mono_method_signature (method->method)->generic_param_count != 0;
2714 ICALL_EXPORT gboolean
2715 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2717 MONO_ARCH_SAVE_REGS;
2719 return method->method->is_generic;
2722 ICALL_EXPORT MonoArray*
2723 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2728 MONO_ARCH_SAVE_REGS;
2730 domain = mono_object_domain (method);
2732 if (method->method->is_inflated) {
2733 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2736 count = inst->type_argc;
2737 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2739 for (i = 0; i < count; i++)
2740 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2746 count = mono_method_signature (method->method)->generic_param_count;
2747 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2749 for (i = 0; i < count; i++) {
2750 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2751 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2752 MonoClass *pklass = mono_class_from_generic_parameter (
2753 param, method->method->klass->image, TRUE);
2754 mono_array_setref (res, i,
2755 mono_type_get_object (domain, &pklass->byval_arg));
2761 ICALL_EXPORT MonoObject *
2762 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2765 * Invoke from reflection is supposed to always be a virtual call (the API
2766 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2767 * greater flexibility.
2769 MonoMethod *m = method->method;
2770 MonoMethodSignature *sig = mono_method_signature (m);
2775 MONO_ARCH_SAVE_REGS;
2779 if (mono_security_core_clr_enabled ())
2780 mono_security_core_clr_ensure_reflection_access_method (m);
2782 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2783 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2784 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2789 if (!mono_object_isinst (this, m->klass)) {
2790 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2791 char *target_name = mono_type_get_full_name (m->klass);
2792 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2793 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2795 g_free (target_name);
2799 m = mono_object_get_virtual_method (this, m);
2800 /* must pass the pointer to the value for valuetype methods */
2801 if (m->klass->valuetype)
2802 obj = mono_object_unbox (this);
2803 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2804 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2809 if (sig->ret->byref) {
2810 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System", "NotSupportedException", "Cannot invoke method returning ByRef type via reflection"));
2814 pcount = params? mono_array_length (params): 0;
2815 if (pcount != sig->param_count) {
2816 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2820 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2821 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Cannot invoke constructor of an abstract class."));
2825 image = m->klass->image;
2826 if (image->assembly->ref_only) {
2827 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_invalid_operation ("It is illegal to invoke a method on a type loaded using the ReflectionOnly api."));
2831 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2832 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2836 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2839 intptr_t *lower_bounds;
2840 pcount = mono_array_length (params);
2841 lengths = alloca (sizeof (uintptr_t) * pcount);
2842 /* Note: the synthetized array .ctors have int32 as argument type */
2843 for (i = 0; i < pcount; ++i)
2844 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2846 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2847 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2848 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2850 for (i = 0; i < mono_array_length (arr); ++i) {
2851 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2853 mono_array_setref_fast (arr, i, subarray);
2855 return (MonoObject*)arr;
2858 if (m->klass->rank == pcount) {
2859 /* Only lengths provided. */
2860 lower_bounds = NULL;
2862 g_assert (pcount == (m->klass->rank * 2));
2863 /* lower bounds are first. */
2864 lower_bounds = (intptr_t*)lengths;
2865 lengths += m->klass->rank;
2868 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2870 return mono_runtime_invoke_array (m, obj, params, NULL);
2873 #ifndef DISABLE_REMOTING
2874 ICALL_EXPORT MonoObject *
2875 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2877 MonoDomain *domain = mono_object_domain (method);
2878 MonoMethod *m = method->method;
2879 MonoMethodSignature *sig = mono_method_signature (m);
2880 MonoArray *out_args;
2882 int i, j, outarg_count = 0;
2884 MONO_ARCH_SAVE_REGS;
2886 if (m->klass == mono_defaults.object_class) {
2888 if (!strcmp (m->name, "FieldGetter")) {
2889 MonoClass *k = this->vtable->klass;
2893 /* If this is a proxy, then it must be a CBO */
2894 if (k == mono_defaults.transparent_proxy_class) {
2895 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2896 this = tp->rp->unwrapped_server;
2898 k = this->vtable->klass;
2901 name = mono_array_get (params, MonoString *, 1);
2902 str = mono_string_to_utf8 (name);
2905 MonoClassField* field = mono_class_get_field_from_name (k, str);
2907 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2908 if (field_klass->valuetype)
2909 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2911 result = *((gpointer *)((char *)this + field->offset));
2913 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2914 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2915 mono_array_setref (out_args, 0, result);
2923 g_assert_not_reached ();
2925 } else if (!strcmp (m->name, "FieldSetter")) {
2926 MonoClass *k = this->vtable->klass;
2932 /* If this is a proxy, then it must be a CBO */
2933 if (k == mono_defaults.transparent_proxy_class) {
2934 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2935 this = tp->rp->unwrapped_server;
2937 k = this->vtable->klass;
2940 name = mono_array_get (params, MonoString *, 1);
2941 str = mono_string_to_utf8 (name);
2944 MonoClassField* field = mono_class_get_field_from_name (k, str);
2946 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2947 MonoObject *val = mono_array_get (params, gpointer, 2);
2949 if (field_klass->valuetype) {
2950 size = mono_type_size (field->type, &align);
2951 g_assert (size == mono_class_value_size (field_klass, NULL));
2952 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2954 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2957 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2958 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2968 g_assert_not_reached ();
2973 for (i = 0; i < mono_array_length (params); i++) {
2974 if (sig->params [i]->byref)
2978 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2980 /* handle constructors only for objects already allocated */
2981 if (!strcmp (method->method->name, ".ctor"))
2984 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2985 g_assert (!method->method->klass->valuetype);
2986 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2988 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2989 if (sig->params [i]->byref) {
2991 arg = mono_array_get (params, gpointer, i);
2992 mono_array_setref (out_args, j, arg);
2997 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3004 read_enum_value (char *mem, int type)
3008 return *(guint8*)mem;
3010 return *(gint8*)mem;
3012 return *(guint16*)mem;
3014 return *(gint16*)mem;
3016 return *(guint32*)mem;
3018 return *(gint32*)mem;
3020 return *(guint64*)mem;
3022 return *(gint64*)mem;
3024 g_assert_not_reached ();
3030 write_enum_value (char *mem, int type, guint64 value)
3034 case MONO_TYPE_I1: {
3035 guint8 *p = (guint8*)mem;
3040 case MONO_TYPE_I2: {
3041 guint16 *p = (void*)mem;
3046 case MONO_TYPE_I4: {
3047 guint32 *p = (void*)mem;
3052 case MONO_TYPE_I8: {
3053 guint64 *p = (void*)mem;
3058 g_assert_not_reached ();
3063 ICALL_EXPORT MonoObject *
3064 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3067 MonoClass *enumc, *objc;
3072 MONO_ARCH_SAVE_REGS;
3074 MONO_CHECK_ARG_NULL (enumType);
3075 MONO_CHECK_ARG_NULL (value);
3077 domain = mono_object_domain (enumType);
3078 enumc = mono_class_from_mono_type (enumType->type);
3080 mono_class_init_or_throw (enumc);
3082 objc = value->vtable->klass;
3084 if (!enumc->enumtype)
3085 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3086 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_I1 && objc->byval_arg.type <= MONO_TYPE_U8)))
3087 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."));
3089 etype = mono_class_enum_basetype (enumc);
3091 /* MS throws this for typebuilders */
3092 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3094 res = mono_object_new (domain, enumc);
3095 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3096 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3101 ICALL_EXPORT MonoObject *
3102 ves_icall_System_Enum_get_value (MonoObject *this)
3110 MONO_ARCH_SAVE_REGS;
3115 g_assert (this->vtable->klass->enumtype);
3117 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3118 res = mono_object_new (mono_object_domain (this), enumc);
3119 dst = (char *)res + sizeof (MonoObject);
3120 src = (char *)this + sizeof (MonoObject);
3121 size = mono_class_value_size (enumc, NULL);
3123 memcpy (dst, src, size);
3128 ICALL_EXPORT MonoReflectionType *
3129 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3134 MONO_ARCH_SAVE_REGS;
3136 klass = mono_class_from_mono_type (type->type);
3137 mono_class_init_or_throw (klass);
3139 etype = mono_class_enum_basetype (klass);
3141 /* MS throws this for typebuilders */
3142 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3144 return mono_type_get_object (mono_object_domain (type), etype);
3148 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3150 gpointer tdata = (char *)this + sizeof (MonoObject);
3151 gpointer odata = (char *)other + sizeof (MonoObject);
3152 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3153 g_assert (basetype);
3155 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3156 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3157 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3160 return me > other ? 1 : -1; \
3163 switch (basetype->type) {
3165 COMPARE_ENUM_VALUES (guint8);
3167 COMPARE_ENUM_VALUES (gint8);
3168 case MONO_TYPE_CHAR:
3170 COMPARE_ENUM_VALUES (guint16);
3172 COMPARE_ENUM_VALUES (gint16);
3174 COMPARE_ENUM_VALUES (guint32);
3176 COMPARE_ENUM_VALUES (gint32);
3178 COMPARE_ENUM_VALUES (guint64);
3180 COMPARE_ENUM_VALUES (gint64);
3182 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3184 #undef COMPARE_ENUM_VALUES
3189 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3191 gpointer data = (char *)this + sizeof (MonoObject);
3192 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3193 g_assert (basetype);
3195 switch (basetype->type) {
3197 return *((gint8*)data);
3199 return *((guint8*)data);
3200 case MONO_TYPE_CHAR:
3202 return *((guint16*)data);
3205 return *((gint16*)data);
3207 return *((guint32*)data);
3209 return *((gint32*)data);
3211 case MONO_TYPE_I8: {
3212 gint64 value = *((gint64*)data);
3213 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3216 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3222 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3224 MonoDomain *domain = mono_object_domain (type);
3225 MonoClass *enumc = mono_class_from_mono_type (type->type);
3226 guint j = 0, nvalues, crow;
3228 MonoClassField *field;
3230 MONO_ARCH_SAVE_REGS;
3232 mono_class_init_or_throw (enumc);
3234 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3235 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3236 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3237 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3241 while ((field = mono_class_get_fields (enumc, &iter))) {
3244 MonoTypeEnum def_type;
3246 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3248 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3250 if (mono_field_is_deleted (field))
3252 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3254 p = mono_class_get_field_default_value (field, &def_type);
3255 len = mono_metadata_decode_blob_size (p, &p);
3256 switch (mono_class_enum_basetype (enumc)->type) {
3259 mono_array_set (info->values, gchar, j, *p);
3261 case MONO_TYPE_CHAR:
3264 mono_array_set (info->values, gint16, j, read16 (p));
3268 mono_array_set (info->values, gint32, j, read32 (p));
3272 mono_array_set (info->values, gint64, j, read64 (p));
3275 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3282 BFLAGS_IgnoreCase = 1,
3283 BFLAGS_DeclaredOnly = 2,
3284 BFLAGS_Instance = 4,
3286 BFLAGS_Public = 0x10,
3287 BFLAGS_NonPublic = 0x20,
3288 BFLAGS_FlattenHierarchy = 0x40,
3289 BFLAGS_InvokeMethod = 0x100,
3290 BFLAGS_CreateInstance = 0x200,
3291 BFLAGS_GetField = 0x400,
3292 BFLAGS_SetField = 0x800,
3293 BFLAGS_GetProperty = 0x1000,
3294 BFLAGS_SetProperty = 0x2000,
3295 BFLAGS_ExactBinding = 0x10000,
3296 BFLAGS_SuppressChangeType = 0x20000,
3297 BFLAGS_OptionalParamBinding = 0x40000
3300 ICALL_EXPORT MonoReflectionField *
3301 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3304 MonoClass *startklass, *klass;
3306 MonoClassField *field;
3309 int (*compare_func) (const char *s1, const char *s2) = NULL;
3310 domain = ((MonoObject *)type)->vtable->domain;
3311 klass = startklass = mono_class_from_mono_type (type->type);
3314 mono_raise_exception (mono_get_exception_argument_null ("name"));
3315 if (type->type->byref)
3318 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3321 if (klass->exception_type != MONO_EXCEPTION_NONE)
3322 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3325 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3326 guint32 flags = mono_field_get_flags (field);
3329 if (mono_field_is_deleted_with_flags (field, flags))
3331 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3332 if (bflags & BFLAGS_Public)
3334 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3335 if (bflags & BFLAGS_NonPublic) {
3342 if (flags & FIELD_ATTRIBUTE_STATIC) {
3343 if (bflags & BFLAGS_Static)
3344 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3347 if (bflags & BFLAGS_Instance)
3354 utf8_name = mono_string_to_utf8 (name);
3356 if (compare_func (mono_field_get_name (field), utf8_name)) {
3362 return mono_field_get_object (domain, klass, field);
3364 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3370 ICALL_EXPORT MonoArray*
3371 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3374 MonoClass *startklass, *klass, *refklass;
3379 MonoClassField *field;
3380 MonoPtrArray tmp_array;
3382 MONO_ARCH_SAVE_REGS;
3384 domain = ((MonoObject *)type)->vtable->domain;
3385 if (type->type->byref)
3386 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3387 klass = startklass = mono_class_from_mono_type (type->type);
3388 refklass = mono_class_from_mono_type (reftype->type);
3390 mono_ptr_array_init (tmp_array, 2);
3393 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3394 mono_ptr_array_destroy (tmp_array);
3395 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3399 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3400 guint32 flags = mono_field_get_flags (field);
3402 if (mono_field_is_deleted_with_flags (field, flags))
3404 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3405 if (bflags & BFLAGS_Public)
3407 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3408 if (bflags & BFLAGS_NonPublic) {
3415 if (flags & FIELD_ATTRIBUTE_STATIC) {
3416 if (bflags & BFLAGS_Static)
3417 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3420 if (bflags & BFLAGS_Instance)
3426 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3427 mono_ptr_array_append (tmp_array, member);
3429 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3432 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3434 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3435 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3437 mono_ptr_array_destroy (tmp_array);
3443 method_nonpublic (MonoMethod* method, gboolean start_klass)
3445 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3446 case METHOD_ATTRIBUTE_ASSEM:
3447 return (start_klass || mono_defaults.generic_ilist_class);
3448 case METHOD_ATTRIBUTE_PRIVATE:
3450 case METHOD_ATTRIBUTE_PUBLIC:
3458 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3461 MonoClass *startklass;
3464 int len, match, nslots;
3465 /*FIXME, use MonoBitSet*/
3466 guint32 method_slots_default [8];
3467 guint32 *method_slots = NULL;
3468 int (*compare_func) (const char *s1, const char *s2) = NULL;
3470 array = g_ptr_array_new ();
3476 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3478 /* An optimization for calls made from Delegate:CreateDelegate () */
3479 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3480 method = mono_get_delegate_invoke (klass);
3481 if (mono_loader_get_last_error ())
3484 g_ptr_array_add (array, method);
3488 mono_class_setup_vtable (klass);
3489 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3492 if (is_generic_parameter (&klass->byval_arg))
3493 nslots = mono_class_get_vtable_size (klass->parent);
3495 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3496 if (nslots >= sizeof (method_slots_default) * 8) {
3497 method_slots = g_new0 (guint32, nslots / 32 + 1);
3499 method_slots = method_slots_default;
3500 memset (method_slots, 0, sizeof (method_slots_default));
3503 mono_class_setup_vtable (klass);
3504 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3508 while ((method = mono_class_get_methods (klass, &iter))) {
3510 if (method->slot != -1) {
3511 g_assert (method->slot < nslots);
3512 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3514 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3515 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3518 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3520 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3521 if (bflags & BFLAGS_Public)
3523 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3529 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3530 if (bflags & BFLAGS_Static)
3531 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3534 if (bflags & BFLAGS_Instance)
3542 if (compare_func (name, method->name))
3547 g_ptr_array_add (array, method);
3549 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3551 if (method_slots != method_slots_default)
3552 g_free (method_slots);
3557 if (method_slots != method_slots_default)
3558 g_free (method_slots);
3559 g_ptr_array_free (array, TRUE);
3561 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3562 *ex = mono_class_get_exception_for_failure (klass);
3564 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3565 mono_loader_clear_error ();
3570 ICALL_EXPORT MonoArray*
3571 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3573 static MonoClass *MethodInfo_array;
3576 MonoVTable *array_vtable;
3577 MonoException *ex = NULL;
3578 const char *mname = NULL;
3579 GPtrArray *method_array;
3580 MonoClass *klass, *refklass;
3583 if (!MethodInfo_array) {
3584 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3585 mono_memory_barrier ();
3586 MethodInfo_array = klass;
3589 klass = mono_class_from_mono_type (type->type);
3590 refklass = mono_class_from_mono_type (reftype->type);
3591 domain = ((MonoObject *)type)->vtable->domain;
3592 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3593 if (type->type->byref)
3594 return mono_array_new_specific (array_vtable, 0);
3597 mname = mono_string_to_utf8 (name);
3599 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3600 g_free ((char*)mname);
3602 mono_raise_exception (ex);
3604 res = mono_array_new_specific (array_vtable, method_array->len);
3607 for (i = 0; i < method_array->len; ++i) {
3608 MonoMethod *method = g_ptr_array_index (method_array, i);
3609 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3612 g_ptr_array_free (method_array, TRUE);
3616 ICALL_EXPORT MonoArray*
3617 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3620 static MonoClass *System_Reflection_ConstructorInfo;
3621 MonoClass *startklass, *klass, *refklass;
3626 gpointer iter = NULL;
3627 MonoPtrArray tmp_array;
3629 MONO_ARCH_SAVE_REGS;
3631 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3633 domain = ((MonoObject *)type)->vtable->domain;
3634 if (type->type->byref)
3635 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3636 klass = startklass = mono_class_from_mono_type (type->type);
3637 refklass = mono_class_from_mono_type (reftype->type);
3639 if (!System_Reflection_ConstructorInfo)
3640 System_Reflection_ConstructorInfo = mono_class_from_name (
3641 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3644 while ((method = mono_class_get_methods (klass, &iter))) {
3646 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3648 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3649 if (bflags & BFLAGS_Public)
3652 if (bflags & BFLAGS_NonPublic)
3658 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3659 if (bflags & BFLAGS_Static)
3660 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3663 if (bflags & BFLAGS_Instance)
3669 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3671 mono_ptr_array_append (tmp_array, member);
3674 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3676 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3677 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3679 mono_ptr_array_destroy (tmp_array);
3685 property_hash (gconstpointer data)
3687 MonoProperty *prop = (MonoProperty*)data;
3689 return g_str_hash (prop->name);
3693 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3695 // Properties are hide-by-name-and-signature
3696 if (!g_str_equal (prop1->name, prop2->name))
3699 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3701 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3707 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3712 return method_nonpublic (accessor, start_klass);
3715 ICALL_EXPORT MonoArray*
3716 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3720 static MonoClass *System_Reflection_PropertyInfo;
3721 MonoClass *startklass, *klass;
3727 gchar *propname = NULL;
3728 int (*compare_func) (const char *s1, const char *s2) = NULL;
3730 GHashTable *properties = NULL;
3731 MonoPtrArray tmp_array;
3733 MONO_ARCH_SAVE_REGS;
3735 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3737 if (!System_Reflection_PropertyInfo)
3738 System_Reflection_PropertyInfo = mono_class_from_name (
3739 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3741 domain = ((MonoObject *)type)->vtable->domain;
3742 if (type->type->byref)
3743 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3744 klass = startklass = mono_class_from_mono_type (type->type);
3747 propname = mono_string_to_utf8 (name);
3748 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3751 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3753 mono_class_setup_vtable (klass);
3754 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3758 while ((prop = mono_class_get_properties (klass, &iter))) {
3764 flags = method->flags;
3767 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3768 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3769 if (bflags & BFLAGS_Public)
3771 } else if (bflags & BFLAGS_NonPublic) {
3772 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3773 property_accessor_nonpublic(prop->set, startklass == klass)) {
3780 if (flags & METHOD_ATTRIBUTE_STATIC) {
3781 if (bflags & BFLAGS_Static)
3782 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3785 if (bflags & BFLAGS_Instance)
3794 if (compare_func (propname, prop->name))
3798 if (g_hash_table_lookup (properties, prop))
3801 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3803 g_hash_table_insert (properties, prop, prop);
3805 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3808 g_hash_table_destroy (properties);
3811 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3812 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3813 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3815 mono_ptr_array_destroy (tmp_array);
3821 g_hash_table_destroy (properties);
3824 mono_ptr_array_destroy (tmp_array);
3826 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3827 ex = mono_class_get_exception_for_failure (klass);
3829 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3830 mono_loader_clear_error ();
3832 mono_raise_exception (ex);
3836 ICALL_EXPORT MonoReflectionEvent *
3837 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3840 MonoClass *klass, *startklass;
3845 int (*compare_func) (const char *s1, const char *s2);
3847 MONO_ARCH_SAVE_REGS;
3849 event_name = mono_string_to_utf8 (name);
3850 if (type->type->byref)
3852 klass = startklass = mono_class_from_mono_type (type->type);
3853 domain = mono_object_domain (type);
3855 mono_class_init_or_throw (klass);
3857 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3859 if (klass->exception_type != MONO_EXCEPTION_NONE)
3860 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3863 while ((event = mono_class_get_events (klass, &iter))) {
3864 if (compare_func (event->name, event_name))
3867 method = event->add;
3869 method = event->remove;
3871 method = event->raise;
3873 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3874 if (!(bflags & BFLAGS_Public))
3877 if (!(bflags & BFLAGS_NonPublic))
3879 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3883 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3884 if (!(bflags & BFLAGS_Static))
3886 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3889 if (!(bflags & BFLAGS_Instance))
3893 if (!(bflags & BFLAGS_NonPublic))
3896 g_free (event_name);
3897 return mono_event_get_object (domain, startklass, event);
3900 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3903 g_free (event_name);
3908 event_hash (gconstpointer data)
3910 MonoEvent *event = (MonoEvent*)data;
3912 return g_str_hash (event->name);
3916 event_equal (MonoEvent *event1, MonoEvent *event2)
3918 // Events are hide-by-name
3919 return g_str_equal (event1->name, event2->name);
3922 ICALL_EXPORT MonoArray*
3923 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3927 static MonoClass *System_Reflection_EventInfo;
3928 MonoClass *startklass, *klass;
3934 GHashTable *events = NULL;
3935 MonoPtrArray tmp_array;
3937 MONO_ARCH_SAVE_REGS;
3939 mono_ptr_array_init (tmp_array, 4);
3941 if (!System_Reflection_EventInfo)
3942 System_Reflection_EventInfo = mono_class_from_name (
3943 mono_defaults.corlib, "System.Reflection", "EventInfo");
3945 domain = mono_object_domain (type);
3946 if (type->type->byref)
3947 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3948 klass = startklass = mono_class_from_mono_type (type->type);
3950 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3952 mono_class_setup_vtable (klass);
3953 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3957 while ((event = mono_class_get_events (klass, &iter))) {
3959 method = event->add;
3961 method = event->remove;
3963 method = event->raise;
3965 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3966 if (bflags & BFLAGS_Public)
3968 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3969 if (bflags & BFLAGS_NonPublic)
3974 if (bflags & BFLAGS_NonPublic)
3980 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3981 if (bflags & BFLAGS_Static)
3982 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3985 if (bflags & BFLAGS_Instance)
3990 if (bflags & BFLAGS_Instance)
3995 if (g_hash_table_lookup (events, event))
3998 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4000 g_hash_table_insert (events, event, event);
4002 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4005 g_hash_table_destroy (events);
4007 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4009 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4010 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4012 mono_ptr_array_destroy (tmp_array);
4017 mono_ptr_array_destroy (tmp_array);
4018 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4019 ex = mono_class_get_exception_for_failure (klass);
4021 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4022 mono_loader_clear_error ();
4024 mono_raise_exception (ex);
4028 ICALL_EXPORT MonoReflectionType *
4029 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4037 MONO_ARCH_SAVE_REGS;
4040 mono_raise_exception (mono_get_exception_argument_null ("name"));
4042 domain = ((MonoObject *)type)->vtable->domain;
4043 if (type->type->byref)
4045 klass = mono_class_from_mono_type (type->type);
4047 str = mono_string_to_utf8 (name);
4050 if (klass->exception_type != MONO_EXCEPTION_NONE)
4051 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4054 * If a nested type is generic, return its generic type definition.
4055 * Note that this means that the return value is essentially a
4056 * nested type of the generic type definition of @klass.
4058 * A note in MSDN claims that a generic type definition can have
4059 * nested types that aren't generic. In any case, the container of that
4060 * nested type would be the generic type definition.
4062 if (klass->generic_class)
4063 klass = klass->generic_class->container_class;
4066 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4068 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4069 if (bflags & BFLAGS_Public)
4072 if (bflags & BFLAGS_NonPublic)
4077 if (strcmp (nested->name, str) == 0){
4079 return mono_type_get_object (domain, &nested->byval_arg);
4082 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4088 ICALL_EXPORT MonoArray*
4089 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4098 MonoPtrArray tmp_array;
4100 MONO_ARCH_SAVE_REGS;
4102 domain = ((MonoObject *)type)->vtable->domain;
4103 if (type->type->byref)
4104 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4105 klass = mono_class_from_mono_type (type->type);
4108 * If a nested type is generic, return its generic type definition.
4109 * Note that this means that the return value is essentially the set
4110 * of nested types of the generic type definition of @klass.
4112 * A note in MSDN claims that a generic type definition can have
4113 * nested types that aren't generic. In any case, the container of that
4114 * nested type would be the generic type definition.
4116 if (klass->generic_class)
4117 klass = klass->generic_class->container_class;
4119 mono_ptr_array_init (tmp_array, 1);
4121 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4123 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4124 if (bflags & BFLAGS_Public)
4127 if (bflags & BFLAGS_NonPublic)
4132 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4133 mono_ptr_array_append (tmp_array, member);
4136 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4138 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4139 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4141 mono_ptr_array_destroy (tmp_array);
4146 ICALL_EXPORT MonoReflectionType*
4147 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4150 MonoType *type = NULL;
4151 MonoTypeNameParse info;
4152 gboolean type_resolve;
4154 MONO_ARCH_SAVE_REGS;
4156 /* On MS.NET, this does not fire a TypeResolve event */
4157 type_resolve = TRUE;
4158 str = mono_string_to_utf8 (name);
4159 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4160 if (!mono_reflection_parse_type (str, &info)) {
4162 mono_reflection_free_type_info (&info);
4163 if (throwOnError) /* uhm: this is a parse error, though... */
4164 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4165 /*g_print ("failed parse\n");*/
4169 if (info.assembly.name) {
4171 mono_reflection_free_type_info (&info);
4173 /* 1.0 and 2.0 throw different exceptions */
4174 if (mono_defaults.generic_ilist_class)
4175 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4177 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4182 if (module != NULL) {
4184 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4189 if (assembly_is_dynamic (assembly->assembly)) {
4190 /* Enumerate all modules */
4191 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4195 if (abuilder->modules) {
4196 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4197 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4198 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4204 if (!type && abuilder->loaded_modules) {
4205 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4206 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4207 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4214 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4216 mono_reflection_free_type_info (&info);
4218 MonoException *e = NULL;
4221 e = mono_get_exception_type_load (name, NULL);
4223 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4224 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4226 mono_loader_clear_error ();
4229 mono_raise_exception (e);
4232 } else if (mono_loader_get_last_error ()) {
4234 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4235 mono_loader_clear_error ();
4238 if (type->type == MONO_TYPE_CLASS) {
4239 MonoClass *klass = mono_type_get_class (type);
4241 if (mono_security_enabled () && !klass->exception_type)
4242 /* Some security problems are detected during generic vtable construction */
4243 mono_class_setup_vtable (klass);
4245 /* need to report exceptions ? */
4246 if (throwOnError && klass->exception_type) {
4247 /* report SecurityException (or others) that occured when loading the assembly */
4248 MonoException *exc = mono_class_get_exception_for_failure (klass);
4249 mono_loader_clear_error ();
4250 mono_raise_exception (exc);
4251 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4256 /* g_print ("got it\n"); */
4257 return mono_type_get_object (mono_object_domain (assembly), type);
4261 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4264 gchar *shadow_ini_file;
4267 /* Check for shadow-copied assembly */
4268 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4269 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4271 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4272 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4278 g_free (shadow_ini_file);
4279 if (content != NULL) {
4282 *filename = content;
4289 ICALL_EXPORT MonoString *
4290 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4292 MonoDomain *domain = mono_object_domain (assembly);
4293 MonoAssembly *mass = assembly->assembly;
4294 MonoString *res = NULL;
4299 MONO_ARCH_SAVE_REGS;
4301 if (g_path_is_absolute (mass->image->name)) {
4302 absolute = g_strdup (mass->image->name);
4303 dirname = g_path_get_dirname (absolute);
4305 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4306 dirname = g_strdup (mass->basedir);
4309 replace_shadow_path (domain, dirname, &absolute);
4314 for (i = strlen (absolute) - 1; i >= 0; i--)
4315 if (absolute [i] == '\\')
4320 uri = g_filename_to_uri (absolute, NULL, NULL);
4322 const char *prepend = "file://";
4324 if (*absolute == '/' && *(absolute + 1) == '/') {
4327 prepend = "file:///";
4330 uri = g_strconcat (prepend, absolute, NULL);
4334 res = mono_string_new (domain, uri);
4341 ICALL_EXPORT MonoBoolean
4342 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4344 MonoAssembly *mass = assembly->assembly;
4346 MONO_ARCH_SAVE_REGS;
4348 return mass->in_gac;
4351 ICALL_EXPORT MonoReflectionAssembly*
4352 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4356 MonoImageOpenStatus status;
4358 MONO_ARCH_SAVE_REGS;
4360 name = mono_string_to_utf8 (mname);
4361 res = mono_assembly_load_with_partial_name (name, &status);
4367 return mono_assembly_get_object (mono_domain_get (), res);
4370 ICALL_EXPORT MonoString *
4371 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4373 MonoDomain *domain = mono_object_domain (assembly);
4376 MONO_ARCH_SAVE_REGS;
4378 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4383 ICALL_EXPORT MonoBoolean
4384 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4386 MONO_ARCH_SAVE_REGS;
4388 return assembly->assembly->ref_only;
4391 ICALL_EXPORT MonoString *
4392 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4394 MonoDomain *domain = mono_object_domain (assembly);
4396 MONO_ARCH_SAVE_REGS;
4398 return mono_string_new (domain, assembly->assembly->image->version);
4401 ICALL_EXPORT MonoReflectionMethod*
4402 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4404 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4406 MONO_ARCH_SAVE_REGS;
4410 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4413 ICALL_EXPORT MonoReflectionModule*
4414 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4416 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4419 ICALL_EXPORT MonoArray*
4420 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4422 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4423 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4427 MONO_ARCH_SAVE_REGS;
4429 for (i = 0; i < table->rows; ++i) {
4430 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4431 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4437 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4439 static MonoClass *System_Version = NULL;
4440 static MonoMethod *create_version = NULL;
4444 if (!System_Version) {
4445 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4446 g_assert (System_Version);
4449 if (!create_version) {
4450 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4451 create_version = mono_method_desc_search_in_class (desc, System_Version);
4452 g_assert (create_version);
4453 mono_method_desc_free (desc);
4459 args [3] = &revision;
4460 result = mono_object_new (domain, System_Version);
4461 mono_runtime_invoke (create_version, result, args, NULL);
4466 ICALL_EXPORT MonoArray*
4467 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4469 static MonoClass *System_Reflection_AssemblyName;
4471 MonoDomain *domain = mono_object_domain (assembly);
4473 static MonoMethod *create_culture = NULL;
4474 MonoImage *image = assembly->assembly->image;
4477 MONO_ARCH_SAVE_REGS;
4479 if (!System_Reflection_AssemblyName)
4480 System_Reflection_AssemblyName = mono_class_from_name (
4481 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4483 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4486 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4488 if (count > 0 && !create_culture) {
4489 MonoMethodDesc *desc = mono_method_desc_new (
4490 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4491 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4492 g_assert (create_culture);
4493 mono_method_desc_free (desc);
4496 for (i = 0; i < count; i++) {
4497 MonoReflectionAssemblyName *aname;
4498 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4500 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4502 aname = (MonoReflectionAssemblyName *) mono_object_new (
4503 domain, System_Reflection_AssemblyName);
4505 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4507 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4508 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4509 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4510 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4511 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4512 aname->versioncompat = 1; /* SameMachine (default) */
4513 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4514 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4516 if (create_culture) {
4518 MonoBoolean assembly_ref = 1;
4519 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4520 args [1] = &assembly_ref;
4521 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4524 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4525 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4526 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4528 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4529 /* public key token isn't copied - the class library will
4530 automatically generate it from the public key if required */
4531 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4532 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4534 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4535 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4538 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4541 /* note: this function doesn't return the codebase on purpose (i.e. it can
4542 be used under partial trust as path information isn't present). */
4544 mono_array_setref (result, i, aname);
4549 /* move this in some file in mono/util/ */
4551 g_concat_dir_and_file (const char *dir, const char *file)
4553 g_return_val_if_fail (dir != NULL, NULL);
4554 g_return_val_if_fail (file != NULL, NULL);
4557 * If the directory name doesn't have a / on the end, we need
4558 * to add one so we get a proper path to the file
4560 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4561 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4563 return g_strconcat (dir, file, NULL);
4567 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4569 char *n = mono_string_to_utf8 (name);
4570 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4572 guint32 cols [MONO_MANIFEST_SIZE];
4573 guint32 impl, file_idx;
4577 MONO_ARCH_SAVE_REGS;
4579 for (i = 0; i < table->rows; ++i) {
4580 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4581 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4582 if (strcmp (val, n) == 0)
4586 if (i == table->rows)
4589 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4592 * this code should only be called after obtaining the
4593 * ResourceInfo and handling the other cases.
4595 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4596 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4598 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4603 module = assembly->assembly->image;
4605 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4607 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4610 ICALL_EXPORT gboolean
4611 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4613 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4615 guint32 cols [MONO_MANIFEST_SIZE];
4616 guint32 file_cols [MONO_FILE_SIZE];
4620 MONO_ARCH_SAVE_REGS;
4622 n = mono_string_to_utf8 (name);
4623 for (i = 0; i < table->rows; ++i) {
4624 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4625 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4626 if (strcmp (val, n) == 0)
4630 if (i == table->rows)
4633 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4634 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4637 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4638 case MONO_IMPLEMENTATION_FILE:
4639 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4640 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4641 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4642 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4643 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4644 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4647 info->location = RESOURCE_LOCATION_EMBEDDED;
4650 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4651 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4652 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4653 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4654 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4655 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4657 mono_raise_exception (ex);
4659 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4661 /* Obtain info recursively */
4662 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4663 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4666 case MONO_IMPLEMENTATION_EXP_TYPE:
4667 g_assert_not_reached ();
4675 ICALL_EXPORT MonoObject*
4676 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4678 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4679 MonoArray *result = NULL;
4684 MONO_ARCH_SAVE_REGS;
4686 /* check hash if needed */
4688 n = mono_string_to_utf8 (name);
4689 for (i = 0; i < table->rows; ++i) {
4690 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4691 if (strcmp (val, n) == 0) {
4694 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4695 fn = mono_string_new (mono_object_domain (assembly), n);
4697 return (MonoObject*)fn;
4705 for (i = 0; i < table->rows; ++i) {
4706 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4710 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4713 for (i = 0; i < table->rows; ++i) {
4714 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4715 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4716 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4717 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4722 return (MonoObject*)result;
4725 ICALL_EXPORT MonoArray*
4726 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4728 MonoDomain *domain = mono_domain_get();
4731 int i, j, file_count = 0;
4732 MonoImage **modules;
4733 guint32 module_count, real_module_count;
4734 MonoTableInfo *table;
4735 guint32 cols [MONO_FILE_SIZE];
4736 MonoImage *image = assembly->assembly->image;
4738 g_assert (image != NULL);
4739 g_assert (!assembly_is_dynamic (assembly->assembly));
4741 table = &image->tables [MONO_TABLE_FILE];
4742 file_count = table->rows;
4744 modules = image->modules;
4745 module_count = image->module_count;
4747 real_module_count = 0;
4748 for (i = 0; i < module_count; ++i)
4750 real_module_count ++;
4752 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4753 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4755 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4757 for (i = 0; i < module_count; ++i)
4759 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4763 for (i = 0; i < file_count; ++i, ++j) {
4764 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4765 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4766 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4768 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4770 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4771 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4773 mono_array_setref (res, j, mono_module_get_object (domain, m));
4780 ICALL_EXPORT MonoReflectionMethod*
4781 ves_icall_GetCurrentMethod (void)
4783 MonoMethod *m = mono_method_get_last_managed ();
4785 while (m->is_inflated)
4786 m = ((MonoMethodInflated*)m)->declaring;
4788 return mono_method_get_object (mono_domain_get (), m, NULL);
4793 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4796 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4797 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4798 //method is inflated, we should inflate it on the other class
4799 MonoGenericContext ctx;
4800 ctx.method_inst = inflated->context.method_inst;
4801 ctx.class_inst = inflated->context.class_inst;
4802 if (klass->generic_class)
4803 ctx.class_inst = klass->generic_class->context.class_inst;
4804 else if (klass->generic_container)
4805 ctx.class_inst = klass->generic_container->context.class_inst;
4806 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4809 mono_class_setup_methods (method->klass);
4810 if (method->klass->exception_type)
4812 for (i = 0; i < method->klass->method.count; ++i) {
4813 if (method->klass->methods [i] == method) {
4818 mono_class_setup_methods (klass);
4819 if (klass->exception_type)
4821 g_assert (offset >= 0 && offset < klass->method.count);
4822 return klass->methods [offset];
4825 ICALL_EXPORT MonoReflectionMethod*
4826 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4830 klass = mono_class_from_mono_type (type);
4831 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4833 if (method->klass != klass) {
4834 method = mono_method_get_equivalent_method (method, klass);
4839 klass = method->klass;
4840 return mono_method_get_object (mono_domain_get (), method, klass);
4843 ICALL_EXPORT MonoReflectionMethod*
4844 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4846 return mono_method_get_object (mono_domain_get (), method, NULL);
4849 ICALL_EXPORT MonoReflectionMethodBody*
4850 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4852 return mono_method_body_get_object (mono_domain_get (), method);
4855 ICALL_EXPORT MonoReflectionAssembly*
4856 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4858 MonoMethod *dest = NULL;
4860 MONO_ARCH_SAVE_REGS;
4862 mono_stack_walk_no_il (get_executing, &dest);
4864 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4868 ICALL_EXPORT MonoReflectionAssembly*
4869 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4871 MonoDomain* domain = mono_domain_get ();
4873 MONO_ARCH_SAVE_REGS;
4875 if (!domain->entry_assembly)
4878 return mono_assembly_get_object (domain, domain->entry_assembly);
4881 ICALL_EXPORT MonoReflectionAssembly*
4882 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4887 MONO_ARCH_SAVE_REGS;
4890 mono_stack_walk_no_il (get_executing, &dest);
4892 mono_stack_walk_no_il (get_caller, &dest);
4895 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4898 ICALL_EXPORT MonoString *
4899 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4900 gboolean assembly_qualified)
4902 MonoDomain *domain = mono_object_domain (object);
4903 MonoTypeNameFormat format;
4908 format = assembly_qualified ?
4909 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4910 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4912 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4914 name = mono_type_get_name_full (object->type, format);
4918 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4923 res = mono_string_new (domain, name);
4930 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4932 MonoClass *klass = mono_class_from_mono_type (this->type);
4933 mono_class_init_or_throw (klass);
4934 return mono_security_core_clr_class_level (klass);
4938 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4940 static MonoMethod *create_culture = NULL;
4943 const char *pkey_ptr;
4945 MonoBoolean assembly_ref = 0;
4947 MONO_ARCH_SAVE_REGS;
4949 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4950 aname->major = name->major;
4951 aname->minor = name->minor;
4952 aname->build = name->build;
4953 aname->flags = name->flags;
4954 aname->revision = name->revision;
4955 aname->hashalg = name->hash_alg;
4956 aname->versioncompat = 1; /* SameMachine (default) */
4957 aname->processor_architecture = name->arch;
4959 if (by_default_version)
4960 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4963 if (absolute != NULL && *absolute != '\0') {
4964 const gchar *prepend = "file://";
4967 codebase = g_strdup (absolute);
4972 for (i = strlen (codebase) - 1; i >= 0; i--)
4973 if (codebase [i] == '\\')
4976 if (*codebase == '/' && *(codebase + 1) == '/') {
4979 prepend = "file:///";
4983 result = g_strconcat (prepend, codebase, NULL);
4989 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
4993 if (!create_culture) {
4994 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4995 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4996 g_assert (create_culture);
4997 mono_method_desc_free (desc);
5000 if (name->culture) {
5001 args [0] = mono_string_new (domain, name->culture);
5002 args [1] = &assembly_ref;
5003 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5006 if (name->public_key) {
5007 pkey_ptr = (char*)name->public_key;
5008 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5010 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5011 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5012 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5013 } else if (default_publickey) {
5014 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5015 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5018 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5019 if (name->public_key_token [0]) {
5023 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5024 p = mono_array_addr (aname->keyToken, char, 0);
5026 for (i = 0, j = 0; i < 8; i++) {
5027 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5028 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5031 } else if (default_token) {
5032 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5036 ICALL_EXPORT MonoString *
5037 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5039 MonoDomain *domain = mono_object_domain (assembly);
5040 MonoAssembly *mass = assembly->assembly;
5044 name = mono_stringify_assembly_name (&mass->aname);
5045 res = mono_string_new (domain, name);
5052 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5055 MonoAssembly *mass = assembly->assembly;
5057 MONO_ARCH_SAVE_REGS;
5059 if (g_path_is_absolute (mass->image->name)) {
5060 fill_reflection_assembly_name (mono_object_domain (assembly),
5061 aname, &mass->aname, mass->image->name, TRUE,
5065 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5067 fill_reflection_assembly_name (mono_object_domain (assembly),
5068 aname, &mass->aname, absolute, TRUE, TRUE,
5075 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5078 MonoImageOpenStatus status = MONO_IMAGE_OK;
5081 MonoAssemblyName name;
5084 MONO_ARCH_SAVE_REGS;
5086 filename = mono_string_to_utf8 (fname);
5088 dirname = g_path_get_dirname (filename);
5089 replace_shadow_path (mono_domain_get (), dirname, &filename);
5092 image = mono_image_open (filename, &status);
5098 if (status == MONO_IMAGE_IMAGE_INVALID)
5099 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5101 exc = mono_get_exception_file_not_found2 (NULL, fname);
5102 mono_raise_exception (exc);
5105 res = mono_assembly_fill_assembly_name (image, &name);
5107 mono_image_close (image);
5109 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5112 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5116 mono_image_close (image);
5119 ICALL_EXPORT MonoBoolean
5120 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5121 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5123 MonoBoolean result = FALSE;
5124 MonoDeclSecurityEntry entry;
5126 /* SecurityAction.RequestMinimum */
5127 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5128 *minimum = entry.blob;
5129 *minLength = entry.size;
5132 /* SecurityAction.RequestOptional */
5133 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5134 *optional = entry.blob;
5135 *optLength = entry.size;
5138 /* SecurityAction.RequestRefuse */
5139 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5140 *refused = entry.blob;
5141 *refLength = entry.size;
5149 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5153 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5155 guint32 attrs, visibility;
5157 /* we start the count from 1 because we skip the special type <Module> */
5160 for (i = 1; i < tdef->rows; ++i) {
5161 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5162 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5163 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5167 count = tdef->rows - 1;
5169 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5170 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5172 for (i = 1; i < tdef->rows; ++i) {
5173 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5174 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5175 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5177 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5178 g_assert (!mono_loader_get_last_error ()); /* Plug any leaks */
5181 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5183 MonoException *ex = mono_error_convert_to_exception (&error);
5184 mono_array_setref (*exceptions, count, ex);
5193 ICALL_EXPORT MonoArray*
5194 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5196 MonoArray *res = NULL;
5197 MonoArray *exceptions = NULL;
5198 MonoImage *image = NULL;
5199 MonoTableInfo *table = NULL;
5202 int i, len, ex_count;
5204 MONO_ARCH_SAVE_REGS;
5206 domain = mono_object_domain (assembly);
5208 g_assert (!assembly_is_dynamic (assembly->assembly));
5209 image = assembly->assembly->image;
5210 table = &image->tables [MONO_TABLE_FILE];
5211 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5213 /* Append data from all modules in the assembly */
5214 for (i = 0; i < table->rows; ++i) {
5215 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5216 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5219 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5220 /* Append the new types to the end of the array */
5221 if (mono_array_length (res2) > 0) {
5223 MonoArray *res3, *ex3;
5225 len1 = mono_array_length (res);
5226 len2 = mono_array_length (res2);
5228 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5229 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5230 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5233 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5234 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5235 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5242 /* the ReflectionTypeLoadException must have all the types (Types property),
5243 * NULL replacing types which throws an exception. The LoaderException must
5244 * contain all exceptions for NULL items.
5247 len = mono_array_length (res);
5250 for (i = 0; i < len; i++) {
5251 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5255 klass = mono_type_get_class (t->type);
5256 if ((klass != NULL) && klass->exception_type) {
5257 /* keep the class in the list */
5258 list = g_list_append (list, klass);
5259 /* and replace Type with NULL */
5260 mono_array_setref (res, i, NULL);
5267 if (list || ex_count) {
5269 MonoException *exc = NULL;
5270 MonoArray *exl = NULL;
5271 int j, length = g_list_length (list) + ex_count;
5273 mono_loader_clear_error ();
5275 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5276 /* Types for which mono_class_get_checked () succeeded */
5277 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5278 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5279 mono_array_setref (exl, i, exc);
5281 /* Types for which it don't */
5282 for (j = 0; j < mono_array_length (exceptions); ++j) {
5283 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5285 g_assert (i < length);
5286 mono_array_setref (exl, i, exc);
5293 exc = mono_get_exception_reflection_type_load (res, exl);
5294 mono_loader_clear_error ();
5295 mono_raise_exception (exc);
5301 ICALL_EXPORT gboolean
5302 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5304 MonoAssemblyName aname;
5305 MonoDomain *domain = mono_object_domain (name);
5307 gboolean is_version_defined;
5308 gboolean is_token_defined;
5310 aname.public_key = NULL;
5311 val = mono_string_to_utf8 (assname);
5312 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5313 g_free ((guint8*) aname.public_key);
5318 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5319 FALSE, is_token_defined);
5321 mono_assembly_name_free (&aname);
5322 g_free ((guint8*) aname.public_key);
5328 ICALL_EXPORT MonoReflectionType*
5329 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5332 MonoDomain *domain = mono_object_domain (module);
5335 MONO_ARCH_SAVE_REGS;
5337 g_assert (module->image);
5339 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5340 /* These images do not have a global type */
5343 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5344 mono_error_raise_exception (&error);
5345 return mono_type_get_object (domain, &klass->byval_arg);
5349 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5351 /*if (module->image)
5352 mono_image_close (module->image);*/
5355 ICALL_EXPORT MonoString*
5356 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5358 MonoDomain *domain = mono_object_domain (module);
5360 MONO_ARCH_SAVE_REGS;
5362 g_assert (module->image);
5363 return mono_string_new (domain, module->image->guid);
5366 ICALL_EXPORT gpointer
5367 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5370 if (module->image && module->image->is_module_handle)
5371 return module->image->raw_data;
5374 return (gpointer) (-1);
5378 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5380 if (image_is_dynamic (image)) {
5381 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5382 *pe_kind = dyn->pe_kind;
5383 *machine = dyn->machine;
5386 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5387 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5392 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5394 return (image->md_version_major << 16) | (image->md_version_minor);
5397 ICALL_EXPORT MonoArray*
5398 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5400 MonoArray *exceptions;
5403 MONO_ARCH_SAVE_REGS;
5406 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5408 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5409 for (i = 0; i < mono_array_length (exceptions); ++i) {
5410 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5412 mono_raise_exception (ex);
5419 mono_memberref_is_method (MonoImage *image, guint32 token)
5421 if (!image_is_dynamic (image)) {
5422 guint32 cols [MONO_MEMBERREF_SIZE];
5424 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5425 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5426 mono_metadata_decode_blob_size (sig, &sig);
5427 return (*sig != 0x6);
5429 MonoClass *handle_class;
5431 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5434 return mono_defaults.methodhandle_class == handle_class;
5439 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5442 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5443 mono_array_addr (type_args, MonoType*, 0));
5445 context->class_inst = NULL;
5447 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5448 mono_array_addr (method_args, MonoType*, 0));
5450 context->method_inst = NULL;
5453 ICALL_EXPORT MonoType*
5454 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5457 int table = mono_metadata_token_table (token);
5458 int index = mono_metadata_token_index (token);
5459 MonoGenericContext context;
5462 *resolve_error = ResolveTokenError_Other;
5464 /* Validate token */
5465 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5466 (table != MONO_TABLE_TYPESPEC)) {
5467 *resolve_error = ResolveTokenError_BadTable;
5471 if (image_is_dynamic (image)) {
5472 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5473 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5474 return klass ? &klass->byval_arg : NULL;
5477 init_generic_context_from_args (&context, type_args, method_args);
5478 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5479 return klass ? &klass->byval_arg : NULL;
5482 if ((index <= 0) || (index > image->tables [table].rows)) {
5483 *resolve_error = ResolveTokenError_OutOfRange;
5487 init_generic_context_from_args (&context, type_args, method_args);
5488 klass = mono_class_get_checked (image, token, &error);
5490 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5491 mono_error_raise_exception (&error);
5494 return &klass->byval_arg;
5499 ICALL_EXPORT MonoMethod*
5500 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5502 int table = mono_metadata_token_table (token);
5503 int index = mono_metadata_token_index (token);
5504 MonoGenericContext context;
5507 *error = ResolveTokenError_Other;
5509 /* Validate token */
5510 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5511 (table != MONO_TABLE_MEMBERREF)) {
5512 *error = ResolveTokenError_BadTable;
5516 if (image_is_dynamic (image)) {
5517 if (table == MONO_TABLE_METHOD)
5518 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5520 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5521 *error = ResolveTokenError_BadTable;
5525 init_generic_context_from_args (&context, type_args, method_args);
5526 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5529 if ((index <= 0) || (index > image->tables [table].rows)) {
5530 *error = ResolveTokenError_OutOfRange;
5533 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5534 *error = ResolveTokenError_BadTable;
5538 init_generic_context_from_args (&context, type_args, method_args);
5539 method = mono_get_method_full (image, token, NULL, &context);
5541 if (mono_loader_get_last_error ())
5542 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5547 ICALL_EXPORT MonoString*
5548 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5550 int index = mono_metadata_token_index (token);
5552 *error = ResolveTokenError_Other;
5554 /* Validate token */
5555 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5556 *error = ResolveTokenError_BadTable;
5560 if (image_is_dynamic (image))
5561 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5563 if ((index <= 0) || (index >= image->heap_us.size)) {
5564 *error = ResolveTokenError_OutOfRange;
5568 /* FIXME: What to do if the index points into the middle of a string ? */
5570 return mono_ldstr (mono_domain_get (), image, index);
5573 ICALL_EXPORT MonoClassField*
5574 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5578 int table = mono_metadata_token_table (token);
5579 int index = mono_metadata_token_index (token);
5580 MonoGenericContext context;
5581 MonoClassField *field;
5583 *resolve_error = ResolveTokenError_Other;
5585 /* Validate token */
5586 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5587 *resolve_error = ResolveTokenError_BadTable;
5591 if (image_is_dynamic (image)) {
5592 if (table == MONO_TABLE_FIELD)
5593 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5595 if (mono_memberref_is_method (image, token)) {
5596 *resolve_error = ResolveTokenError_BadTable;
5600 init_generic_context_from_args (&context, type_args, method_args);
5601 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5604 if ((index <= 0) || (index > image->tables [table].rows)) {
5605 *resolve_error = ResolveTokenError_OutOfRange;
5608 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5609 *resolve_error = ResolveTokenError_BadTable;
5613 init_generic_context_from_args (&context, type_args, method_args);
5614 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5615 mono_error_raise_exception (&error);
5621 ICALL_EXPORT MonoObject*
5622 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5624 int table = mono_metadata_token_table (token);
5626 *error = ResolveTokenError_Other;
5629 case MONO_TABLE_TYPEDEF:
5630 case MONO_TABLE_TYPEREF:
5631 case MONO_TABLE_TYPESPEC: {
5632 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5634 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5638 case MONO_TABLE_METHOD:
5639 case MONO_TABLE_METHODSPEC: {
5640 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5642 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5646 case MONO_TABLE_FIELD: {
5647 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5649 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5653 case MONO_TABLE_MEMBERREF:
5654 if (mono_memberref_is_method (image, token)) {
5655 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5657 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5662 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5664 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5671 *error = ResolveTokenError_BadTable;
5677 ICALL_EXPORT MonoArray*
5678 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5680 int table = mono_metadata_token_table (token);
5681 int idx = mono_metadata_token_index (token);
5682 MonoTableInfo *tables = image->tables;
5687 *error = ResolveTokenError_OutOfRange;
5689 /* FIXME: Support other tables ? */
5690 if (table != MONO_TABLE_STANDALONESIG)
5693 if (image_is_dynamic (image))
5696 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5699 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5701 ptr = mono_metadata_blob_heap (image, sig);
5702 len = mono_metadata_decode_blob_size (ptr, &ptr);
5704 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5705 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5709 ICALL_EXPORT MonoReflectionType*
5710 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5713 int isbyref = 0, rank;
5714 char *str = mono_string_to_utf8 (smodifiers);
5717 MONO_ARCH_SAVE_REGS;
5719 klass = mono_class_from_mono_type (tb->type.type);
5721 /* logic taken from mono_reflection_parse_type(): keep in sync */
5725 if (isbyref) { /* only one level allowed by the spec */
5732 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5735 klass = mono_ptr_class_get (&klass->byval_arg);
5736 mono_class_init (klass);
5747 else if (*p != '*') { /* '*' means unknown lower bound */
5758 klass = mono_array_class_get (klass, rank);
5759 mono_class_init (klass);
5766 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5769 ICALL_EXPORT MonoBoolean
5770 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5775 MONO_ARCH_SAVE_REGS;
5778 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5784 check_for_invalid_type (MonoClass *klass)
5788 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5791 name = mono_type_get_full_name (klass);
5792 str = mono_string_new (mono_domain_get (), name);
5794 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5797 ICALL_EXPORT MonoReflectionType *
5798 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5800 MonoClass *klass, *aklass;
5802 MONO_ARCH_SAVE_REGS;
5804 klass = mono_class_from_mono_type (type->type);
5805 check_for_invalid_type (klass);
5807 if (rank == 0) //single dimentional array
5808 aklass = mono_array_class_get (klass, 1);
5810 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5812 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5815 ICALL_EXPORT MonoReflectionType *
5816 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5820 MONO_ARCH_SAVE_REGS;
5822 klass = mono_class_from_mono_type (type->type);
5823 mono_class_init_or_throw (klass);
5824 check_for_invalid_type (klass);
5826 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5829 ICALL_EXPORT MonoReflectionType *
5830 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5832 MonoClass *klass, *pklass;
5834 klass = mono_class_from_mono_type (type->type);
5835 mono_class_init_or_throw (klass);
5836 check_for_invalid_type (klass);
5838 pklass = mono_ptr_class_get (type->type);
5840 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5843 ICALL_EXPORT MonoObject *
5844 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5845 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5847 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5848 MonoObject *delegate;
5850 MonoMethod *method = info->method;
5852 MONO_ARCH_SAVE_REGS;
5854 mono_class_init_or_throw (delegate_class);
5856 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5858 if (mono_security_core_clr_enabled ()) {
5859 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5863 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5865 if (method_is_dynamic (method)) {
5866 /* Creating a trampoline would leak memory */
5867 func = mono_compile_method (method);
5869 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5870 method = mono_object_get_virtual_method (target, method);
5871 func = mono_create_ftnptr (mono_domain_get (),
5872 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5875 mono_delegate_ctor_with_method (delegate, target, func, method);
5881 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5883 /* Reset the invoke impl to the default one */
5884 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5888 * Magic number to convert a time which is relative to
5889 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5891 #define EPOCH_ADJUST ((guint64)62135596800LL)
5894 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5896 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5899 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5901 convert_to_absolute_date(SYSTEMTIME *date)
5903 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5904 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5905 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5906 /* from the calendar FAQ */
5907 int a = (14 - date->wMonth) / 12;
5908 int y = date->wYear - a;
5909 int m = date->wMonth + 12 * a - 2;
5910 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5912 /* d is now the day of the week for the first of the month (0 == Sunday) */
5914 int day_of_week = date->wDayOfWeek;
5916 /* set day_in_month to the first day in the month which falls on day_of_week */
5917 int day_in_month = 1 + (day_of_week - d);
5918 if (day_in_month <= 0)
5921 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5922 date->wDay = day_in_month + (date->wDay - 1) * 7;
5923 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5930 * Return's the offset from GMT of a local time.
5932 * tm is a local time
5933 * t is the same local time as seconds.
5936 gmt_offset(struct tm *tm, time_t t)
5938 #if defined (HAVE_TM_GMTOFF)
5939 return tm->tm_gmtoff;
5944 g.tm_isdst = tm->tm_isdst;
5946 return (int)difftime(t, t2);
5951 * This is heavily based on zdump.c from glibc 2.2.
5953 * * data[0]: start of daylight saving time (in DateTime ticks).
5954 * * data[1]: end of daylight saving time (in DateTime ticks).
5955 * * data[2]: utcoffset (in TimeSpan ticks).
5956 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5957 * * name[0]: name of this timezone when not daylight saving.
5958 * * name[1]: name of this timezone when daylight saving.
5960 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5961 * the class library allows years between 1 and 9999.
5963 * Returns true on success and zero on failure.
5965 ICALL_EXPORT guint32
5966 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5969 MonoDomain *domain = mono_domain_get ();
5970 struct tm start, tt;
5973 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5974 int day, transitioned;
5977 gmtoff_st = gmtoff_ds = transitioned = 0;
5979 MONO_ARCH_SAVE_REGS;
5981 MONO_CHECK_ARG_NULL (data);
5982 MONO_CHECK_ARG_NULL (names);
5984 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5985 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5988 * no info is better than crashing: we'll need our own tz data
5989 * to make this work properly, anyway. The range is probably
5990 * reduced to 1970 .. 2037 because that is what mktime is
5991 * guaranteed to support (we get into an infinite loop
5995 memset (&start, 0, sizeof (start));
5998 start.tm_year = year-1900;
6000 t = mktime (&start);
6002 if ((year < 1970) || (year > 2037) || (t == -1)) {
6004 tt = *localtime (&t);
6005 strftime (tzone, sizeof (tzone), "%Z", &tt);
6006 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6007 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6011 gmtoff = gmt_offset (&start, t);
6013 /* For each day of the year, calculate the tm_gmtoff. */
6014 for (day = 0; day < 365 && transitioned < 2; day++) {
6017 tt = *localtime (&t);
6019 gmtoff_after = gmt_offset(&tt, t);
6021 /* Daylight saving starts or ends here. */
6022 if (gmtoff_after != gmtoff) {
6026 /* Try to find the exact hour when daylight saving starts/ends. */
6030 tt1 = *localtime (&t1);
6031 } while (gmt_offset (&tt1, t1) != gmtoff);
6033 /* Try to find the exact minute when daylight saving starts/ends. */
6036 tt1 = *localtime (&t1);
6037 } while (gmt_offset (&tt1, t1) == gmtoff);
6039 strftime (tzone, sizeof (tzone), "%Z", &tt);
6041 /* Write data, if we're already in daylight saving, we're done. */
6043 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6044 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6045 if (gmtoff_ds == 0) {
6047 gmtoff_ds = gmtoff_after;
6054 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6055 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6056 if (gmtoff_ds == 0) {
6057 gmtoff_st = gmtoff_after;
6063 /* This is only set once when we enter daylight saving. */
6065 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6066 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6068 gmtoff = gmt_offset (&tt, t);
6072 if (transitioned < 2) {
6073 strftime (tzone, sizeof (tzone), "%Z", &tt);
6074 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6075 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6076 mono_array_set ((*data), gint64, 0, 0);
6077 mono_array_set ((*data), gint64, 1, 0);
6078 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6079 mono_array_set ((*data), gint64, 3, 0);
6084 MonoDomain *domain = mono_domain_get ();
6085 TIME_ZONE_INFORMATION tz_info;
6090 tz_id = GetTimeZoneInformation (&tz_info);
6091 if (tz_id == TIME_ZONE_ID_INVALID)
6094 MONO_CHECK_ARG_NULL (data);
6095 MONO_CHECK_ARG_NULL (names);
6097 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6098 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6100 for (i = 0; i < 32; ++i)
6101 if (!tz_info.DaylightName [i])
6103 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6104 for (i = 0; i < 32; ++i)
6105 if (!tz_info.StandardName [i])
6107 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6109 if ((year <= 1601) || (year > 30827)) {
6111 * According to MSDN, the MS time functions can't handle dates outside
6117 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6118 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6119 tz_info.StandardDate.wYear = year;
6120 convert_to_absolute_date(&tz_info.StandardDate);
6121 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6126 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6127 tz_info.DaylightDate.wYear = year;
6128 convert_to_absolute_date(&tz_info.DaylightDate);
6129 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6134 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6136 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6137 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6145 static inline gint32
6146 mono_array_get_byte_length (MonoArray *array)
6152 klass = array->obj.vtable->klass;
6154 if (array->bounds == NULL)
6155 length = array->max_length;
6158 for (i = 0; i < klass->rank; ++ i)
6159 length *= array->bounds [i].length;
6162 switch (klass->element_class->byval_arg.type) {
6165 case MONO_TYPE_BOOLEAN:
6169 case MONO_TYPE_CHAR:
6177 return length * sizeof (gpointer);
6188 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6190 MONO_ARCH_SAVE_REGS;
6192 return mono_array_get_byte_length (array);
6196 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6198 MONO_ARCH_SAVE_REGS;
6200 return mono_array_get (array, gint8, idx);
6204 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6206 MONO_ARCH_SAVE_REGS;
6208 mono_array_set (array, gint8, idx, value);
6211 ICALL_EXPORT MonoBoolean
6212 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6214 guint8 *src_buf, *dest_buf;
6216 MONO_ARCH_SAVE_REGS;
6218 /* This is called directly from the class libraries without going through the managed wrapper */
6219 MONO_CHECK_ARG_NULL (src);
6220 MONO_CHECK_ARG_NULL (dest);
6222 /* watch out for integer overflow */
6223 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6226 src_buf = (guint8 *)src->vector + src_offset;
6227 dest_buf = (guint8 *)dest->vector + dest_offset;
6230 memcpy (dest_buf, src_buf, count);
6232 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6237 #ifndef DISABLE_REMOTING
6238 ICALL_EXPORT MonoObject *
6239 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6241 MonoDomain *domain = mono_object_domain (this);
6243 MonoRealProxy *rp = ((MonoRealProxy *)this);
6244 MonoTransparentProxy *tp;
6248 MONO_ARCH_SAVE_REGS;
6250 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6251 tp = (MonoTransparentProxy*) res;
6253 MONO_OBJECT_SETREF (tp, rp, rp);
6254 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6255 klass = mono_class_from_mono_type (type);
6257 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6258 tp->remote_class = mono_remote_class (domain, class_name, klass);
6260 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6264 ICALL_EXPORT MonoReflectionType *
6265 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6267 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6271 /* System.Environment */
6274 ves_icall_System_Environment_get_UserName (void)
6276 MONO_ARCH_SAVE_REGS;
6278 /* using glib is more portable */
6279 return mono_string_new (mono_domain_get (), g_get_user_name ());
6283 ICALL_EXPORT MonoString *
6284 ves_icall_System_Environment_get_MachineName (void)
6286 #if defined (HOST_WIN32)
6291 len = MAX_COMPUTERNAME_LENGTH + 1;
6292 buf = g_new (gunichar2, len);
6295 if (GetComputerName (buf, (PDWORD) &len))
6296 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6300 #elif !defined(DISABLE_SOCKETS)
6304 if (gethostname (buf, sizeof (buf)) == 0)
6305 result = mono_string_new (mono_domain_get (), buf);
6311 return mono_string_new (mono_domain_get (), "mono");
6316 ves_icall_System_Environment_get_Platform (void)
6318 #if defined (TARGET_WIN32)
6321 #elif defined(__MACH__)
6324 // Notice that the value is hidden from user code, and only exposed
6325 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6326 // define and making assumptions based on Unix/128/4 values before there
6327 // was a MacOS define. Lots of code would assume that not-Unix meant
6328 // Windows, but in this case, it would be OSX.
6337 ICALL_EXPORT MonoString *
6338 ves_icall_System_Environment_get_NewLine (void)
6340 MONO_ARCH_SAVE_REGS;
6342 #if defined (HOST_WIN32)
6343 return mono_string_new (mono_domain_get (), "\r\n");
6345 return mono_string_new (mono_domain_get (), "\n");
6349 ICALL_EXPORT MonoString *
6350 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6355 MONO_ARCH_SAVE_REGS;
6360 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6361 value = g_getenv (utf8_name);
6368 return mono_string_new (mono_domain_get (), value);
6372 * There is no standard way to get at environ.
6375 #ifndef __MINGW32_VERSION
6376 #if defined(__APPLE__) && !defined (__arm__)
6377 /* Apple defines this in crt_externs.h but doesn't provide that header for
6378 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6379 * in fact exist on all implementations (so far)
6381 gchar ***_NSGetEnviron(void);
6382 #define environ (*_NSGetEnviron())
6390 ICALL_EXPORT MonoArray *
6391 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6402 env_strings = GetEnvironmentStrings();
6405 env_string = env_strings;
6406 while (*env_string != '\0') {
6407 /* weird case that MS seems to skip */
6408 if (*env_string != '=')
6410 while (*env_string != '\0')
6416 domain = mono_domain_get ();
6417 names = mono_array_new (domain, mono_defaults.string_class, n);
6421 env_string = env_strings;
6422 while (*env_string != '\0') {
6423 /* weird case that MS seems to skip */
6424 if (*env_string != '=') {
6425 equal_str = wcschr(env_string, '=');
6426 g_assert(equal_str);
6427 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6428 mono_array_setref (names, n, str);
6431 while (*env_string != '\0')
6436 FreeEnvironmentStrings (env_strings);
6448 MONO_ARCH_SAVE_REGS;
6451 for (e = environ; *e != 0; ++ e)
6454 domain = mono_domain_get ();
6455 names = mono_array_new (domain, mono_defaults.string_class, n);
6458 for (e = environ; *e != 0; ++ e) {
6459 parts = g_strsplit (*e, "=", 2);
6461 str = mono_string_new (domain, *parts);
6462 mono_array_setref (names, n, str);
6475 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6477 #if !GLIB_CHECK_VERSION(2,4,0)
6478 #define g_setenv(a,b,c) setenv(a,b,c)
6479 #define g_unsetenv(a) unsetenv(a)
6483 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6486 gunichar2 *utf16_name, *utf16_value;
6488 gchar *utf8_name, *utf8_value;
6492 MONO_ARCH_SAVE_REGS;
6495 utf16_name = mono_string_to_utf16 (name);
6496 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6497 SetEnvironmentVariable (utf16_name, NULL);
6498 g_free (utf16_name);
6502 utf16_value = mono_string_to_utf16 (value);
6504 SetEnvironmentVariable (utf16_name, utf16_value);
6506 g_free (utf16_name);
6507 g_free (utf16_value);
6509 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6511 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6512 g_unsetenv (utf8_name);
6517 utf8_value = mono_string_to_utf8_checked (value, &error);
6518 if (!mono_error_ok (&error)) {
6520 mono_error_raise_exception (&error);
6522 g_setenv (utf8_name, utf8_value, TRUE);
6525 g_free (utf8_value);
6530 ves_icall_System_Environment_Exit (int result)
6532 MONO_ARCH_SAVE_REGS;
6534 mono_environment_exitcode_set (result);
6536 /* FIXME: There are some cleanup hangs that should be worked out, but
6537 * if the program is going to exit, everything will be cleaned up when
6538 * NaCl exits anyway.
6540 #ifndef __native_client__
6541 if (!mono_runtime_try_shutdown ())
6542 mono_thread_exit ();
6544 /* Suspend all managed threads since the runtime is going away */
6545 mono_thread_suspend_all_other_threads ();
6547 mono_runtime_quit ();
6550 /* we may need to do some cleanup here... */
6554 ICALL_EXPORT MonoString*
6555 ves_icall_System_Environment_GetGacPath (void)
6557 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6560 ICALL_EXPORT MonoString*
6561 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6563 #if defined (HOST_WIN32)
6564 #ifndef CSIDL_FLAG_CREATE
6565 #define CSIDL_FLAG_CREATE 0x8000
6568 WCHAR path [MAX_PATH];
6569 /* Create directory if no existing */
6570 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6574 return mono_string_new_utf16 (mono_domain_get (), path, len);
6577 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6579 return mono_string_new (mono_domain_get (), "");
6582 ICALL_EXPORT MonoArray *
6583 ves_icall_System_Environment_GetLogicalDrives (void)
6585 gunichar2 buf [256], *ptr, *dname;
6587 guint initial_size = 127, size = 128;
6590 MonoString *drivestr;
6591 MonoDomain *domain = mono_domain_get ();
6594 MONO_ARCH_SAVE_REGS;
6599 while (size > initial_size) {
6600 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6601 if (size > initial_size) {
6604 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6605 initial_size = size;
6619 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6624 while (*u16) { u16++; len ++; }
6625 drivestr = mono_string_new_utf16 (domain, dname, len);
6626 mono_array_setref (result, ndrives++, drivestr);
6636 ICALL_EXPORT MonoString *
6637 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6639 gunichar2 volume_name [MAX_PATH + 1];
6641 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6643 return mono_string_from_utf16 (volume_name);
6646 ICALL_EXPORT MonoString *
6647 ves_icall_System_Environment_InternalGetHome (void)
6649 MONO_ARCH_SAVE_REGS;
6651 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6654 static const char *encodings [] = {
6656 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6657 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6658 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6660 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6661 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6662 "x_unicode_2_0_utf_7",
6664 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6665 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6667 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6670 "unicodefffe", "utf_16be",
6677 * Returns the internal codepage, if the value of "int_code_page" is
6678 * 1 at entry, and we can not compute a suitable code page number,
6679 * returns the code page as a string
6681 ICALL_EXPORT MonoString*
6682 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6687 char *codepage = NULL;
6689 int want_name = *int_code_page;
6692 *int_code_page = -1;
6693 MONO_ARCH_SAVE_REGS;
6695 g_get_charset (&cset);
6696 c = codepage = strdup (cset);
6697 for (c = codepage; *c; c++){
6698 if (isascii (*c) && isalpha (*c))
6703 /* g_print ("charset: %s\n", cset); */
6705 /* handle some common aliases */
6708 for (i = 0; p != 0; ){
6709 if ((gssize) p < 7){
6711 p = encodings [++i];
6714 if (strcmp (p, codepage) == 0){
6715 *int_code_page = code;
6718 p = encodings [++i];
6721 if (strstr (codepage, "utf_8") != NULL)
6722 *int_code_page |= 0x10000000;
6725 if (want_name && *int_code_page == -1)
6726 return mono_string_new (mono_domain_get (), cset);
6731 ICALL_EXPORT MonoBoolean
6732 ves_icall_System_Environment_get_HasShutdownStarted (void)
6734 if (mono_runtime_is_shutting_down ())
6737 if (mono_domain_is_unloading (mono_domain_get ()))
6744 ves_icall_System_Environment_BroadcastSettingChange (void)
6747 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6752 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6753 MonoReflectionMethod *method,
6754 MonoArray *out_args)
6756 MONO_ARCH_SAVE_REGS;
6758 mono_message_init (mono_object_domain (this), this, method, out_args);
6761 #ifndef DISABLE_REMOTING
6762 ICALL_EXPORT MonoBoolean
6763 ves_icall_IsTransparentProxy (MonoObject *proxy)
6765 MONO_ARCH_SAVE_REGS;
6770 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6776 ICALL_EXPORT MonoReflectionMethod *
6777 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6778 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6782 MonoMethod **vtable;
6783 MonoMethod *res = NULL;
6785 MONO_CHECK_ARG_NULL (rtype);
6786 MONO_CHECK_ARG_NULL (rmethod);
6788 method = rmethod->method;
6789 klass = mono_class_from_mono_type (rtype->type);
6790 mono_class_init_or_throw (klass);
6792 if (MONO_CLASS_IS_INTERFACE (klass))
6795 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6798 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6799 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6805 mono_class_setup_vtable (klass);
6806 vtable = klass->vtable;
6808 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6809 gboolean variance_used = FALSE;
6810 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6811 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6813 res = vtable [offs + method->slot];
6815 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6818 if (method->slot != -1)
6819 res = vtable [method->slot];
6825 return mono_method_get_object (mono_domain_get (), res, NULL);
6829 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6834 MONO_ARCH_SAVE_REGS;
6836 klass = mono_class_from_mono_type (type->type);
6837 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6839 mono_vtable_set_is_remote (vtable, enable);
6842 #else /* DISABLE_REMOTING */
6845 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6847 g_assert_not_reached ();
6852 ICALL_EXPORT MonoObject *
6853 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6858 MONO_ARCH_SAVE_REGS;
6860 domain = mono_object_domain (type);
6861 klass = mono_class_from_mono_type (type->type);
6862 mono_class_init_or_throw (klass);
6864 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6865 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6867 if (klass->rank >= 1) {
6868 g_assert (klass->rank == 1);
6869 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6871 /* Bypass remoting object creation check */
6872 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6876 ICALL_EXPORT MonoString *
6877 ves_icall_System_IO_get_temp_path (void)
6879 MONO_ARCH_SAVE_REGS;
6881 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6884 #ifndef PLATFORM_NO_DRIVEINFO
6885 ICALL_EXPORT MonoBoolean
6886 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6887 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6891 ULARGE_INTEGER wapi_free_bytes_avail;
6892 ULARGE_INTEGER wapi_total_number_of_bytes;
6893 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6895 MONO_ARCH_SAVE_REGS;
6897 *error = ERROR_SUCCESS;
6898 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6899 &wapi_total_number_of_free_bytes);
6902 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6903 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6904 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6906 *free_bytes_avail = 0;
6907 *total_number_of_bytes = 0;
6908 *total_number_of_free_bytes = 0;
6909 *error = GetLastError ();
6915 ICALL_EXPORT guint32
6916 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6918 MONO_ARCH_SAVE_REGS;
6920 return GetDriveType (mono_string_chars (root_path_name));
6924 ICALL_EXPORT gpointer
6925 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6927 MONO_ARCH_SAVE_REGS;
6929 return mono_compile_method (method);
6932 ICALL_EXPORT MonoString *
6933 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6938 MONO_ARCH_SAVE_REGS;
6940 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6942 #if defined (HOST_WIN32)
6943 /* Avoid mixing '/' and '\\' */
6946 for (i = strlen (path) - 1; i >= 0; i--)
6947 if (path [i] == '/')
6951 mcpath = mono_string_new (mono_domain_get (), path);
6958 get_bundled_app_config (void)
6960 const gchar *app_config;
6963 gchar *config_file_name, *config_file_path;
6967 MONO_ARCH_SAVE_REGS;
6969 domain = mono_domain_get ();
6970 file = domain->setup->configuration_file;
6974 // Retrieve config file and remove the extension
6975 config_file_name = mono_string_to_utf8 (file);
6976 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6977 if (!config_file_path)
6978 config_file_path = config_file_name;
6979 len = strlen (config_file_path) - strlen (".config");
6980 module = g_malloc0 (len + 1);
6981 memcpy (module, config_file_path, len);
6982 // Get the config file from the module name
6983 app_config = mono_config_string_for_assembly_file (module);
6986 if (config_file_name != config_file_path)
6987 g_free (config_file_name);
6988 g_free (config_file_path);
6993 return mono_string_new (mono_domain_get (), app_config);
6997 get_bundled_machine_config (void)
6999 const gchar *machine_config;
7001 MONO_ARCH_SAVE_REGS;
7003 machine_config = mono_get_machine_config ();
7005 if (!machine_config)
7008 return mono_string_new (mono_domain_get (), machine_config);
7011 ICALL_EXPORT MonoString *
7012 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7017 MONO_ARCH_SAVE_REGS;
7019 path = g_path_get_dirname (mono_get_config_dir ());
7021 #if defined (HOST_WIN32)
7022 /* Avoid mixing '/' and '\\' */
7025 for (i = strlen (path) - 1; i >= 0; i--)
7026 if (path [i] == '/')
7030 ipath = mono_string_new (mono_domain_get (), path);
7036 ICALL_EXPORT gboolean
7037 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7039 MonoPEResourceDataEntry *entry;
7042 MONO_ARCH_SAVE_REGS;
7044 if (!assembly || !result || !size)
7049 image = assembly->assembly->image;
7050 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7054 *result = mono_image_rva_map (image, entry->rde_data_offset);
7059 *size = entry->rde_size;
7064 ICALL_EXPORT MonoBoolean
7065 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7067 return mono_is_debugger_attached ();
7070 ICALL_EXPORT MonoBoolean
7071 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7073 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7074 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7080 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7082 if (mono_get_runtime_callbacks ()->debug_log)
7083 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7087 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7089 #if defined (HOST_WIN32)
7090 OutputDebugString (mono_string_chars (message));
7092 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7096 /* Only used for value types */
7097 ICALL_EXPORT MonoObject *
7098 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7103 MONO_ARCH_SAVE_REGS;
7105 domain = mono_object_domain (type);
7106 klass = mono_class_from_mono_type (type->type);
7107 mono_class_init_or_throw (klass);
7109 if (mono_class_is_nullable (klass))
7110 /* No arguments -> null */
7113 return mono_object_new (domain, klass);
7116 ICALL_EXPORT MonoReflectionMethod *
7117 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7119 MonoClass *klass, *parent;
7120 MonoMethod *method = m->method;
7121 MonoMethod *result = NULL;
7124 MONO_ARCH_SAVE_REGS;
7126 if (method->klass == NULL)
7129 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7130 MONO_CLASS_IS_INTERFACE (method->klass) ||
7131 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7134 slot = mono_method_get_vtable_slot (method);
7138 klass = method->klass;
7139 if (klass->generic_class)
7140 klass = klass->generic_class->container_class;
7143 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7144 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7145 mono_class_setup_vtable (parent);
7146 if (parent->vtable_size <= slot)
7151 klass = klass->parent;
7156 if (klass == method->klass)
7159 /*This is possible if definition == FALSE.
7160 * Do it here to be really sure we don't read invalid memory.
7162 if (slot >= klass->vtable_size)
7165 mono_class_setup_vtable (klass);
7167 result = klass->vtable [slot];
7168 if (result == NULL) {
7169 /* It is an abstract method */
7170 gpointer iter = NULL;
7171 while ((result = mono_class_get_methods (klass, &iter)))
7172 if (result->slot == slot)
7179 return mono_method_get_object (mono_domain_get (), result, NULL);
7182 ICALL_EXPORT MonoString*
7183 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7185 MonoMethod *method = m->method;
7187 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7192 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7194 MONO_ARCH_SAVE_REGS;
7196 iter->sig = *(MonoMethodSignature**)argsp;
7198 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7199 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7202 /* FIXME: it's not documented what start is exactly... */
7206 iter->args = argsp + sizeof (gpointer);
7208 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7210 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7213 ICALL_EXPORT MonoTypedRef
7214 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7216 guint32 i, arg_size;
7219 MONO_ARCH_SAVE_REGS;
7221 i = iter->sig->sentinelpos + iter->next_arg;
7223 g_assert (i < iter->sig->param_count);
7225 res.type = iter->sig->params [i];
7226 res.klass = mono_class_from_mono_type (res.type);
7227 arg_size = mono_type_stack_size (res.type, &align);
7228 #if defined(__arm__) || defined(__mips__)
7229 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7231 res.value = iter->args;
7232 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7233 /* Values are stored as 8 byte register sized objects, but 'value'
7234 * is dereferenced as a pointer in other routines.
7236 res.value = (char*)res.value + 4;
7238 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7239 if (arg_size <= sizeof (gpointer)) {
7241 int padding = arg_size - mono_type_size (res.type, &dummy);
7242 res.value = (guint8*)res.value + padding;
7245 iter->args = (char*)iter->args + arg_size;
7248 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7253 ICALL_EXPORT MonoTypedRef
7254 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7256 guint32 i, arg_size;
7259 MONO_ARCH_SAVE_REGS;
7261 i = iter->sig->sentinelpos + iter->next_arg;
7263 g_assert (i < iter->sig->param_count);
7265 while (i < iter->sig->param_count) {
7266 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7268 res.type = iter->sig->params [i];
7269 res.klass = mono_class_from_mono_type (res.type);
7270 /* FIXME: endianess issue... */
7271 arg_size = mono_type_stack_size (res.type, &align);
7272 #if defined(__arm__) || defined(__mips__)
7273 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7275 res.value = iter->args;
7276 iter->args = (char*)iter->args + arg_size;
7278 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7281 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7289 ICALL_EXPORT MonoType*
7290 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7293 MONO_ARCH_SAVE_REGS;
7295 i = iter->sig->sentinelpos + iter->next_arg;
7297 g_assert (i < iter->sig->param_count);
7299 return iter->sig->params [i];
7302 ICALL_EXPORT MonoObject*
7303 mono_TypedReference_ToObject (MonoTypedRef tref)
7305 MONO_ARCH_SAVE_REGS;
7307 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7308 MonoObject** objp = tref.value;
7312 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7315 ICALL_EXPORT MonoObject*
7316 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7318 MONO_ARCH_SAVE_REGS;
7320 if (MONO_TYPE_IS_REFERENCE (type)) {
7321 MonoObject** objp = value;
7325 return mono_value_box (mono_domain_get (), klass, value);
7329 prelink_method (MonoMethod *method)
7331 const char *exc_class, *exc_arg;
7332 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7334 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7336 mono_raise_exception(
7337 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7339 /* create the wrapper, too? */
7343 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7345 MONO_ARCH_SAVE_REGS;
7346 prelink_method (method->method);
7350 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7352 MonoClass *klass = mono_class_from_mono_type (type->type);
7354 gpointer iter = NULL;
7355 MONO_ARCH_SAVE_REGS;
7357 mono_class_init_or_throw (klass);
7359 while ((m = mono_class_get_methods (klass, &iter)))
7363 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7365 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7366 gint32 const **exponents,
7367 gunichar2 const **digitLowerTable,
7368 gunichar2 const **digitUpperTable,
7369 gint64 const **tenPowersList,
7370 gint32 const **decHexDigits)
7372 *mantissas = Formatter_MantissaBitsTable;
7373 *exponents = Formatter_TensExponentTable;
7374 *digitLowerTable = Formatter_DigitLowerTable;
7375 *digitUpperTable = Formatter_DigitUpperTable;
7376 *tenPowersList = Formatter_TenPowersList;
7377 *decHexDigits = Formatter_DecHexDigits;
7381 get_category_data (int version,
7382 guint8 const **category_data,
7383 guint16 const **category_astral_index)
7385 *category_astral_index = NULL;
7387 #ifndef DISABLE_NET_4_0
7389 *category_data = CategoryData_v4;
7390 #ifndef DISABLE_ASTRAL
7391 *category_astral_index = CategoryData_v4_astral_index;
7397 *category_data = CategoryData_v2;
7398 #ifndef DISABLE_ASTRAL
7399 *category_astral_index = CategoryData_v2_astral_index;
7403 /* These parameters are "readonly" in corlib/System/Char.cs */
7405 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7406 guint8 const **category_data,
7407 guint16 const **category_astral_index,
7408 guint8 const **numeric_data,
7409 gdouble const **numeric_data_values,
7410 guint16 const **to_lower_data_low,
7411 guint16 const **to_lower_data_high,
7412 guint16 const **to_upper_data_low,
7413 guint16 const **to_upper_data_high)
7415 get_category_data (category_data_version, category_data, category_astral_index);
7416 *numeric_data = NumericData;
7417 *numeric_data_values = NumericDataValues;
7418 *to_lower_data_low = ToLowerDataLow;
7419 *to_lower_data_high = ToLowerDataHigh;
7420 *to_upper_data_low = ToUpperDataLow;
7421 *to_upper_data_high = ToUpperDataHigh;
7425 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7426 * and avoid useless allocations.
7431 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7435 for (i = 0; i < type->num_mods; ++i) {
7436 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7441 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7443 for (i = 0; i < type->num_mods; ++i) {
7444 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7446 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7447 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7448 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7455 ICALL_EXPORT MonoArray*
7456 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7458 MonoType *type = param->ClassImpl->type;
7459 MonoClass *member_class = mono_object_class (param->MemberImpl);
7460 MonoMethod *method = NULL;
7463 MonoMethodSignature *sig;
7465 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7466 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7467 method = rmethod->method;
7468 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7469 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7470 if (!(method = prop->property->get))
7471 method = prop->property->set;
7474 char *type_name = mono_type_get_full_name (member_class);
7475 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7476 MonoException *ex = mono_get_exception_not_supported (msg);
7479 mono_raise_exception (ex);
7482 image = method->klass->image;
7483 pos = param->PositionImpl;
7484 sig = mono_method_signature (method);
7488 type = sig->params [pos];
7490 return type_array_from_modifiers (image, type, optional);
7494 get_property_type (MonoProperty *prop)
7496 MonoMethodSignature *sig;
7498 sig = mono_method_signature (prop->get);
7500 } else if (prop->set) {
7501 sig = mono_method_signature (prop->set);
7502 return sig->params [sig->param_count - 1];
7507 ICALL_EXPORT MonoArray*
7508 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7510 MonoType *type = get_property_type (property->property);
7511 MonoImage *image = property->klass->image;
7515 return type_array_from_modifiers (image, type, optional);
7519 *Construct a MonoType suited to be used to decode a constant blob object.
7521 * @type is the target type which will be constructed
7522 * @blob_type is the blob type, for example, that comes from the constant table
7523 * @real_type is the expected constructed type.
7526 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7528 type->type = blob_type;
7529 type->data.klass = NULL;
7530 if (blob_type == MONO_TYPE_CLASS)
7531 type->data.klass = mono_defaults.object_class;
7532 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7533 /* For enums, we need to use the base type */
7534 type->type = MONO_TYPE_VALUETYPE;
7535 type->data.klass = mono_class_from_mono_type (real_type);
7537 type->data.klass = mono_class_from_mono_type (real_type);
7540 ICALL_EXPORT MonoObject*
7541 property_info_get_default_value (MonoReflectionProperty *property)
7544 MonoProperty *prop = property->property;
7545 MonoType *type = get_property_type (prop);
7546 MonoDomain *domain = mono_object_domain (property);
7547 MonoTypeEnum def_type;
7548 const char *def_value;
7551 mono_class_init (prop->parent);
7553 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7554 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7556 def_value = mono_class_get_property_default_value (prop, &def_type);
7558 mono_type_from_blob_type (&blob_type, def_type, type);
7559 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7564 ICALL_EXPORT MonoBoolean
7565 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7567 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7568 MonoCustomAttrInfo *cinfo;
7571 mono_class_init_or_throw (attr_class);
7573 cinfo = mono_reflection_get_custom_attrs_info (obj);
7576 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7578 mono_custom_attrs_free (cinfo);
7582 ICALL_EXPORT MonoArray*
7583 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7585 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7590 mono_class_init_or_throw (attr_class);
7592 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7593 mono_error_raise_exception (&error);
7595 if (mono_loader_get_last_error ()) {
7596 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7597 g_assert_not_reached ();
7605 ICALL_EXPORT MonoString*
7606 ves_icall_Mono_Runtime_GetDisplayName (void)
7609 MonoString *display_name;
7611 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7612 display_name = mono_string_new (mono_domain_get (), info);
7614 return display_name;
7617 ICALL_EXPORT MonoString*
7618 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7620 MonoString *message;
7624 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7625 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7628 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7630 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7638 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7639 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7640 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7641 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7642 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7643 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7644 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7645 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7649 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7654 gunichar2 last, prev_last, prev2_last;
7661 int havePadding = 0;
7663 last = prev_last = 0, prev2_last = 0;
7664 for (i = 0; i < ilength; i++) {
7666 if (c >= sizeof (dbase64)) {
7667 exc = mono_exception_from_name_msg (mono_get_corlib (),
7668 "System", "FormatException",
7669 "Invalid character found.");
7670 mono_raise_exception (exc);
7671 } else if (isspace (c)) {
7673 } else if (havePadding && c != '=') {
7674 exc = mono_exception_from_name_msg (mono_get_corlib (),
7675 "System", "FormatException",
7676 "Invalid character found.");
7677 mono_raise_exception (exc);
7679 if (c == '=') havePadding = 1;
7680 prev2_last = prev_last;
7686 olength = ilength - ignored;
7688 if (allowWhitespaceOnly && olength == 0) {
7689 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7692 if ((olength & 3) != 0 || olength <= 0) {
7693 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7694 "FormatException", "Invalid length.");
7695 mono_raise_exception (exc);
7698 if (prev2_last == '=') {
7699 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7700 mono_raise_exception (exc);
7703 olength = (olength * 3) / 4;
7707 if (prev_last == '=')
7710 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7711 res_ptr = mono_array_addr (result, guchar, 0);
7712 for (i = 0; i < ilength; ) {
7715 for (k = 0; k < 4 && i < ilength;) {
7721 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7722 exc = mono_exception_from_name_msg (mono_get_corlib (),
7723 "System", "FormatException",
7724 "Invalid character found.");
7725 mono_raise_exception (exc);
7730 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7732 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7734 *res_ptr++ = (b [2] << 6) | b [3];
7736 while (i < ilength && isspace (start [i]))
7743 ICALL_EXPORT MonoArray *
7744 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7746 MONO_ARCH_SAVE_REGS;
7748 return base64_to_byte_array (mono_string_chars (str),
7749 mono_string_length (str), allowWhitespaceOnly);
7752 ICALL_EXPORT MonoArray *
7753 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7755 MONO_ARCH_SAVE_REGS;
7757 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7761 #ifndef DISABLE_ICALL_TABLES
7763 #define ICALL_TYPE(id,name,first)
7764 #define ICALL(id,name,func) Icall_ ## id,
7767 #include "metadata/icall-def.h"
7773 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7774 #define ICALL(id,name,func)
7776 #include "metadata/icall-def.h"
7782 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7783 #define ICALL(id,name,func)
7785 guint16 first_icall;
7788 static const IcallTypeDesc
7789 icall_type_descs [] = {
7790 #include "metadata/icall-def.h"
7794 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7797 #define ICALL_TYPE(id,name,first)
7800 #ifdef HAVE_ARRAY_ELEM_INIT
7801 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7802 #define MSGSTRFIELD1(line) str##line
7804 static const struct msgstrtn_t {
7805 #define ICALL(id,name,func)
7807 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7808 #include "metadata/icall-def.h"
7810 } icall_type_names_str = {
7811 #define ICALL_TYPE(id,name,first) (name),
7812 #include "metadata/icall-def.h"
7815 static const guint16 icall_type_names_idx [] = {
7816 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7817 #include "metadata/icall-def.h"
7820 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7822 static const struct msgstr_t {
7824 #define ICALL_TYPE(id,name,first)
7825 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7826 #include "metadata/icall-def.h"
7828 } icall_names_str = {
7829 #define ICALL(id,name,func) (name),
7830 #include "metadata/icall-def.h"
7833 static const guint16 icall_names_idx [] = {
7834 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7835 #include "metadata/icall-def.h"
7838 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7844 #define ICALL_TYPE(id,name,first) name,
7845 #define ICALL(id,name,func)
7846 static const char* const
7847 icall_type_names [] = {
7848 #include "metadata/icall-def.h"
7852 #define icall_type_name_get(id) (icall_type_names [(id)])
7856 #define ICALL_TYPE(id,name,first)
7857 #define ICALL(id,name,func) name,
7858 static const char* const
7860 #include "metadata/icall-def.h"
7863 #define icall_name_get(id) icall_names [(id)]
7865 #endif /* !HAVE_ARRAY_ELEM_INIT */
7869 #define ICALL_TYPE(id,name,first)
7870 #define ICALL(id,name,func) func,
7871 static const gconstpointer
7872 icall_functions [] = {
7873 #include "metadata/icall-def.h"
7877 #ifdef ENABLE_ICALL_SYMBOL_MAP
7880 #define ICALL_TYPE(id,name,first)
7881 #define ICALL(id,name,func) #func,
7882 static const gconstpointer
7883 icall_symbols [] = {
7884 #include "metadata/icall-def.h"
7889 #endif /* DISABLE_ICALL_TABLES */
7891 static mono_mutex_t icall_mutex;
7892 static GHashTable *icall_hash = NULL;
7893 static GHashTable *jit_icall_hash_name = NULL;
7894 static GHashTable *jit_icall_hash_addr = NULL;
7897 mono_icall_init (void)
7899 #ifndef DISABLE_ICALL_TABLES
7902 /* check that tables are sorted: disable in release */
7905 const char *prev_class = NULL;
7906 const char *prev_method;
7908 for (i = 0; i < Icall_type_num; ++i) {
7909 const IcallTypeDesc *desc;
7912 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7913 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7914 prev_class = icall_type_name_get (i);
7915 desc = &icall_type_descs [i];
7916 num_icalls = icall_desc_num_icalls (desc);
7917 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7918 for (j = 0; j < num_icalls; ++j) {
7919 const char *methodn = icall_name_get (desc->first_icall + j);
7920 if (prev_method && strcmp (prev_method, methodn) >= 0)
7921 g_print ("method %s should come before method %s\n", methodn, prev_method);
7922 prev_method = methodn;
7928 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7929 mono_mutex_init (&icall_mutex);
7933 mono_icall_lock (void)
7935 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7939 mono_icall_unlock (void)
7941 mono_locks_mutex_release (&icall_mutex, IcallLock);
7945 mono_icall_cleanup (void)
7947 g_hash_table_destroy (icall_hash);
7948 g_hash_table_destroy (jit_icall_hash_name);
7949 g_hash_table_destroy (jit_icall_hash_addr);
7950 mono_mutex_destroy (&icall_mutex);
7954 mono_add_internal_call (const char *name, gconstpointer method)
7958 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7960 mono_icall_unlock ();
7963 #ifndef DISABLE_ICALL_TABLES
7965 #ifdef HAVE_ARRAY_ELEM_INIT
7967 compare_method_imap (const void *key, const void *elem)
7969 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7970 return strcmp (key, method_name);
7974 find_method_icall (const IcallTypeDesc *imap, const char *name)
7976 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);
7979 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7983 compare_class_imap (const void *key, const void *elem)
7985 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7986 return strcmp (key, class_name);
7989 static const IcallTypeDesc*
7990 find_class_icalls (const char *name)
7992 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
7995 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
7998 #else /* HAVE_ARRAY_ELEM_INIT */
8001 compare_method_imap (const void *key, const void *elem)
8003 const char** method_name = (const char**)elem;
8004 return strcmp (key, *method_name);
8008 find_method_icall (const IcallTypeDesc *imap, const char *name)
8010 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8013 return (gpointer)icall_functions [(nameslot - icall_names)];
8017 compare_class_imap (const void *key, const void *elem)
8019 const char** class_name = (const char**)elem;
8020 return strcmp (key, *class_name);
8023 static const IcallTypeDesc*
8024 find_class_icalls (const char *name)
8026 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8029 return &icall_type_descs [nameslot - icall_type_names];
8032 #endif /* HAVE_ARRAY_ELEM_INIT */
8034 #endif /* DISABLE_ICALL_TABLES */
8037 * we should probably export this as an helper (handle nested types).
8038 * Returns the number of chars written in buf.
8041 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8043 int nspacelen, cnamelen;
8044 nspacelen = strlen (klass->name_space);
8045 cnamelen = strlen (klass->name);
8046 if (nspacelen + cnamelen + 2 > bufsize)
8049 memcpy (buf, klass->name_space, nspacelen);
8050 buf [nspacelen ++] = '.';
8052 memcpy (buf + nspacelen, klass->name, cnamelen);
8053 buf [nspacelen + cnamelen] = 0;
8054 return nspacelen + cnamelen;
8057 #ifdef DISABLE_ICALL_TABLES
8059 no_icall_table (void)
8061 g_assert_not_reached ();
8066 mono_lookup_internal_call (MonoMethod *method)
8071 int typelen = 0, mlen, siglen;
8073 #ifndef DISABLE_ICALL_TABLES
8074 const IcallTypeDesc *imap = NULL;
8077 g_assert (method != NULL);
8079 if (method->is_inflated)
8080 method = ((MonoMethodInflated *) method)->declaring;
8082 if (method->klass->nested_in) {
8083 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8087 mname [pos++] = '/';
8090 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8096 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8101 #ifndef DISABLE_ICALL_TABLES
8102 imap = find_class_icalls (mname);
8105 mname [typelen] = ':';
8106 mname [typelen + 1] = ':';
8108 mlen = strlen (method->name);
8109 memcpy (mname + typelen + 2, method->name, mlen);
8110 sigstart = mname + typelen + 2 + mlen;
8113 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8114 siglen = strlen (tmpsig);
8115 if (typelen + mlen + siglen + 6 > sizeof (mname))
8118 memcpy (sigstart + 1, tmpsig, siglen);
8119 sigstart [siglen + 1] = ')';
8120 sigstart [siglen + 2] = 0;
8125 res = g_hash_table_lookup (icall_hash, mname);
8127 mono_icall_unlock ();;
8130 /* try without signature */
8132 res = g_hash_table_lookup (icall_hash, mname);
8134 mono_icall_unlock ();
8138 #ifdef DISABLE_ICALL_TABLES
8139 mono_icall_unlock ();
8140 /* Fail only when the result is actually used */
8141 /* mono_marshal_get_native_wrapper () depends on this */
8142 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8143 return ves_icall_System_String_ctor_RedirectToCreateString;
8145 return no_icall_table;
8147 /* it wasn't found in the static call tables */
8149 mono_icall_unlock ();
8152 res = find_method_icall (imap, sigstart - mlen);
8154 mono_icall_unlock ();
8157 /* try _with_ signature */
8159 res = find_method_icall (imap, sigstart - mlen);
8161 mono_icall_unlock ();
8165 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8166 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8167 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8168 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8169 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");
8170 g_print ("If you see other errors or faults after this message they are probably related\n");
8171 g_print ("and you need to fix your mono install first.\n");
8173 mono_icall_unlock ();
8179 #ifdef ENABLE_ICALL_SYMBOL_MAP
8181 func_cmp (gconstpointer key, gconstpointer p)
8183 return (gsize)key - (gsize)*(gsize*)p;
8188 * mono_lookup_icall_symbol:
8190 * Given the icall METHOD, returns its C symbol.
8193 mono_lookup_icall_symbol (MonoMethod *m)
8195 #ifdef DISABLE_ICALL_TABLES
8196 g_assert_not_reached ();
8199 #ifdef ENABLE_ICALL_SYMBOL_MAP
8203 static gconstpointer *functions_sorted;
8204 static const char**symbols_sorted;
8205 static gboolean inited;
8210 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8211 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8212 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8213 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8214 /* Bubble sort the two arrays */
8218 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8219 if (functions_sorted [i] > functions_sorted [i + 1]) {
8222 tmp = functions_sorted [i];
8223 functions_sorted [i] = functions_sorted [i + 1];
8224 functions_sorted [i + 1] = tmp;
8225 tmp = symbols_sorted [i];
8226 symbols_sorted [i] = symbols_sorted [i + 1];
8227 symbols_sorted [i + 1] = tmp;
8234 func = mono_lookup_internal_call (m);
8237 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8241 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8243 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8244 g_assert_not_reached ();
8251 type_from_typename (char *typename)
8253 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8255 if (!strcmp (typename, "int"))
8256 klass = mono_defaults.int_class;
8257 else if (!strcmp (typename, "ptr"))
8258 klass = mono_defaults.int_class;
8259 else if (!strcmp (typename, "void"))
8260 klass = mono_defaults.void_class;
8261 else if (!strcmp (typename, "int32"))
8262 klass = mono_defaults.int32_class;
8263 else if (!strcmp (typename, "uint32"))
8264 klass = mono_defaults.uint32_class;
8265 else if (!strcmp (typename, "int8"))
8266 klass = mono_defaults.sbyte_class;
8267 else if (!strcmp (typename, "uint8"))
8268 klass = mono_defaults.byte_class;
8269 else if (!strcmp (typename, "int16"))
8270 klass = mono_defaults.int16_class;
8271 else if (!strcmp (typename, "uint16"))
8272 klass = mono_defaults.uint16_class;
8273 else if (!strcmp (typename, "long"))
8274 klass = mono_defaults.int64_class;
8275 else if (!strcmp (typename, "ulong"))
8276 klass = mono_defaults.uint64_class;
8277 else if (!strcmp (typename, "float"))
8278 klass = mono_defaults.single_class;
8279 else if (!strcmp (typename, "double"))
8280 klass = mono_defaults.double_class;
8281 else if (!strcmp (typename, "object"))
8282 klass = mono_defaults.object_class;
8283 else if (!strcmp (typename, "obj"))
8284 klass = mono_defaults.object_class;
8285 else if (!strcmp (typename, "string"))
8286 klass = mono_defaults.string_class;
8287 else if (!strcmp (typename, "bool"))
8288 klass = mono_defaults.boolean_class;
8289 else if (!strcmp (typename, "boolean"))
8290 klass = mono_defaults.boolean_class;
8292 g_error ("%s", typename);
8293 g_assert_not_reached ();
8295 return &klass->byval_arg;
8299 * LOCKING: Take the corlib image lock.
8301 MonoMethodSignature*
8302 mono_create_icall_signature (const char *sigstr)
8307 MonoMethodSignature *res, *res2;
8308 MonoImage *corlib = mono_defaults.corlib;
8310 mono_image_lock (corlib);
8311 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8312 mono_image_unlock (corlib);
8317 parts = g_strsplit (sigstr, " ", 256);
8326 res = mono_metadata_signature_alloc (corlib, len - 1);
8331 * Under windows, the default pinvoke calling convention is STDCALL but
8334 res->call_convention = MONO_CALL_C;
8337 res->ret = type_from_typename (parts [0]);
8338 for (i = 1; i < len; ++i) {
8339 res->params [i - 1] = type_from_typename (parts [i]);
8344 mono_image_lock (corlib);
8345 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8347 res = res2; /*Value is allocated in the image pool*/
8349 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8350 mono_image_unlock (corlib);
8356 mono_find_jit_icall_by_name (const char *name)
8358 MonoJitICallInfo *info;
8359 g_assert (jit_icall_hash_name);
8362 info = g_hash_table_lookup (jit_icall_hash_name, name);
8363 mono_icall_unlock ();
8368 mono_find_jit_icall_by_addr (gconstpointer addr)
8370 MonoJitICallInfo *info;
8371 g_assert (jit_icall_hash_addr);
8374 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8375 mono_icall_unlock ();
8381 * mono_get_jit_icall_info:
8383 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8384 * caller should access it while holding the icall lock.
8387 mono_get_jit_icall_info (void)
8389 return jit_icall_hash_name;
8393 * mono_lookup_jit_icall_symbol:
8395 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8398 mono_lookup_jit_icall_symbol (const char *name)
8400 MonoJitICallInfo *info;
8401 const char *res = NULL;
8404 info = g_hash_table_lookup (jit_icall_hash_name, name);
8406 res = info->c_symbol;
8407 mono_icall_unlock ();
8412 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8415 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8416 mono_icall_unlock ();
8420 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8422 MonoJitICallInfo *info;
8429 if (!jit_icall_hash_name) {
8430 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8431 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8434 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8435 g_warning ("jit icall already defined \"%s\"\n", name);
8436 g_assert_not_reached ();
8439 info = g_new0 (MonoJitICallInfo, 1);
8444 info->c_symbol = c_symbol;
8447 info->wrapper = func;
8449 info->wrapper = NULL;
8452 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8453 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8455 mono_icall_unlock ();
8460 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8462 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);