5 * Dietmar Maurer (dietmar@ximian.com)
6 * Paolo Molaro (lupus@ximian.com)
7 * Patrik Torstensson (patrik.torstensson@labs2.com)
8 * Marek Safar (marek.safar@gmail.com)
10 * Copyright 2001-2003 Ximian, Inc (http://www.ximian.com)
11 * Copyright 2004-2009 Novell, Inc (http://www.novell.com)
12 * Copyright 2011-2014 Xamarin Inc (http://www.xamarin.com).
23 #ifdef HAVE_SYS_TIME_H
29 #if defined (HOST_WIN32)
32 #if defined (HAVE_WCHAR_H)
36 #include "mono/utils/mono-membar.h"
37 #include <mono/metadata/object.h>
38 #include <mono/metadata/threads.h>
39 #include <mono/metadata/threads-types.h>
40 #include <mono/metadata/threadpool.h>
41 #include <mono/metadata/monitor.h>
42 #include <mono/metadata/reflection.h>
43 #include <mono/metadata/assembly.h>
44 #include <mono/metadata/tabledefs.h>
45 #include <mono/metadata/exception.h>
46 #include <mono/metadata/file-io.h>
47 #include <mono/metadata/console-io.h>
48 #include <mono/metadata/socket-io.h>
49 #include <mono/metadata/mono-endian.h>
50 #include <mono/metadata/tokentype.h>
51 #include <mono/metadata/domain-internals.h>
52 #include <mono/metadata/metadata-internals.h>
53 #include <mono/metadata/class-internals.h>
54 #include <mono/metadata/marshal.h>
55 #include <mono/metadata/gc-internal.h>
56 #include <mono/metadata/mono-gc.h>
57 #include <mono/metadata/rand.h>
58 #include <mono/metadata/sysmath.h>
59 #include <mono/metadata/string-icalls.h>
60 #include <mono/metadata/debug-helpers.h>
61 #include <mono/metadata/process.h>
62 #include <mono/metadata/environment.h>
63 #include <mono/metadata/profiler-private.h>
64 #include <mono/metadata/locales.h>
65 #include <mono/metadata/filewatcher.h>
66 #include <mono/metadata/char-conversions.h>
67 #include <mono/metadata/security.h>
68 #include <mono/metadata/mono-config.h>
69 #include <mono/metadata/cil-coff.h>
70 #include <mono/metadata/number-formatter.h>
71 #include <mono/metadata/security-manager.h>
72 #include <mono/metadata/security-core-clr.h>
73 #include <mono/metadata/mono-perfcounters.h>
74 #include <mono/metadata/mono-debug.h>
75 #include <mono/metadata/mono-ptr-array.h>
76 #include <mono/metadata/verify-internals.h>
77 #include <mono/metadata/runtime.h>
78 #include <mono/metadata/file-mmap.h>
79 #include <mono/io-layer/io-layer.h>
80 #include <mono/utils/strtod.h>
81 #include <mono/utils/monobitset.h>
82 #include <mono/utils/mono-time.h>
83 #include <mono/utils/mono-proclib.h>
84 #include <mono/utils/mono-string.h>
85 #include <mono/utils/mono-error-internals.h>
86 #include <mono/utils/mono-mmap.h>
87 #include <mono/utils/mono-io-portability.h>
88 #include <mono/utils/mono-digest.h>
89 #include <mono/utils/bsearch.h>
90 #include <mono/utils/mono-mutex.h>
91 #include <mono/utils/mono-threads.h>
93 #if defined (HOST_WIN32)
99 extern MonoString* ves_icall_System_Environment_GetOSVersionString (void) MONO_INTERNAL;
101 ICALL_EXPORT MonoReflectionAssembly* ves_icall_System_Reflection_Assembly_GetCallingAssembly (void);
104 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional);
106 static inline MonoBoolean
107 is_generic_parameter (MonoType *type)
109 return !type->byref && (type->type == MONO_TYPE_VAR || type->type == MONO_TYPE_MVAR);
113 mono_class_init_or_throw (MonoClass *klass)
115 if (!mono_class_init (klass))
116 mono_raise_exception (mono_class_get_exception_for_failure (klass));
120 * We expect a pointer to a char, not a string
122 ICALL_EXPORT gboolean
123 mono_double_ParseImpl (char *ptr, double *result)
125 gchar *endptr = NULL;
131 /* mono_strtod () is not thread-safe */
132 mono_mutex_lock (&mono_strtod_mutex);
133 *result = mono_strtod (ptr, &endptr);
134 mono_mutex_unlock (&mono_strtod_mutex);
137 if (!*ptr || (endptr && *endptr))
143 ICALL_EXPORT MonoObject *
144 ves_icall_System_Array_GetValueImpl (MonoObject *this, guint32 pos)
153 ao = (MonoArray *)this;
154 ac = (MonoClass *)ao->obj.vtable->klass;
156 esize = mono_array_element_size (ac);
157 ea = (gpointer*)((char*)ao->vector + (pos * esize));
159 if (ac->element_class->valuetype)
160 return mono_value_box (this->vtable->domain, ac->element_class, ea);
165 ICALL_EXPORT MonoObject *
166 ves_icall_System_Array_GetValue (MonoObject *this, MonoObject *idxs)
174 MONO_CHECK_ARG_NULL (idxs);
176 io = (MonoArray *)idxs;
177 ic = (MonoClass *)io->obj.vtable->klass;
179 ao = (MonoArray *)this;
180 ac = (MonoClass *)ao->obj.vtable->klass;
182 g_assert (ic->rank == 1);
183 if (io->bounds != NULL || io->max_length != ac->rank)
184 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
186 ind = (gint32 *)io->vector;
188 if (ao->bounds == NULL) {
189 if (*ind < 0 || *ind >= ao->max_length)
190 mono_raise_exception (mono_get_exception_index_out_of_range ());
192 return ves_icall_System_Array_GetValueImpl (this, *ind);
195 for (i = 0; i < ac->rank; i++)
196 if ((ind [i] < ao->bounds [i].lower_bound) ||
197 (ind [i] >= (mono_array_lower_bound_t)ao->bounds [i].length + ao->bounds [i].lower_bound))
198 mono_raise_exception (mono_get_exception_index_out_of_range ());
200 pos = ind [0] - ao->bounds [0].lower_bound;
201 for (i = 1; i < ac->rank; i++)
202 pos = pos*ao->bounds [i].length + ind [i] -
203 ao->bounds [i].lower_bound;
205 return ves_icall_System_Array_GetValueImpl (this, pos);
209 ves_icall_System_Array_SetValueImpl (MonoArray *this, MonoObject *value, guint32 pos)
211 MonoClass *ac, *vc, *ec;
223 vc = value->vtable->klass;
227 ac = this->obj.vtable->klass;
228 ec = ac->element_class;
230 esize = mono_array_element_size (ac);
231 ea = (gpointer*)((char*)this->vector + (pos * esize));
232 va = (gpointer*)((char*)value + sizeof (MonoObject));
234 if (mono_class_is_nullable (ec)) {
235 mono_nullable_init ((guint8*)ea, value, ec);
240 mono_gc_bzero_atomic (ea, esize);
244 #define NO_WIDENING_CONVERSION G_STMT_START{\
245 mono_raise_exception (mono_get_exception_argument ( \
246 "value", "not a widening conversion")); \
249 #define CHECK_WIDENING_CONVERSION(extra) G_STMT_START{\
250 if (esize < vsize + (extra)) \
251 mono_raise_exception (mono_get_exception_argument ( \
252 "value", "not a widening conversion")); \
255 #define INVALID_CAST G_STMT_START{ \
256 mono_get_runtime_callbacks ()->set_cast_details (vc, ec); \
257 mono_raise_exception (mono_get_exception_invalid_cast ()); \
260 /* Check element (destination) type. */
261 switch (ec->byval_arg.type) {
262 case MONO_TYPE_STRING:
263 switch (vc->byval_arg.type) {
264 case MONO_TYPE_STRING:
270 case MONO_TYPE_BOOLEAN:
271 switch (vc->byval_arg.type) {
272 case MONO_TYPE_BOOLEAN:
285 NO_WIDENING_CONVERSION;
292 if (!ec->valuetype) {
293 if (!mono_object_isinst (value, ec))
295 mono_gc_wbarrier_set_arrayref (this, ea, (MonoObject*)value);
299 if (mono_object_isinst (value, ec)) {
300 if (ec->has_references)
301 mono_value_copy (ea, (char*)value + sizeof (MonoObject), ec);
303 mono_gc_memmove_atomic (ea, (char *)value + sizeof (MonoObject), esize);
310 vsize = mono_class_instance_size (vc) - sizeof (MonoObject);
312 et = ec->byval_arg.type;
313 if (et == MONO_TYPE_VALUETYPE && ec->byval_arg.data.klass->enumtype)
314 et = mono_class_enum_basetype (ec->byval_arg.data.klass)->type;
316 vt = vc->byval_arg.type;
317 if (vt == MONO_TYPE_VALUETYPE && vc->byval_arg.data.klass->enumtype)
318 vt = mono_class_enum_basetype (vc->byval_arg.data.klass)->type;
320 #define ASSIGN_UNSIGNED(etype) G_STMT_START{\
326 case MONO_TYPE_CHAR: \
327 CHECK_WIDENING_CONVERSION(0); \
328 *(etype *) ea = (etype) u64; \
330 /* You can't assign a signed value to an unsigned array. */ \
335 /* You can't assign a floating point number to an integer array. */ \
338 NO_WIDENING_CONVERSION; \
342 #define ASSIGN_SIGNED(etype) G_STMT_START{\
348 CHECK_WIDENING_CONVERSION(0); \
349 *(etype *) ea = (etype) i64; \
351 /* You can assign an unsigned value to a signed array if the array's */ \
352 /* element size is larger than the value size. */ \
357 case MONO_TYPE_CHAR: \
358 CHECK_WIDENING_CONVERSION(1); \
359 *(etype *) ea = (etype) u64; \
361 /* You can't assign a floating point number to an integer array. */ \
364 NO_WIDENING_CONVERSION; \
368 #define ASSIGN_REAL(etype) G_STMT_START{\
372 CHECK_WIDENING_CONVERSION(0); \
373 *(etype *) ea = (etype) r64; \
375 /* All integer values fit into a floating point array, so we don't */ \
376 /* need to CHECK_WIDENING_CONVERSION here. */ \
381 *(etype *) ea = (etype) i64; \
387 case MONO_TYPE_CHAR: \
388 *(etype *) ea = (etype) u64; \
395 u64 = *(guint8 *) va;
398 u64 = *(guint16 *) va;
401 u64 = *(guint32 *) va;
404 u64 = *(guint64 *) va;
410 i64 = *(gint16 *) va;
413 i64 = *(gint32 *) va;
416 i64 = *(gint64 *) va;
419 r64 = *(gfloat *) va;
422 r64 = *(gdouble *) va;
425 u64 = *(guint16 *) va;
427 case MONO_TYPE_BOOLEAN:
428 /* Boolean is only compatible with itself. */
441 NO_WIDENING_CONVERSION;
448 /* If we can't do a direct copy, let's try a widening conversion. */
451 ASSIGN_UNSIGNED (guint16);
453 ASSIGN_UNSIGNED (guint8);
455 ASSIGN_UNSIGNED (guint16);
457 ASSIGN_UNSIGNED (guint32);
459 ASSIGN_UNSIGNED (guint64);
461 ASSIGN_SIGNED (gint8);
463 ASSIGN_SIGNED (gint16);
465 ASSIGN_SIGNED (gint32);
467 ASSIGN_SIGNED (gint64);
469 ASSIGN_REAL (gfloat);
471 ASSIGN_REAL (gdouble);
475 /* Not reached, INVALID_CAST does not return. Just to avoid a compiler warning ... */
479 #undef NO_WIDENING_CONVERSION
480 #undef CHECK_WIDENING_CONVERSION
481 #undef ASSIGN_UNSIGNED
487 ves_icall_System_Array_SetValue (MonoArray *this, MonoObject *value,
495 MONO_CHECK_ARG_NULL (idxs);
497 ic = idxs->obj.vtable->klass;
498 ac = this->obj.vtable->klass;
500 g_assert (ic->rank == 1);
501 if (idxs->bounds != NULL || idxs->max_length != ac->rank)
502 mono_raise_exception (mono_get_exception_argument (NULL, NULL));
504 ind = (gint32 *)idxs->vector;
506 if (this->bounds == NULL) {
507 if (*ind < 0 || *ind >= this->max_length)
508 mono_raise_exception (mono_get_exception_index_out_of_range ());
510 ves_icall_System_Array_SetValueImpl (this, value, *ind);
514 for (i = 0; i < ac->rank; i++)
515 if ((ind [i] < this->bounds [i].lower_bound) ||
516 (ind [i] >= (mono_array_lower_bound_t)this->bounds [i].length + this->bounds [i].lower_bound))
517 mono_raise_exception (mono_get_exception_index_out_of_range ());
519 pos = ind [0] - this->bounds [0].lower_bound;
520 for (i = 1; i < ac->rank; i++)
521 pos = pos * this->bounds [i].length + ind [i] -
522 this->bounds [i].lower_bound;
524 ves_icall_System_Array_SetValueImpl (this, value, pos);
527 ICALL_EXPORT MonoArray *
528 ves_icall_System_Array_CreateInstanceImpl (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
530 MonoClass *aklass, *klass;
533 gboolean bounded = FALSE;
537 MONO_CHECK_ARG_NULL (type);
538 MONO_CHECK_ARG_NULL (lengths);
540 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
542 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
544 for (i = 0; i < mono_array_length (lengths); i++)
545 if (mono_array_get (lengths, gint32, i) < 0)
546 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
548 klass = mono_class_from_mono_type (type->type);
549 mono_class_init_or_throw (klass);
551 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint32, 0) != 0))
552 /* vectors are not the same as one dimensional arrays with no-zero bounds */
557 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
559 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
560 for (i = 0; i < aklass->rank; ++i) {
561 sizes [i] = mono_array_get (lengths, guint32, i);
563 sizes [i + aklass->rank] = mono_array_get (bounds, gint32, i);
565 sizes [i + aklass->rank] = 0;
568 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
573 ICALL_EXPORT MonoArray *
574 ves_icall_System_Array_CreateInstanceImpl64 (MonoReflectionType *type, MonoArray *lengths, MonoArray *bounds)
576 MonoClass *aklass, *klass;
579 gboolean bounded = FALSE;
583 MONO_CHECK_ARG_NULL (type);
584 MONO_CHECK_ARG_NULL (lengths);
586 MONO_CHECK_ARG (lengths, mono_array_length (lengths) > 0);
588 MONO_CHECK_ARG (bounds, mono_array_length (lengths) == mono_array_length (bounds));
590 for (i = 0; i < mono_array_length (lengths); i++)
591 if ((mono_array_get (lengths, gint64, i) < 0) ||
592 (mono_array_get (lengths, gint64, i) > MONO_ARRAY_MAX_INDEX))
593 mono_raise_exception (mono_get_exception_argument_out_of_range (NULL));
595 klass = mono_class_from_mono_type (type->type);
596 mono_class_init_or_throw (klass);
598 if (bounds && (mono_array_length (bounds) == 1) && (mono_array_get (bounds, gint64, 0) != 0))
599 /* vectors are not the same as one dimensional arrays with no-zero bounds */
604 aklass = mono_bounded_array_class_get (klass, mono_array_length (lengths), bounded);
606 sizes = alloca (aklass->rank * sizeof(intptr_t) * 2);
607 for (i = 0; i < aklass->rank; ++i) {
608 sizes [i] = mono_array_get (lengths, guint64, i);
610 sizes [i + aklass->rank] = (mono_array_size_t) mono_array_get (bounds, guint64, i);
612 sizes [i + aklass->rank] = 0;
615 array = mono_array_new_full (mono_object_domain (type), aklass, sizes, (intptr_t*)sizes + aklass->rank);
621 ves_icall_System_Array_GetRank (MonoObject *this)
625 return this->vtable->klass->rank;
629 ves_icall_System_Array_GetLength (MonoArray *this, gint32 dimension)
631 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
636 if ((dimension < 0) || (dimension >= rank))
637 mono_raise_exception (mono_get_exception_index_out_of_range ());
639 if (this->bounds == NULL)
640 length = this->max_length;
642 length = this->bounds [dimension].length;
644 #ifdef MONO_BIG_ARRAYS
645 if (length > G_MAXINT32)
646 mono_raise_exception (mono_get_exception_overflow ());
652 ves_icall_System_Array_GetLongLength (MonoArray *this, gint32 dimension)
654 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
658 if ((dimension < 0) || (dimension >= rank))
659 mono_raise_exception (mono_get_exception_index_out_of_range ());
661 if (this->bounds == NULL)
662 return this->max_length;
664 return this->bounds [dimension].length;
668 ves_icall_System_Array_GetLowerBound (MonoArray *this, gint32 dimension)
670 gint32 rank = ((MonoObject *)this)->vtable->klass->rank;
674 if ((dimension < 0) || (dimension >= rank))
675 mono_raise_exception (mono_get_exception_index_out_of_range ());
677 if (this->bounds == NULL)
680 return this->bounds [dimension].lower_bound;
684 ves_icall_System_Array_ClearInternal (MonoArray *arr, int idx, int length)
686 int sz = mono_array_element_size (mono_object_class (arr));
687 mono_gc_bzero_atomic (mono_array_addr_with_size_fast (arr, sz, idx), length * sz);
690 ICALL_EXPORT gboolean
691 ves_icall_System_Array_FastCopy (MonoArray *source, int source_idx, MonoArray* dest, int dest_idx, int length)
696 MonoVTable *src_vtable;
697 MonoVTable *dest_vtable;
698 MonoClass *src_class;
699 MonoClass *dest_class;
701 src_vtable = source->obj.vtable;
702 dest_vtable = dest->obj.vtable;
704 if (src_vtable->rank != dest_vtable->rank)
707 if (source->bounds || dest->bounds)
710 /* there's no integer overflow since mono_array_length returns an unsigned integer */
711 if ((dest_idx + length > mono_array_length_fast (dest)) ||
712 (source_idx + length > mono_array_length_fast (source)))
715 src_class = src_vtable->klass->element_class;
716 dest_class = dest_vtable->klass->element_class;
719 * Handle common cases.
722 /* Case1: object[] -> valuetype[] (ArrayList::ToArray)
723 We fallback to managed here since we need to typecheck each boxed valuetype before storing them in the dest array.
725 if (src_class == mono_defaults.object_class && dest_class->valuetype)
728 /* Check if we're copying a char[] <==> (u)short[] */
729 if (src_class != dest_class) {
730 if (dest_class->valuetype || dest_class->enumtype || src_class->valuetype || src_class->enumtype)
733 /* It's only safe to copy between arrays if we can ensure the source will always have a subtype of the destination. We bail otherwise. */
734 if (!mono_class_is_subclass_of (src_class, dest_class, FALSE))
738 if (dest_class->valuetype) {
739 element_size = mono_array_element_size (source->obj.vtable->klass);
740 source_addr = mono_array_addr_with_size_fast (source, element_size, source_idx);
741 if (dest_class->has_references) {
742 mono_value_copy_array (dest, dest_idx, source_addr, length);
744 dest_addr = mono_array_addr_with_size_fast (dest, element_size, dest_idx);
745 mono_gc_memmove_atomic (dest_addr, source_addr, element_size * length);
748 mono_array_memcpy_refs_fast (dest, dest_idx, source, source_idx, length);
755 ves_icall_System_Array_GetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
764 ao = (MonoArray *)this;
765 ac = (MonoClass *)ao->obj.vtable->klass;
767 esize = mono_array_element_size (ac);
768 ea = (gpointer*)((char*)ao->vector + (pos * esize));
770 mono_gc_memmove_atomic (value, ea, esize);
774 ves_icall_System_Array_SetGenericValueImpl (MonoObject *this, guint32 pos, gpointer value)
783 ao = (MonoArray *)this;
784 ac = (MonoClass *)ao->obj.vtable->klass;
785 ec = ac->element_class;
787 esize = mono_array_element_size (ac);
788 ea = (gpointer*)((char*)ao->vector + (pos * esize));
790 if (MONO_TYPE_IS_REFERENCE (&ec->byval_arg)) {
791 g_assert (esize == sizeof (gpointer));
792 mono_gc_wbarrier_generic_store (ea, *(gpointer*)value);
794 g_assert (ec->inited);
795 g_assert (esize == mono_class_value_size (ec, NULL));
796 if (ec->has_references)
797 mono_gc_wbarrier_value_copy (ea, value, 1, ec);
799 mono_gc_memmove_atomic (ea, value, esize);
804 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_InitializeArray (MonoArray *array, MonoClassField *field_handle)
806 MonoClass *klass = array->obj.vtable->klass;
807 guint32 size = mono_array_element_size (klass);
808 MonoType *type = mono_type_get_underlying_type (&klass->element_class->byval_arg);
810 const char *field_data;
812 if (MONO_TYPE_IS_REFERENCE (type) || type->type == MONO_TYPE_VALUETYPE) {
813 MonoException *exc = mono_get_exception_argument("array",
814 "Cannot initialize array of non-primitive type.");
815 mono_raise_exception (exc);
818 if (!(field_handle->type->attrs & FIELD_ATTRIBUTE_HAS_FIELD_RVA)) {
819 MonoException *exc = mono_get_exception_argument("field_handle",
820 "Field doesn't have an RVA");
821 mono_raise_exception (exc);
824 size *= array->max_length;
825 field_data = mono_field_get_data (field_handle);
827 if (size > mono_type_size (field_handle->type, &align)) {
828 MonoException *exc = mono_get_exception_argument("field_handle",
829 "Field not large enough to fill array");
830 mono_raise_exception (exc);
833 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
835 guint ## n *data = (guint ## n *) mono_array_addr (array, char, 0); \
836 guint ## n *src = (guint ## n *) field_data; \
837 guint ## n *end = (guint ## n *)((char*)src + size); \
839 for (; src < end; data++, src++) { \
840 *data = read ## n (src); \
844 /* printf ("Initialize array with elements of %s type\n", klass->element_class->name); */
846 switch (type->type) {
863 memcpy (mono_array_addr (array, char, 0), field_data, size);
867 memcpy (mono_array_addr (array, char, 0), field_data, size);
872 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetOffsetToStringData (void)
876 return offsetof (MonoString, chars);
879 ICALL_EXPORT MonoObject *
880 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_GetObjectValue (MonoObject *obj)
884 if ((obj == NULL) || (! (obj->vtable->klass->valuetype)))
887 return mono_object_clone (obj);
891 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunClassConstructor (MonoType *handle)
896 MONO_CHECK_ARG_NULL (handle);
898 klass = mono_class_from_mono_type (handle);
899 MONO_CHECK_ARG (handle, klass);
901 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
903 /* This will call the type constructor */
904 mono_runtime_class_init (vtable);
908 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_RunModuleConstructor (MonoImage *image)
912 mono_image_check_for_module_cctor (image);
913 if (image->has_module_cctor) {
914 MonoClass *module_klass = mono_class_get_checked (image, MONO_TOKEN_TYPE_DEF | 1, &error);
915 mono_error_raise_exception (&error);
916 /*It's fine to raise the exception here*/
917 mono_runtime_class_init (mono_class_vtable_full (mono_domain_get (), module_klass, TRUE));
921 ICALL_EXPORT MonoBoolean
922 ves_icall_System_Runtime_CompilerServices_RuntimeHelpers_SufficientExecutionStack (void)
927 /* later make this configurable and per-arch */
928 int min_size = 4096 * 4 * sizeof (void*);
929 mono_thread_info_get_stack_bounds (&stack_addr, &stack_size);
930 /* if we have no info we are optimistic and assume there is enough room */
934 // FIXME: Windows dynamically extends the stack, so stack_addr might be close
938 current = (guint8 *)&stack_addr;
939 if (current > stack_addr) {
940 if ((current - stack_addr) < min_size)
943 if (current - (stack_addr - stack_size) < min_size)
949 ICALL_EXPORT MonoObject *
950 ves_icall_System_Object_MemberwiseClone (MonoObject *this)
954 return mono_object_clone (this);
958 ves_icall_System_ValueType_InternalGetHashCode (MonoObject *this, MonoArray **fields)
961 MonoObject **values = NULL;
964 gint32 result = (int)(gsize)mono_defaults.int32_class;
965 MonoClassField* field;
970 klass = mono_object_class (this);
972 if (mono_class_num_fields (klass) == 0)
976 * Compute the starting value of the hashcode for fields of primitive
977 * types, and return the remaining fields in an array to the managed side.
978 * This way, we can avoid costly reflection operations in managed code.
981 while ((field = mono_class_get_fields (klass, &iter))) {
982 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
984 if (mono_field_is_deleted (field))
986 /* FIXME: Add more types */
987 switch (field->type->type) {
989 result ^= *(gint32*)((guint8*)this + field->offset);
991 case MONO_TYPE_STRING: {
993 s = *(MonoString**)((guint8*)this + field->offset);
995 result ^= mono_string_hash (s);
1000 values = g_newa (MonoObject*, mono_class_num_fields (klass));
1001 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1002 values [count++] = o;
1008 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1009 for (i = 0; i < count; ++i)
1010 mono_array_setref (*fields, i, values [i]);
1017 ICALL_EXPORT MonoBoolean
1018 ves_icall_System_ValueType_Equals (MonoObject *this, MonoObject *that, MonoArray **fields)
1021 MonoObject **values = NULL;
1023 MonoClassField* field;
1027 MONO_ARCH_SAVE_REGS;
1029 MONO_CHECK_ARG_NULL (that);
1031 if (this->vtable != that->vtable)
1034 klass = mono_object_class (this);
1036 if (klass->enumtype && mono_class_enum_basetype (klass) && mono_class_enum_basetype (klass)->type == MONO_TYPE_I4)
1037 return (*(gint32*)((guint8*)this + sizeof (MonoObject)) == *(gint32*)((guint8*)that + sizeof (MonoObject)));
1040 * Do the comparison for fields of primitive type and return a result if
1041 * possible. Otherwise, return the remaining fields in an array to the
1042 * managed side. This way, we can avoid costly reflection operations in
1047 while ((field = mono_class_get_fields (klass, &iter))) {
1048 if (field->type->attrs & FIELD_ATTRIBUTE_STATIC)
1050 if (mono_field_is_deleted (field))
1052 /* FIXME: Add more types */
1053 switch (field->type->type) {
1056 case MONO_TYPE_BOOLEAN:
1057 if (*((guint8*)this + field->offset) != *((guint8*)that + field->offset))
1062 case MONO_TYPE_CHAR:
1063 if (*(gint16*)((guint8*)this + field->offset) != *(gint16*)((guint8*)that + field->offset))
1068 if (*(gint32*)((guint8*)this + field->offset) != *(gint32*)((guint8*)that + field->offset))
1073 if (*(gint64*)((guint8*)this + field->offset) != *(gint64*)((guint8*)that + field->offset))
1077 if (*(float*)((guint8*)this + field->offset) != *(float*)((guint8*)that + field->offset))
1081 if (*(double*)((guint8*)this + field->offset) != *(double*)((guint8*)that + field->offset))
1086 case MONO_TYPE_STRING: {
1087 MonoString *s1, *s2;
1088 guint32 s1len, s2len;
1089 s1 = *(MonoString**)((guint8*)this + field->offset);
1090 s2 = *(MonoString**)((guint8*)that + field->offset);
1093 if ((s1 == NULL) || (s2 == NULL))
1095 s1len = mono_string_length (s1);
1096 s2len = mono_string_length (s2);
1100 if (memcmp (mono_string_chars (s1), mono_string_chars (s2), s1len * sizeof (gunichar2)) != 0)
1106 values = g_newa (MonoObject*, mono_class_num_fields (klass) * 2);
1107 o = mono_field_get_value_object (mono_object_domain (this), field, this);
1108 values [count++] = o;
1109 o = mono_field_get_value_object (mono_object_domain (this), field, that);
1110 values [count++] = o;
1113 if (klass->enumtype)
1114 /* enums only have one non-static field */
1120 mono_gc_wbarrier_generic_store (fields, (MonoObject*) mono_array_new (mono_domain_get (), mono_defaults.object_class, count));
1121 for (i = 0; i < count; ++i)
1122 mono_array_setref_fast (*fields, i, values [i]);
1129 ICALL_EXPORT MonoReflectionType *
1130 ves_icall_System_Object_GetType (MonoObject *obj)
1132 MONO_ARCH_SAVE_REGS;
1134 #ifndef DISABLE_REMOTING
1135 if (obj->vtable->klass == mono_defaults.transparent_proxy_class)
1136 return mono_type_get_object (mono_object_domain (obj), &((MonoTransparentProxy*)obj)->remote_class->proxy_class->byval_arg);
1139 return mono_type_get_object (mono_object_domain (obj), &obj->vtable->klass->byval_arg);
1143 mono_type_type_from_obj (MonoReflectionType *mtype, MonoObject *obj)
1145 MONO_ARCH_SAVE_REGS;
1147 mtype->type = &obj->vtable->klass->byval_arg;
1148 g_assert (mtype->type->type);
1152 ves_icall_ModuleBuilder_getToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, gboolean create_open_instance)
1154 MONO_ARCH_SAVE_REGS;
1156 MONO_CHECK_ARG_NULL (obj);
1158 return mono_image_create_token (mb->dynamic_image, obj, create_open_instance, TRUE);
1162 ves_icall_ModuleBuilder_getMethodToken (MonoReflectionModuleBuilder *mb,
1163 MonoReflectionMethod *method,
1164 MonoArray *opt_param_types)
1166 MONO_ARCH_SAVE_REGS;
1168 MONO_CHECK_ARG_NULL (method);
1170 return mono_image_create_method_token (
1171 mb->dynamic_image, (MonoObject *) method, opt_param_types);
1175 ves_icall_ModuleBuilder_WriteToFile (MonoReflectionModuleBuilder *mb, HANDLE file)
1177 MONO_ARCH_SAVE_REGS;
1179 mono_image_create_pefile (mb, file);
1183 ves_icall_ModuleBuilder_build_metadata (MonoReflectionModuleBuilder *mb)
1185 MONO_ARCH_SAVE_REGS;
1187 mono_image_build_metadata (mb);
1191 ves_icall_ModuleBuilder_RegisterToken (MonoReflectionModuleBuilder *mb, MonoObject *obj, guint32 token)
1193 MONO_ARCH_SAVE_REGS;
1195 mono_image_register_token (mb->dynamic_image, token, obj);
1199 get_caller (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1201 MonoMethod **dest = data;
1203 /* skip unmanaged frames */
1219 get_executing (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1221 MonoMethod **dest = data;
1223 /* skip unmanaged frames */
1228 if (!strcmp (m->klass->name_space, "System.Reflection"))
1237 get_caller_no_reflection (MonoMethod *m, gint32 no, gint32 ilo, gboolean managed, gpointer data)
1239 MonoMethod **dest = data;
1241 /* skip unmanaged frames */
1245 if (m->wrapper_type != MONO_WRAPPER_NONE)
1248 if (m->klass->image == mono_defaults.corlib && !strcmp (m->klass->name_space, "System.Reflection"))
1262 static MonoReflectionType *
1263 type_from_name (const char *str, MonoBoolean ignoreCase)
1265 MonoMethod *m, *dest;
1267 MonoType *type = NULL;
1268 MonoAssembly *assembly = NULL;
1269 MonoTypeNameParse info;
1270 char *temp_str = g_strdup (str);
1271 gboolean type_resolve = FALSE;
1273 MONO_ARCH_SAVE_REGS;
1275 /* mono_reflection_parse_type() mangles the string */
1276 if (!mono_reflection_parse_type (temp_str, &info)) {
1277 mono_reflection_free_type_info (&info);
1284 * We must compute the calling assembly as type loading must happen under a metadata context.
1285 * For example. The main assembly is a.exe and Type.GetType is called from dir/b.dll. Without
1286 * the metadata context (basedir currently) set to dir/b.dll we won't be able to load a dir/c.dll.
1288 m = mono_method_get_last_managed ();
1291 mono_stack_walk_no_il (get_caller_no_reflection, &dest);
1296 * FIXME: mono_method_get_last_managed() sometimes returns NULL, thus
1297 * causing ves_icall_System_Reflection_Assembly_GetCallingAssembly()
1298 * to crash. This only seems to happen in some strange remoting
1299 * scenarios and I was unable to figure out what's happening there.
1300 * Dec 10, 2005 - Martin.
1304 assembly = dest->klass->image->assembly;
1305 type_resolve = TRUE;
1307 g_warning (G_STRLOC);
1310 if (info.assembly.name)
1311 assembly = mono_assembly_load (&info.assembly, assembly ? assembly->basedir : NULL, NULL);
1315 /* When loading from the current assembly, AppDomain.TypeResolve will not be called yet */
1316 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1319 if (!info.assembly.name && !type) /* try mscorlib */
1320 type = mono_reflection_get_type (NULL, &info, ignoreCase, &type_resolve);
1322 if (assembly && !type && type_resolve) {
1323 type_resolve = FALSE; /* This will invoke TypeResolve if not done in the first 'if' */
1324 type = mono_reflection_get_type (assembly->image, &info, ignoreCase, &type_resolve);
1327 mono_reflection_free_type_info (&info);
1333 return mono_type_get_object (mono_domain_get (), type);
1337 MonoReflectionType *
1338 mono_type_get (const char *str)
1340 char *copy = g_strdup (str);
1341 MonoReflectionType *type = type_from_name (copy, FALSE);
1348 ICALL_EXPORT MonoReflectionType*
1349 ves_icall_type_from_name (MonoString *name,
1350 MonoBoolean throwOnError,
1351 MonoBoolean ignoreCase)
1353 char *str = mono_string_to_utf8 (name);
1354 MonoReflectionType *type;
1356 type = type_from_name (str, ignoreCase);
1359 MonoException *e = NULL;
1362 e = mono_get_exception_type_load (name, NULL);
1364 mono_loader_clear_error ();
1366 mono_raise_exception (e);
1373 ICALL_EXPORT MonoReflectionType*
1374 ves_icall_type_from_handle (MonoType *handle)
1376 MonoDomain *domain = mono_domain_get ();
1378 MONO_ARCH_SAVE_REGS;
1380 return mono_type_get_object (domain, handle);
1383 ICALL_EXPORT MonoBoolean
1384 ves_icall_System_Type_EqualsInternal (MonoReflectionType *type, MonoReflectionType *c)
1386 MONO_ARCH_SAVE_REGS;
1388 if (c && type->type && c->type)
1389 return mono_metadata_type_equal (type->type, c->type);
1391 return (type == c) ? TRUE : FALSE;
1394 /* System.TypeCode */
1413 TYPECODE_STRING = 18
1416 ICALL_EXPORT guint32
1417 ves_icall_type_GetTypeCodeInternal (MonoReflectionType *type)
1419 int t = type->type->type;
1421 MONO_ARCH_SAVE_REGS;
1423 if (type->type->byref)
1424 return TYPECODE_OBJECT;
1428 case MONO_TYPE_VOID:
1429 return TYPECODE_OBJECT;
1430 case MONO_TYPE_BOOLEAN:
1431 return TYPECODE_BOOLEAN;
1433 return TYPECODE_BYTE;
1435 return TYPECODE_SBYTE;
1437 return TYPECODE_UINT16;
1439 return TYPECODE_INT16;
1440 case MONO_TYPE_CHAR:
1441 return TYPECODE_CHAR;
1445 return TYPECODE_OBJECT;
1447 return TYPECODE_UINT32;
1449 return TYPECODE_INT32;
1451 return TYPECODE_UINT64;
1453 return TYPECODE_INT64;
1455 return TYPECODE_SINGLE;
1457 return TYPECODE_DOUBLE;
1458 case MONO_TYPE_VALUETYPE: {
1459 MonoClass *klass = type->type->data.klass;
1461 if (klass->enumtype) {
1462 t = mono_class_enum_basetype (klass)->type;
1464 } else if (mono_is_corlib_image (klass->image)) {
1465 if (strcmp (klass->name_space, "System") == 0) {
1466 if (strcmp (klass->name, "Decimal") == 0)
1467 return TYPECODE_DECIMAL;
1468 else if (strcmp (klass->name, "DateTime") == 0)
1469 return TYPECODE_DATETIME;
1472 return TYPECODE_OBJECT;
1474 case MONO_TYPE_STRING:
1475 return TYPECODE_STRING;
1476 case MONO_TYPE_SZARRAY:
1477 case MONO_TYPE_ARRAY:
1478 case MONO_TYPE_OBJECT:
1480 case MONO_TYPE_MVAR:
1481 case MONO_TYPE_TYPEDBYREF:
1482 return TYPECODE_OBJECT;
1483 case MONO_TYPE_CLASS:
1485 MonoClass *klass = type->type->data.klass;
1486 if (klass->image == mono_defaults.corlib && strcmp (klass->name_space, "System") == 0) {
1487 if (strcmp (klass->name, "DBNull") == 0)
1488 return TYPECODE_DBNULL;
1491 return TYPECODE_OBJECT;
1492 case MONO_TYPE_GENERICINST:
1493 return TYPECODE_OBJECT;
1495 g_error ("type 0x%02x not handled in GetTypeCode()", t);
1500 ICALL_EXPORT guint32
1501 ves_icall_type_is_subtype_of (MonoReflectionType *type, MonoReflectionType *c, MonoBoolean check_interfaces)
1507 MONO_ARCH_SAVE_REGS;
1509 g_assert (type != NULL);
1511 domain = ((MonoObject *)type)->vtable->domain;
1513 if (!c) /* FIXME: dont know what do do here */
1516 klass = mono_class_from_mono_type (type->type);
1517 klassc = mono_class_from_mono_type (c->type);
1519 /* Interface check requires a more complex setup so we
1520 * only do for them. Otherwise we simply avoid mono_class_init.
1522 if (check_interfaces) {
1523 mono_class_init_or_throw (klass);
1524 mono_class_init_or_throw (klassc);
1525 } else if (!klass->supertypes || !klassc->supertypes) {
1526 mono_class_setup_supertypes (klass);
1527 mono_class_setup_supertypes (klassc);
1530 if (type->type->byref)
1531 return klassc == mono_defaults.object_class;
1533 return mono_class_is_subclass_of (klass, klassc, check_interfaces);
1537 mono_type_is_primitive (MonoType *type)
1539 return (type->type >= MONO_TYPE_BOOLEAN && type->type <= MONO_TYPE_R8) ||
1540 type-> type == MONO_TYPE_I || type->type == MONO_TYPE_U;
1544 mono_type_get_underlying_type_ignore_byref (MonoType *type)
1546 if (type->type == MONO_TYPE_VALUETYPE && type->data.klass->enumtype)
1547 return mono_class_enum_basetype (type->data.klass);
1548 if (type->type == MONO_TYPE_GENERICINST && type->data.generic_class->container_class->enumtype)
1549 return mono_class_enum_basetype (type->data.generic_class->container_class);
1553 ICALL_EXPORT guint32
1554 ves_icall_type_is_assignable_from (MonoReflectionType *type, MonoReflectionType *c)
1560 MONO_ARCH_SAVE_REGS;
1562 g_assert (type != NULL);
1564 domain = ((MonoObject *)type)->vtable->domain;
1566 klass = mono_class_from_mono_type (type->type);
1567 klassc = mono_class_from_mono_type (c->type);
1569 if (type->type->byref ^ c->type->byref)
1572 if (type->type->byref) {
1573 MonoType *t = mono_type_get_underlying_type_ignore_byref (type->type);
1574 MonoType *ot = mono_type_get_underlying_type_ignore_byref (c->type);
1576 klass = mono_class_from_mono_type (t);
1577 klassc = mono_class_from_mono_type (ot);
1579 if (mono_type_is_primitive (t)) {
1580 return mono_type_is_primitive (ot) && klass->instance_size == klassc->instance_size;
1581 } else if (t->type == MONO_TYPE_VAR || t->type == MONO_TYPE_MVAR) {
1582 return t->type == ot->type && t->data.generic_param->num == ot->data.generic_param->num;
1583 } else if (t->type == MONO_TYPE_PTR || t->type == MONO_TYPE_FNPTR) {
1584 return t->type == ot->type;
1586 if (ot->type == MONO_TYPE_VAR || ot->type == MONO_TYPE_MVAR)
1589 if (klass->valuetype)
1590 return klass == klassc;
1591 return klass->valuetype == klassc->valuetype;
1594 return mono_class_is_assignable_from (klass, klassc);
1597 ICALL_EXPORT guint32
1598 ves_icall_type_IsInstanceOfType (MonoReflectionType *type, MonoObject *obj)
1600 MonoClass *klass = mono_class_from_mono_type (type->type);
1601 mono_class_init_or_throw (klass);
1602 return mono_object_isinst (obj, klass) != NULL;
1605 ICALL_EXPORT guint32
1606 ves_icall_get_attributes (MonoReflectionType *type)
1608 MonoClass *klass = mono_class_from_mono_type (type->type);
1609 return klass->flags;
1612 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1613 ves_icall_System_Reflection_FieldInfo_get_marshal_info (MonoReflectionField *field)
1615 MonoClass *klass = field->field->parent;
1616 MonoMarshalType *info;
1620 if (klass->generic_container ||
1621 (klass->generic_class && klass->generic_class->context.class_inst->is_open))
1624 ftype = mono_field_get_type (field->field);
1625 if (ftype && !(ftype->attrs & FIELD_ATTRIBUTE_HAS_FIELD_MARSHAL))
1628 info = mono_marshal_load_type_info (klass);
1630 for (i = 0; i < info->num_fields; ++i) {
1631 if (info->fields [i].field == field->field) {
1632 if (!info->fields [i].mspec)
1635 return mono_reflection_marshal_as_attribute_from_marshal_spec (field->object.vtable->domain, klass, info->fields [i].mspec);
1642 ICALL_EXPORT MonoReflectionField*
1643 ves_icall_System_Reflection_FieldInfo_internal_from_handle_type (MonoClassField *handle, MonoType *type)
1645 gboolean found = FALSE;
1652 klass = handle->parent;
1654 klass = mono_class_from_mono_type (type);
1656 /* Check that the field belongs to the class */
1657 for (k = klass; k; k = k->parent) {
1658 if (k == handle->parent) {
1665 /* The managed code will throw the exception */
1669 return mono_field_get_object (mono_domain_get (), klass, handle);
1672 ICALL_EXPORT MonoArray*
1673 ves_icall_System_Reflection_FieldInfo_GetTypeModifiers (MonoReflectionField *field, MonoBoolean optional)
1676 MonoType *type = mono_field_get_type_checked (field->field, &error);
1677 mono_error_raise_exception (&error);
1679 return type_array_from_modifiers (field->field->parent->image, type, optional);
1683 vell_icall_get_method_attributes (MonoMethod *method)
1685 return method->flags;
1689 ves_icall_get_method_info (MonoMethod *method, MonoMethodInfo *info)
1692 MonoDomain *domain = mono_domain_get ();
1693 MonoMethodSignature* sig;
1694 MONO_ARCH_SAVE_REGS;
1696 sig = mono_method_signature_checked (method, &error);
1697 if (!mono_error_ok (&error))
1698 mono_error_raise_exception (&error);
1701 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &method->klass->byval_arg));
1702 MONO_STRUCT_SETREF (info, ret, mono_type_get_object (domain, sig->ret));
1703 info->attrs = method->flags;
1704 info->implattrs = method->iflags;
1705 if (sig->call_convention == MONO_CALL_DEFAULT)
1706 info->callconv = sig->sentinelpos >= 0 ? 2 : 1;
1708 if (sig->call_convention == MONO_CALL_VARARG || sig->sentinelpos >= 0)
1713 info->callconv |= (sig->hasthis << 5) | (sig->explicit_this << 6);
1716 ICALL_EXPORT MonoArray*
1717 ves_icall_get_parameter_info (MonoMethod *method, MonoReflectionMethod *member)
1719 MonoDomain *domain = mono_domain_get ();
1721 return mono_param_get_objects_internal (domain, method, member->reftype ? mono_class_from_mono_type (member->reftype->type) : NULL);
1724 ICALL_EXPORT MonoReflectionMarshalAsAttribute*
1725 ves_icall_System_MonoMethodInfo_get_retval_marshal (MonoMethod *method)
1727 MonoDomain *domain = mono_domain_get ();
1728 MonoReflectionMarshalAsAttribute* res = NULL;
1729 MonoMarshalSpec **mspecs;
1732 mspecs = g_new (MonoMarshalSpec*, mono_method_signature (method)->param_count + 1);
1733 mono_method_get_marshal_info (method, mspecs);
1736 res = mono_reflection_marshal_as_attribute_from_marshal_spec (domain, method->klass, mspecs [0]);
1738 for (i = mono_method_signature (method)->param_count; i >= 0; i--)
1740 mono_metadata_free_marshal_spec (mspecs [i]);
1747 ves_icall_MonoField_GetFieldOffset (MonoReflectionField *field)
1749 MonoClass *parent = field->field->parent;
1750 if (!parent->size_inited)
1751 mono_class_init (parent);
1752 mono_class_setup_fields_locking (parent);
1754 return field->field->offset - sizeof (MonoObject);
1757 ICALL_EXPORT MonoReflectionType*
1758 ves_icall_MonoField_GetParentType (MonoReflectionField *field, MonoBoolean declaring)
1761 MONO_ARCH_SAVE_REGS;
1763 parent = declaring? field->field->parent: field->klass;
1765 return mono_type_get_object (mono_object_domain (field), &parent->byval_arg);
1768 ICALL_EXPORT MonoObject *
1769 ves_icall_MonoField_GetValueInternal (MonoReflectionField *field, MonoObject *obj)
1771 MonoClass *fklass = field->klass;
1772 MonoClassField *cf = field->field;
1773 MonoDomain *domain = mono_object_domain (field);
1775 if (fklass->image->assembly->ref_only)
1776 mono_raise_exception (mono_get_exception_invalid_operation (
1777 "It is illegal to get the value on a field on a type loaded using the ReflectionOnly methods."));
1779 if (mono_security_core_clr_enabled ())
1780 mono_security_core_clr_ensure_reflection_access_field (cf);
1782 return mono_field_get_value_object (domain, cf, obj);
1786 ves_icall_MonoField_SetValueInternal (MonoReflectionField *field, MonoObject *obj, MonoObject *value)
1789 MonoClassField *cf = field->field;
1793 MONO_ARCH_SAVE_REGS;
1795 if (field->klass->image->assembly->ref_only)
1796 mono_raise_exception (mono_get_exception_invalid_operation (
1797 "It is illegal to set the value on a field on a type loaded using the ReflectionOnly methods."));
1799 if (mono_security_core_clr_enabled ())
1800 mono_security_core_clr_ensure_reflection_access_field (cf);
1802 type = mono_field_get_type_checked (cf, &error);
1803 if (!mono_error_ok (&error))
1804 mono_error_raise_exception (&error);
1806 v = (gchar *) value;
1808 switch (type->type) {
1811 case MONO_TYPE_BOOLEAN:
1814 case MONO_TYPE_CHAR:
1823 case MONO_TYPE_VALUETYPE:
1826 v += sizeof (MonoObject);
1828 case MONO_TYPE_STRING:
1829 case MONO_TYPE_OBJECT:
1830 case MONO_TYPE_CLASS:
1831 case MONO_TYPE_ARRAY:
1832 case MONO_TYPE_SZARRAY:
1835 case MONO_TYPE_GENERICINST: {
1836 MonoGenericClass *gclass = type->data.generic_class;
1837 g_assert (!gclass->context.class_inst->is_open);
1839 if (mono_class_is_nullable (mono_class_from_mono_type (type))) {
1840 MonoClass *nklass = mono_class_from_mono_type (type);
1841 MonoObject *nullable;
1844 * Convert the boxed vtype into a Nullable structure.
1845 * This is complicated by the fact that Nullables have
1846 * a variable structure.
1848 nullable = mono_object_new (mono_domain_get (), nklass);
1850 mono_nullable_init (mono_object_unbox (nullable), value, nklass);
1852 v = mono_object_unbox (nullable);
1855 if (gclass->container_class->valuetype && (v != NULL))
1856 v += sizeof (MonoObject);
1860 g_error ("type 0x%x not handled in "
1861 "ves_icall_FieldInfo_SetValueInternal", type->type);
1866 if (type->attrs & FIELD_ATTRIBUTE_STATIC) {
1867 MonoVTable *vtable = mono_class_vtable_full (mono_object_domain (field), cf->parent, TRUE);
1868 if (!vtable->initialized)
1869 mono_runtime_class_init (vtable);
1870 mono_field_static_set_value (vtable, cf, v);
1872 mono_field_set_value (obj, cf, v);
1876 ICALL_EXPORT MonoObject *
1877 ves_icall_MonoField_GetRawConstantValue (MonoReflectionField *this)
1879 MonoObject *o = NULL;
1880 MonoClassField *field = this->field;
1882 MonoDomain *domain = mono_object_domain (this);
1884 MonoTypeEnum def_type;
1885 const char *def_value;
1889 MONO_ARCH_SAVE_REGS;
1891 mono_class_init (field->parent);
1893 t = mono_field_get_type_checked (field, &error);
1894 if (!mono_error_ok (&error))
1895 mono_error_raise_exception (&error);
1897 if (!(t->attrs & FIELD_ATTRIBUTE_HAS_DEFAULT))
1898 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1900 if (image_is_dynamic (field->parent->image)) {
1901 MonoClass *klass = field->parent;
1902 int fidx = field - klass->fields;
1904 g_assert (fidx >= 0 && fidx < klass->field.count);
1905 g_assert (klass->ext);
1906 g_assert (klass->ext->field_def_values);
1907 def_type = klass->ext->field_def_values [fidx].def_type;
1908 def_value = klass->ext->field_def_values [fidx].data;
1910 def_value = mono_class_get_field_default_value (field, &def_type);
1911 /* FIXME, maybe we should try to raise TLE if field->parent is broken */
1913 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
1916 /*FIXME unify this with reflection.c:mono_get_object_from_blob*/
1920 case MONO_TYPE_BOOLEAN:
1923 case MONO_TYPE_CHAR:
1931 case MONO_TYPE_R8: {
1934 /* boxed value type */
1935 t = g_new0 (MonoType, 1);
1937 klass = mono_class_from_mono_type (t);
1939 o = mono_object_new (domain, klass);
1940 v = ((gchar *) o) + sizeof (MonoObject);
1941 mono_get_constant_value_from_blob (domain, def_type, def_value, v);
1944 case MONO_TYPE_STRING:
1945 case MONO_TYPE_CLASS:
1946 mono_get_constant_value_from_blob (domain, def_type, def_value, &o);
1949 g_assert_not_reached ();
1955 ICALL_EXPORT MonoReflectionType*
1956 ves_icall_MonoField_ResolveType (MonoReflectionField *ref_field)
1959 MonoClassField *field = ref_field->field;
1960 MonoType *type = mono_field_get_type_checked (field, &error);
1961 if (!mono_error_ok (&error))
1962 mono_error_raise_exception (&error);
1963 return mono_type_get_object (mono_object_domain (ref_field), type);
1966 ICALL_EXPORT MonoReflectionType*
1967 ves_icall_MonoGenericMethod_get_ReflectedType (MonoReflectionGenericMethod *rmethod)
1969 MonoMethod *method = rmethod->method.method;
1971 return mono_type_get_object (mono_object_domain (rmethod), &method->klass->byval_arg);
1974 /* From MonoProperty.cs */
1976 PInfo_Attributes = 1,
1977 PInfo_GetMethod = 1 << 1,
1978 PInfo_SetMethod = 1 << 2,
1979 PInfo_ReflectedType = 1 << 3,
1980 PInfo_DeclaringType = 1 << 4,
1985 ves_icall_get_property_info (MonoReflectionProperty *property, MonoPropertyInfo *info, PInfo req_info)
1987 MonoDomain *domain = mono_object_domain (property);
1989 MONO_ARCH_SAVE_REGS;
1991 if ((req_info & PInfo_ReflectedType) != 0)
1992 MONO_STRUCT_SETREF (info, parent, mono_type_get_object (domain, &property->klass->byval_arg));
1993 if ((req_info & PInfo_DeclaringType) != 0)
1994 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &property->property->parent->byval_arg));
1996 if ((req_info & PInfo_Name) != 0)
1997 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, property->property->name));
1999 if ((req_info & PInfo_Attributes) != 0)
2000 info->attrs = property->property->attrs;
2002 if ((req_info & PInfo_GetMethod) != 0)
2003 MONO_STRUCT_SETREF (info, get, property->property->get ?
2004 mono_method_get_object (domain, property->property->get, property->klass): NULL);
2006 if ((req_info & PInfo_SetMethod) != 0)
2007 MONO_STRUCT_SETREF (info, set, property->property->set ?
2008 mono_method_get_object (domain, property->property->set, property->klass): NULL);
2010 * There may be other methods defined for properties, though, it seems they are not exposed
2011 * in the reflection API
2016 ves_icall_get_event_info (MonoReflectionMonoEvent *event, MonoEventInfo *info)
2018 MonoDomain *domain = mono_object_domain (event);
2020 MONO_ARCH_SAVE_REGS;
2022 MONO_STRUCT_SETREF (info, reflected_type, mono_type_get_object (domain, &event->klass->byval_arg));
2023 MONO_STRUCT_SETREF (info, declaring_type, mono_type_get_object (domain, &event->event->parent->byval_arg));
2025 MONO_STRUCT_SETREF (info, name, mono_string_new (domain, event->event->name));
2026 info->attrs = event->event->attrs;
2027 MONO_STRUCT_SETREF (info, add_method, event->event->add ? mono_method_get_object (domain, event->event->add, NULL): NULL);
2028 MONO_STRUCT_SETREF (info, remove_method, event->event->remove ? mono_method_get_object (domain, event->event->remove, NULL): NULL);
2029 MONO_STRUCT_SETREF (info, raise_method, event->event->raise ? mono_method_get_object (domain, event->event->raise, NULL): NULL);
2031 #ifndef MONO_SMALL_CONFIG
2032 if (event->event->other) {
2034 while (event->event->other [n])
2036 MONO_STRUCT_SETREF (info, other_methods, mono_array_new (domain, mono_defaults.method_info_class, n));
2038 for (i = 0; i < n; i++)
2039 mono_array_setref (info->other_methods, i, mono_method_get_object (domain, event->event->other [i], NULL));
2045 collect_interfaces (MonoClass *klass, GHashTable *ifaces, MonoError *error)
2050 mono_class_setup_interfaces (klass, error);
2051 if (!mono_error_ok (error))
2054 for (i = 0; i < klass->interface_count; i++) {
2055 ic = klass->interfaces [i];
2056 g_hash_table_insert (ifaces, ic, ic);
2058 collect_interfaces (ic, ifaces, error);
2059 if (!mono_error_ok (error))
2065 MonoArray *iface_array;
2066 MonoGenericContext *context;
2070 } FillIfaceArrayData;
2073 fill_iface_array (gpointer key, gpointer value, gpointer user_data)
2075 FillIfaceArrayData *data = user_data;
2076 MonoClass *ic = key;
2077 MonoType *ret = &ic->byval_arg, *inflated = NULL;
2079 if (!mono_error_ok (data->error))
2082 if (data->context && ic->generic_class && ic->generic_class->context.class_inst->is_open) {
2083 inflated = ret = mono_class_inflate_generic_type_checked (ret, data->context, data->error);
2084 if (!mono_error_ok (data->error))
2088 mono_array_setref (data->iface_array, data->next_idx++, mono_type_get_object (data->domain, ret));
2091 mono_metadata_free_type (inflated);
2094 ICALL_EXPORT MonoArray*
2095 ves_icall_Type_GetInterfaces (MonoReflectionType* type)
2098 MonoClass *class = mono_class_from_mono_type (type->type);
2100 FillIfaceArrayData data = { 0 };
2103 GHashTable *iface_hash = g_hash_table_new (NULL, NULL);
2105 if (class->generic_class && class->generic_class->context.class_inst->is_open) {
2106 data.context = mono_class_get_context (class);
2107 class = class->generic_class->container_class;
2110 for (parent = class; parent; parent = parent->parent) {
2111 mono_class_setup_interfaces (parent, &error);
2112 if (!mono_error_ok (&error))
2114 collect_interfaces (parent, iface_hash, &error);
2115 if (!mono_error_ok (&error))
2119 data.error = &error;
2120 data.domain = mono_object_domain (type);
2122 len = g_hash_table_size (iface_hash);
2124 g_hash_table_destroy (iface_hash);
2125 if (!data.domain->empty_types)
2126 data.domain->empty_types = mono_array_new_cached (data.domain, mono_defaults.monotype_class, 0);
2127 return data.domain->empty_types;
2130 data.iface_array = mono_array_new_cached (data.domain, mono_defaults.monotype_class, len);
2131 g_hash_table_foreach (iface_hash, fill_iface_array, &data);
2132 if (!mono_error_ok (&error))
2135 g_hash_table_destroy (iface_hash);
2136 return data.iface_array;
2139 g_hash_table_destroy (iface_hash);
2140 mono_error_raise_exception (&error);
2145 ves_icall_Type_GetInterfaceMapData (MonoReflectionType *type, MonoReflectionType *iface, MonoArray **targets, MonoArray **methods)
2147 gboolean variance_used;
2148 MonoClass *class = mono_class_from_mono_type (type->type);
2149 MonoClass *iclass = mono_class_from_mono_type (iface->type);
2150 MonoReflectionMethod *member;
2153 int i = 0, len, ioffset;
2156 MONO_ARCH_SAVE_REGS;
2157 mono_class_init_or_throw (class);
2158 mono_class_init_or_throw (iclass);
2160 mono_class_setup_vtable (class);
2162 ioffset = mono_class_interface_offset_with_variance (class, iclass, &variance_used);
2166 len = mono_class_num_methods (iclass);
2167 domain = mono_object_domain (type);
2168 mono_gc_wbarrier_generic_store (targets, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2169 mono_gc_wbarrier_generic_store (methods, (MonoObject*) mono_array_new (domain, mono_defaults.method_info_class, len));
2171 while ((method = mono_class_get_methods (iclass, &iter))) {
2172 member = mono_method_get_object (domain, method, iclass);
2173 mono_array_setref (*methods, i, member);
2174 member = mono_method_get_object (domain, class->vtable [i + ioffset], class);
2175 mono_array_setref (*targets, i, member);
2182 ves_icall_Type_GetPacking (MonoReflectionType *type, guint32 *packing, guint32 *size)
2184 MonoClass *klass = mono_class_from_mono_type (type->type);
2185 mono_class_init_or_throw (klass);
2187 if (image_is_dynamic (klass->image)) {
2188 MonoReflectionTypeBuilder *tb = (MonoReflectionTypeBuilder*)type;
2189 *packing = tb->packing_size;
2190 *size = tb->class_size;
2192 mono_metadata_packing_from_typedef (klass->image, klass->type_token, packing, size);
2196 ICALL_EXPORT MonoReflectionType*
2197 ves_icall_MonoType_GetElementType (MonoReflectionType *type)
2201 MONO_ARCH_SAVE_REGS;
2203 if (!type->type->byref && type->type->type == MONO_TYPE_SZARRAY)
2204 return mono_type_get_object (mono_object_domain (type), &type->type->data.klass->byval_arg);
2206 class = mono_class_from_mono_type (type->type);
2207 mono_class_init_or_throw (class);
2209 // GetElementType should only return a type for:
2210 // Array Pointer PassedByRef
2211 if (type->type->byref)
2212 return mono_type_get_object (mono_object_domain (type), &class->byval_arg);
2213 else if (class->element_class && MONO_CLASS_IS_ARRAY (class))
2214 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2215 else if (class->element_class && type->type->type == MONO_TYPE_PTR)
2216 return mono_type_get_object (mono_object_domain (type), &class->element_class->byval_arg);
2221 ICALL_EXPORT MonoReflectionType*
2222 ves_icall_get_type_parent (MonoReflectionType *type)
2224 MonoClass *class = mono_class_from_mono_type (type->type);
2225 return class->parent ? mono_type_get_object (mono_object_domain (type), &class->parent->byval_arg): NULL;
2228 ICALL_EXPORT MonoBoolean
2229 ves_icall_type_ispointer (MonoReflectionType *type)
2231 MONO_ARCH_SAVE_REGS;
2233 return type->type->type == MONO_TYPE_PTR;
2236 ICALL_EXPORT MonoBoolean
2237 ves_icall_type_isprimitive (MonoReflectionType *type)
2239 MONO_ARCH_SAVE_REGS;
2241 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)));
2244 ICALL_EXPORT MonoBoolean
2245 ves_icall_type_isbyref (MonoReflectionType *type)
2247 MONO_ARCH_SAVE_REGS;
2249 return type->type->byref;
2252 ICALL_EXPORT MonoBoolean
2253 ves_icall_type_iscomobject (MonoReflectionType *type)
2255 MonoClass *klass = mono_class_from_mono_type (type->type);
2256 mono_class_init_or_throw (klass);
2258 return mono_class_is_com_object (klass);
2261 ICALL_EXPORT MonoReflectionModule*
2262 ves_icall_MonoType_get_Module (MonoReflectionType *type)
2264 MonoClass *class = mono_class_from_mono_type (type->type);
2265 return mono_module_get_object (mono_object_domain (type), class->image);
2268 ICALL_EXPORT MonoReflectionAssembly*
2269 ves_icall_MonoType_get_Assembly (MonoReflectionType *type)
2271 MonoDomain *domain = mono_domain_get ();
2272 MonoClass *class = mono_class_from_mono_type (type->type);
2273 return mono_assembly_get_object (domain, class->image->assembly);
2276 ICALL_EXPORT MonoReflectionType*
2277 ves_icall_MonoType_get_DeclaringType (MonoReflectionType *type)
2279 MonoDomain *domain = mono_domain_get ();
2282 MONO_ARCH_SAVE_REGS;
2284 if (type->type->byref)
2286 if (type->type->type == MONO_TYPE_VAR) {
2287 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2288 class = param ? param->owner.klass : NULL;
2289 } else if (type->type->type == MONO_TYPE_MVAR) {
2290 MonoGenericContainer *param = mono_type_get_generic_param_owner (type->type);
2291 class = param ? param->owner.method->klass : NULL;
2293 class = mono_class_from_mono_type (type->type)->nested_in;
2296 return class ? mono_type_get_object (domain, &class->byval_arg) : NULL;
2299 ICALL_EXPORT MonoString*
2300 ves_icall_MonoType_get_Name (MonoReflectionType *type)
2302 MonoDomain *domain = mono_domain_get ();
2303 MonoClass *class = mono_class_from_mono_type (type->type);
2305 if (type->type->byref) {
2306 char *n = g_strdup_printf ("%s&", class->name);
2307 MonoString *res = mono_string_new (domain, n);
2313 return mono_string_new (domain, class->name);
2317 ICALL_EXPORT MonoString*
2318 ves_icall_MonoType_get_Namespace (MonoReflectionType *type)
2320 MonoDomain *domain = mono_domain_get ();
2321 MonoClass *class = mono_class_from_mono_type (type->type);
2323 while (class->nested_in)
2324 class = class->nested_in;
2326 if (class->name_space [0] == '\0')
2329 return mono_string_new (domain, class->name_space);
2333 ves_icall_MonoType_GetArrayRank (MonoReflectionType *type)
2337 if (type->type->type != MONO_TYPE_ARRAY && type->type->type != MONO_TYPE_SZARRAY)
2338 mono_raise_exception (mono_get_exception_argument ("type", "Type must be an array type"));
2340 class = mono_class_from_mono_type (type->type);
2345 ICALL_EXPORT MonoArray*
2346 ves_icall_MonoType_GetGenericArguments (MonoReflectionType *type)
2349 MonoClass *klass, *pklass;
2350 MonoDomain *domain = mono_object_domain (type);
2351 MonoVTable *array_vtable = mono_class_vtable_full (domain, mono_array_class_get_cached (mono_defaults.systemtype_class, 1), TRUE);
2353 MONO_ARCH_SAVE_REGS;
2355 klass = mono_class_from_mono_type (type->type);
2357 if (klass->generic_container) {
2358 MonoGenericContainer *container = klass->generic_container;
2359 res = mono_array_new_specific (array_vtable, container->type_argc);
2360 for (i = 0; i < container->type_argc; ++i) {
2361 pklass = mono_class_from_generic_parameter (mono_generic_container_get_param (container, i), klass->image, FALSE);
2362 mono_array_setref (res, i, mono_type_get_object (domain, &pklass->byval_arg));
2364 } else if (klass->generic_class) {
2365 MonoGenericInst *inst = klass->generic_class->context.class_inst;
2366 res = mono_array_new_specific (array_vtable, inst->type_argc);
2367 for (i = 0; i < inst->type_argc; ++i)
2368 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2370 res = mono_array_new_specific (array_vtable, 0);
2375 ICALL_EXPORT gboolean
2376 ves_icall_Type_get_IsGenericTypeDefinition (MonoReflectionType *type)
2379 MONO_ARCH_SAVE_REGS;
2381 if (!IS_MONOTYPE (type))
2384 if (type->type->byref)
2387 klass = mono_class_from_mono_type (type->type);
2388 return klass->generic_container != NULL;
2391 ICALL_EXPORT MonoReflectionType*
2392 ves_icall_Type_GetGenericTypeDefinition_impl (MonoReflectionType *type)
2395 MONO_ARCH_SAVE_REGS;
2397 if (type->type->byref)
2400 klass = mono_class_from_mono_type (type->type);
2402 if (klass->generic_container) {
2403 return type; /* check this one */
2405 if (klass->generic_class) {
2406 MonoClass *generic_class = klass->generic_class->container_class;
2409 tb = mono_class_get_ref_info (generic_class);
2411 if (generic_class->wastypebuilder && tb)
2414 return mono_type_get_object (mono_object_domain (type), &generic_class->byval_arg);
2419 ICALL_EXPORT MonoReflectionType*
2420 ves_icall_Type_MakeGenericType (MonoReflectionType *type, MonoArray *type_array)
2423 MonoType *geninst, **types;
2426 g_assert (IS_MONOTYPE (type));
2427 mono_class_init_or_throw (mono_class_from_mono_type (type->type));
2429 count = mono_array_length (type_array);
2430 types = g_new0 (MonoType *, count);
2432 for (i = 0; i < count; i++) {
2433 MonoReflectionType *t = mono_array_get (type_array, gpointer, i);
2434 types [i] = t->type;
2437 geninst = mono_reflection_bind_generic_parameters (type, count, types);
2442 class = mono_class_from_mono_type (geninst);
2444 /*we might inflate to the GTD*/
2445 if (class->generic_class && !mono_verifier_class_is_valid_generic_instantiation (class))
2446 mono_raise_exception (mono_get_exception_argument ("typeArguments", "Invalid generic arguments"));
2448 return mono_type_get_object (mono_object_domain (type), geninst);
2451 ICALL_EXPORT gboolean
2452 ves_icall_Type_get_IsGenericInstance (MonoReflectionType *type)
2455 MONO_ARCH_SAVE_REGS;
2457 if (type->type->byref)
2460 klass = mono_class_from_mono_type (type->type);
2462 return klass->generic_class != NULL;
2465 ICALL_EXPORT gboolean
2466 ves_icall_Type_get_IsGenericType (MonoReflectionType *type)
2469 MONO_ARCH_SAVE_REGS;
2471 if (!IS_MONOTYPE (type))
2474 if (type->type->byref)
2477 klass = mono_class_from_mono_type (type->type);
2478 return klass->generic_class != NULL || klass->generic_container != NULL;
2482 ves_icall_Type_GetGenericParameterPosition (MonoReflectionType *type)
2484 MONO_ARCH_SAVE_REGS;
2486 if (!IS_MONOTYPE (type))
2489 if (is_generic_parameter (type->type))
2490 return mono_type_get_generic_param_num (type->type);
2494 ICALL_EXPORT GenericParameterAttributes
2495 ves_icall_Type_GetGenericParameterAttributes (MonoReflectionType *type)
2497 MONO_ARCH_SAVE_REGS;
2499 g_assert (IS_MONOTYPE (type));
2500 g_assert (is_generic_parameter (type->type));
2501 return mono_generic_param_info (type->type->data.generic_param)->flags;
2504 ICALL_EXPORT MonoArray *
2505 ves_icall_Type_GetGenericParameterConstraints (MonoReflectionType *type)
2507 MonoGenericParamInfo *param_info;
2513 MONO_ARCH_SAVE_REGS;
2515 g_assert (IS_MONOTYPE (type));
2517 domain = mono_object_domain (type);
2518 param_info = mono_generic_param_info (type->type->data.generic_param);
2519 for (count = 0, ptr = param_info->constraints; ptr && *ptr; ptr++, count++)
2522 res = mono_array_new (domain, mono_defaults.monotype_class, count);
2523 for (i = 0; i < count; i++)
2524 mono_array_setref (res, i, mono_type_get_object (domain, ¶m_info->constraints [i]->byval_arg));
2530 ICALL_EXPORT MonoBoolean
2531 ves_icall_MonoType_get_IsGenericParameter (MonoReflectionType *type)
2533 MONO_ARCH_SAVE_REGS;
2534 return is_generic_parameter (type->type);
2537 ICALL_EXPORT MonoBoolean
2538 ves_icall_TypeBuilder_get_IsGenericParameter (MonoReflectionTypeBuilder *tb)
2540 MONO_ARCH_SAVE_REGS;
2541 return is_generic_parameter (tb->type.type);
2545 ves_icall_EnumBuilder_setup_enum_type (MonoReflectionType *enumtype,
2546 MonoReflectionType *t)
2548 enumtype->type = t->type;
2551 ICALL_EXPORT MonoReflectionMethod*
2552 ves_icall_MonoType_GetCorrespondingInflatedMethod (MonoReflectionType *type,
2553 MonoReflectionMethod* generic)
2560 MONO_ARCH_SAVE_REGS;
2562 domain = ((MonoObject *)type)->vtable->domain;
2564 klass = mono_class_from_mono_type (type->type);
2565 mono_class_init_or_throw (klass);
2568 while ((method = mono_class_get_methods (klass, &iter))) {
2569 if (method->token == generic->method->token)
2570 return mono_method_get_object (domain, method, klass);
2578 ICALL_EXPORT MonoReflectionMethod *
2579 ves_icall_MonoType_get_DeclaringMethod (MonoReflectionType *ref_type)
2582 MonoType *type = ref_type->type;
2584 MONO_ARCH_SAVE_REGS;
2586 if (type->byref || (type->type != MONO_TYPE_MVAR && type->type != MONO_TYPE_VAR))
2587 mono_raise_exception (mono_get_exception_invalid_operation ("DeclaringMethod can only be used on generic arguments"));
2588 if (type->type == MONO_TYPE_VAR)
2591 method = mono_type_get_generic_param_owner (type)->owner.method;
2593 return mono_method_get_object (mono_object_domain (ref_type), method, method->klass);
2596 ICALL_EXPORT MonoReflectionDllImportAttribute*
2597 ves_icall_MonoMethod_GetDllImportAttribute (MonoMethod *method)
2599 static MonoClass *DllImportAttributeClass = NULL;
2600 MonoDomain *domain = mono_domain_get ();
2601 MonoReflectionDllImportAttribute *attr;
2602 MonoImage *image = method->klass->image;
2603 MonoMethodPInvoke *piinfo = (MonoMethodPInvoke *)method;
2604 MonoTableInfo *tables = image->tables;
2605 MonoTableInfo *im = &tables [MONO_TABLE_IMPLMAP];
2606 MonoTableInfo *mr = &tables [MONO_TABLE_MODULEREF];
2607 guint32 im_cols [MONO_IMPLMAP_SIZE];
2608 guint32 scope_token;
2609 const char *import = NULL;
2610 const char *scope = NULL;
2613 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
2616 if (!DllImportAttributeClass) {
2617 DllImportAttributeClass =
2618 mono_class_from_name (mono_defaults.corlib,
2619 "System.Runtime.InteropServices", "DllImportAttribute");
2620 g_assert (DllImportAttributeClass);
2623 if (image_is_dynamic (method->klass->image)) {
2624 MonoReflectionMethodAux *method_aux =
2625 g_hash_table_lookup (
2626 ((MonoDynamicImage*)method->klass->image)->method_aux_hash, method);
2628 import = method_aux->dllentry;
2629 scope = method_aux->dll;
2632 if (!import || !scope) {
2633 mono_raise_exception (mono_get_exception_argument ("method", "System.Reflection.Emit method with invalid pinvoke information"));
2638 if (piinfo->implmap_idx) {
2639 mono_metadata_decode_row (im, piinfo->implmap_idx - 1, im_cols, MONO_IMPLMAP_SIZE);
2641 piinfo->piflags = im_cols [MONO_IMPLMAP_FLAGS];
2642 import = mono_metadata_string_heap (image, im_cols [MONO_IMPLMAP_NAME]);
2643 scope_token = mono_metadata_decode_row_col (mr, im_cols [MONO_IMPLMAP_SCOPE] - 1, MONO_MODULEREF_NAME);
2644 scope = mono_metadata_string_heap (image, scope_token);
2647 flags = piinfo->piflags;
2649 attr = (MonoReflectionDllImportAttribute*)mono_object_new (domain, DllImportAttributeClass);
2651 MONO_OBJECT_SETREF (attr, dll, mono_string_new (domain, scope));
2652 MONO_OBJECT_SETREF (attr, entry_point, mono_string_new (domain, import));
2653 attr->call_conv = (flags & 0x700) >> 8;
2654 attr->charset = ((flags & 0x6) >> 1) + 1;
2655 if (attr->charset == 1)
2657 attr->exact_spelling = (flags & 0x1) != 0;
2658 attr->set_last_error = (flags & 0x40) != 0;
2659 attr->best_fit_mapping = (flags & 0x30) == 0x10;
2660 attr->throw_on_unmappable = (flags & 0x3000) == 0x1000;
2661 attr->preserve_sig = FALSE;
2666 ICALL_EXPORT MonoReflectionMethod *
2667 ves_icall_MonoMethod_GetGenericMethodDefinition (MonoReflectionMethod *method)
2669 MonoMethodInflated *imethod;
2672 MONO_ARCH_SAVE_REGS;
2674 if (method->method->is_generic)
2677 if (!method->method->is_inflated)
2680 imethod = (MonoMethodInflated *) method->method;
2682 result = imethod->declaring;
2683 /* Not a generic method. */
2684 if (!result->is_generic)
2687 if (image_is_dynamic (method->method->klass->image)) {
2688 MonoDynamicImage *image = (MonoDynamicImage*)method->method->klass->image;
2689 MonoReflectionMethod *res;
2692 * FIXME: Why is this stuff needed at all ? Why can't the code below work for
2693 * the dynamic case as well ?
2695 mono_image_lock ((MonoImage*)image);
2696 res = mono_g_hash_table_lookup (image->generic_def_objects, imethod);
2697 mono_image_unlock ((MonoImage*)image);
2703 if (imethod->context.class_inst) {
2704 MonoClass *klass = ((MonoMethod *) imethod)->klass;
2705 /*Generic methods gets the context of the GTD.*/
2706 if (mono_class_get_context (klass))
2707 result = mono_class_inflate_generic_method_full (result, klass, mono_class_get_context (klass));
2710 return mono_method_get_object (mono_object_domain (method), result, NULL);
2713 ICALL_EXPORT gboolean
2714 ves_icall_MonoMethod_get_IsGenericMethod (MonoReflectionMethod *method)
2716 MONO_ARCH_SAVE_REGS;
2718 return mono_method_signature (method->method)->generic_param_count != 0;
2721 ICALL_EXPORT gboolean
2722 ves_icall_MonoMethod_get_IsGenericMethodDefinition (MonoReflectionMethod *method)
2724 MONO_ARCH_SAVE_REGS;
2726 return method->method->is_generic;
2729 ICALL_EXPORT MonoArray*
2730 ves_icall_MonoMethod_GetGenericArguments (MonoReflectionMethod *method)
2735 MONO_ARCH_SAVE_REGS;
2737 domain = mono_object_domain (method);
2739 if (method->method->is_inflated) {
2740 MonoGenericInst *inst = mono_method_get_context (method->method)->method_inst;
2743 count = inst->type_argc;
2744 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2746 for (i = 0; i < count; i++)
2747 mono_array_setref (res, i, mono_type_get_object (domain, inst->type_argv [i]));
2753 count = mono_method_signature (method->method)->generic_param_count;
2754 res = mono_array_new (domain, mono_defaults.systemtype_class, count);
2756 for (i = 0; i < count; i++) {
2757 MonoGenericContainer *container = mono_method_get_generic_container (method->method);
2758 MonoGenericParam *param = mono_generic_container_get_param (container, i);
2759 MonoClass *pklass = mono_class_from_generic_parameter (
2760 param, method->method->klass->image, TRUE);
2761 mono_array_setref (res, i,
2762 mono_type_get_object (domain, &pklass->byval_arg));
2768 ICALL_EXPORT MonoObject *
2769 ves_icall_InternalInvoke (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoException **exc)
2772 * Invoke from reflection is supposed to always be a virtual call (the API
2773 * is stupid), mono_runtime_invoke_*() calls the provided method, allowing
2774 * greater flexibility.
2776 MonoMethod *m = method->method;
2777 MonoMethodSignature *sig = mono_method_signature (m);
2782 MONO_ARCH_SAVE_REGS;
2786 if (mono_security_core_clr_enabled ())
2787 mono_security_core_clr_ensure_reflection_access_method (m);
2789 if (!(m->flags & METHOD_ATTRIBUTE_STATIC)) {
2790 if (!mono_class_vtable_full (mono_object_domain (method), m->klass, FALSE)) {
2791 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_class_get_exception_for_failure (m->klass));
2796 if (!mono_object_isinst (this, m->klass)) {
2797 char *this_name = mono_type_get_full_name (mono_object_get_class (this));
2798 char *target_name = mono_type_get_full_name (m->klass);
2799 char *msg = g_strdup_printf ("Object of type '%s' doesn't match target type '%s'", this_name, target_name);
2800 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", msg));
2802 g_free (target_name);
2806 m = mono_object_get_virtual_method (this, m);
2807 /* must pass the pointer to the value for valuetype methods */
2808 if (m->klass->valuetype)
2809 obj = mono_object_unbox (this);
2810 } else if (strcmp (m->name, ".ctor") && !m->wrapper_type) {
2811 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name_msg (mono_defaults.corlib, "System.Reflection", "TargetException", "Non-static method requires a target."));
2816 if (sig->ret->byref) {
2817 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"));
2821 pcount = params? mono_array_length (params): 0;
2822 if (pcount != sig->param_count) {
2823 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_exception_from_name (mono_defaults.corlib, "System.Reflection", "TargetParameterCountException"));
2827 if ((m->klass->flags & TYPE_ATTRIBUTE_ABSTRACT) && !strcmp (m->name, ".ctor") && !this) {
2828 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."));
2832 image = m->klass->image;
2833 if (image->assembly->ref_only) {
2834 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."));
2838 if (image_is_dynamic (image) && !((MonoDynamicImage*)image)->run) {
2839 mono_gc_wbarrier_generic_store (exc, (MonoObject*) mono_get_exception_not_supported ("Cannot invoke a method in a dynamic assembly without run access."));
2843 if (m->klass->rank && !strcmp (m->name, ".ctor")) {
2846 intptr_t *lower_bounds;
2847 pcount = mono_array_length (params);
2848 lengths = alloca (sizeof (uintptr_t) * pcount);
2849 /* Note: the synthetized array .ctors have int32 as argument type */
2850 for (i = 0; i < pcount; ++i)
2851 lengths [i] = *(int32_t*) ((char*)mono_array_get (params, gpointer, i) + sizeof (MonoObject));
2853 if (m->klass->rank == 1 && sig->param_count == 2 && m->klass->element_class->rank) {
2854 /* This is a ctor for jagged arrays. MS creates an array of arrays. */
2855 MonoArray *arr = mono_array_new_full (mono_object_domain (params), m->klass, lengths, NULL);
2857 for (i = 0; i < mono_array_length (arr); ++i) {
2858 MonoArray *subarray = mono_array_new_full (mono_object_domain (params), m->klass->element_class, &lengths [1], NULL);
2860 mono_array_setref_fast (arr, i, subarray);
2862 return (MonoObject*)arr;
2865 if (m->klass->rank == pcount) {
2866 /* Only lengths provided. */
2867 lower_bounds = NULL;
2869 g_assert (pcount == (m->klass->rank * 2));
2870 /* lower bounds are first. */
2871 lower_bounds = (intptr_t*)lengths;
2872 lengths += m->klass->rank;
2875 return (MonoObject*)mono_array_new_full (mono_object_domain (params), m->klass, lengths, lower_bounds);
2877 return mono_runtime_invoke_array (m, obj, params, NULL);
2880 #ifndef DISABLE_REMOTING
2881 ICALL_EXPORT MonoObject *
2882 ves_icall_InternalExecute (MonoReflectionMethod *method, MonoObject *this, MonoArray *params, MonoArray **outArgs)
2884 MonoDomain *domain = mono_object_domain (method);
2885 MonoMethod *m = method->method;
2886 MonoMethodSignature *sig = mono_method_signature (m);
2887 MonoArray *out_args;
2889 int i, j, outarg_count = 0;
2891 MONO_ARCH_SAVE_REGS;
2893 if (m->klass == mono_defaults.object_class) {
2895 if (!strcmp (m->name, "FieldGetter")) {
2896 MonoClass *k = this->vtable->klass;
2900 /* If this is a proxy, then it must be a CBO */
2901 if (k == mono_defaults.transparent_proxy_class) {
2902 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2903 this = tp->rp->unwrapped_server;
2905 k = this->vtable->klass;
2908 name = mono_array_get (params, MonoString *, 1);
2909 str = mono_string_to_utf8 (name);
2912 MonoClassField* field = mono_class_get_field_from_name (k, str);
2914 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2915 if (field_klass->valuetype)
2916 result = mono_value_box (domain, field_klass, (char *)this + field->offset);
2918 result = *((gpointer *)((char *)this + field->offset));
2920 out_args = mono_array_new (domain, mono_defaults.object_class, 1);
2921 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2922 mono_array_setref (out_args, 0, result);
2930 g_assert_not_reached ();
2932 } else if (!strcmp (m->name, "FieldSetter")) {
2933 MonoClass *k = this->vtable->klass;
2939 /* If this is a proxy, then it must be a CBO */
2940 if (k == mono_defaults.transparent_proxy_class) {
2941 MonoTransparentProxy *tp = (MonoTransparentProxy*) this;
2942 this = tp->rp->unwrapped_server;
2944 k = this->vtable->klass;
2947 name = mono_array_get (params, MonoString *, 1);
2948 str = mono_string_to_utf8 (name);
2951 MonoClassField* field = mono_class_get_field_from_name (k, str);
2953 MonoClass *field_klass = mono_class_from_mono_type (field->type);
2954 MonoObject *val = mono_array_get (params, gpointer, 2);
2956 if (field_klass->valuetype) {
2957 size = mono_type_size (field->type, &align);
2958 g_assert (size == mono_class_value_size (field_klass, NULL));
2959 mono_gc_wbarrier_value_copy ((char *)this + field->offset, (char*)val + sizeof (MonoObject), 1, field_klass);
2961 mono_gc_wbarrier_set_field (this, (char*)this + field->offset, val);
2964 out_args = mono_array_new (domain, mono_defaults.object_class, 0);
2965 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
2975 g_assert_not_reached ();
2980 for (i = 0; i < mono_array_length (params); i++) {
2981 if (sig->params [i]->byref)
2985 out_args = mono_array_new (domain, mono_defaults.object_class, outarg_count);
2987 /* handle constructors only for objects already allocated */
2988 if (!strcmp (method->method->name, ".ctor"))
2991 /* This can be called only on MBR objects, so no need to unbox for valuetypes. */
2992 g_assert (!method->method->klass->valuetype);
2993 result = mono_runtime_invoke_array (method->method, this, params, NULL);
2995 for (i = 0, j = 0; i < mono_array_length (params); i++) {
2996 if (sig->params [i]->byref) {
2998 arg = mono_array_get (params, gpointer, i);
2999 mono_array_setref (out_args, j, arg);
3004 mono_gc_wbarrier_generic_store (outArgs, (MonoObject*) out_args);
3011 read_enum_value (char *mem, int type)
3014 case MONO_TYPE_BOOLEAN:
3016 return *(guint8*)mem;
3018 return *(gint8*)mem;
3019 case MONO_TYPE_CHAR:
3021 return *(guint16*)mem;
3023 return *(gint16*)mem;
3025 return *(guint32*)mem;
3027 return *(gint32*)mem;
3029 return *(guint64*)mem;
3031 return *(gint64*)mem;
3033 g_assert_not_reached ();
3039 write_enum_value (char *mem, int type, guint64 value)
3043 case MONO_TYPE_I1: {
3044 guint8 *p = (guint8*)mem;
3049 case MONO_TYPE_I2: {
3050 guint16 *p = (void*)mem;
3055 case MONO_TYPE_I4: {
3056 guint32 *p = (void*)mem;
3061 case MONO_TYPE_I8: {
3062 guint64 *p = (void*)mem;
3067 g_assert_not_reached ();
3072 ICALL_EXPORT MonoObject *
3073 ves_icall_System_Enum_ToObject (MonoReflectionType *enumType, MonoObject *value)
3076 MonoClass *enumc, *objc;
3081 MONO_ARCH_SAVE_REGS;
3083 MONO_CHECK_ARG_NULL (enumType);
3084 MONO_CHECK_ARG_NULL (value);
3086 domain = mono_object_domain (enumType);
3087 enumc = mono_class_from_mono_type (enumType->type);
3089 mono_class_init_or_throw (enumc);
3091 objc = value->vtable->klass;
3093 if (!enumc->enumtype)
3094 mono_raise_exception (mono_get_exception_argument ("enumType", "Type provided must be an Enum."));
3095 if (!((objc->enumtype) || (objc->byval_arg.type >= MONO_TYPE_BOOLEAN && objc->byval_arg.type <= MONO_TYPE_U8)))
3096 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."));
3098 etype = mono_class_enum_basetype (enumc);
3100 /* MS throws this for typebuilders */
3101 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3103 res = mono_object_new (domain, enumc);
3104 val = read_enum_value ((char *)value + sizeof (MonoObject), objc->enumtype? mono_class_enum_basetype (objc)->type: objc->byval_arg.type);
3105 write_enum_value ((char *)res + sizeof (MonoObject), etype->type, val);
3110 ICALL_EXPORT MonoObject *
3111 ves_icall_System_Enum_get_value (MonoObject *this)
3119 MONO_ARCH_SAVE_REGS;
3124 g_assert (this->vtable->klass->enumtype);
3126 enumc = mono_class_from_mono_type (mono_class_enum_basetype (this->vtable->klass));
3127 res = mono_object_new (mono_object_domain (this), enumc);
3128 dst = (char *)res + sizeof (MonoObject);
3129 src = (char *)this + sizeof (MonoObject);
3130 size = mono_class_value_size (enumc, NULL);
3132 memcpy (dst, src, size);
3137 ICALL_EXPORT MonoReflectionType *
3138 ves_icall_System_Enum_get_underlying_type (MonoReflectionType *type)
3143 MONO_ARCH_SAVE_REGS;
3145 klass = mono_class_from_mono_type (type->type);
3146 mono_class_init_or_throw (klass);
3148 etype = mono_class_enum_basetype (klass);
3150 /* MS throws this for typebuilders */
3151 mono_raise_exception (mono_get_exception_argument ("Type must be a type provided by the runtime.", "enumType"));
3153 return mono_type_get_object (mono_object_domain (type), etype);
3157 ves_icall_System_Enum_compare_value_to (MonoObject *this, MonoObject *other)
3159 gpointer tdata = (char *)this + sizeof (MonoObject);
3160 gpointer odata = (char *)other + sizeof (MonoObject);
3161 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3162 g_assert (basetype);
3164 #define COMPARE_ENUM_VALUES(ENUM_TYPE) do { \
3165 ENUM_TYPE me = *((ENUM_TYPE*)tdata); \
3166 ENUM_TYPE other = *((ENUM_TYPE*)odata); \
3169 return me > other ? 1 : -1; \
3172 switch (basetype->type) {
3174 COMPARE_ENUM_VALUES (guint8);
3176 COMPARE_ENUM_VALUES (gint8);
3177 case MONO_TYPE_CHAR:
3179 COMPARE_ENUM_VALUES (guint16);
3181 COMPARE_ENUM_VALUES (gint16);
3183 COMPARE_ENUM_VALUES (guint32);
3185 COMPARE_ENUM_VALUES (gint32);
3187 COMPARE_ENUM_VALUES (guint64);
3189 COMPARE_ENUM_VALUES (gint64);
3191 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3193 #undef COMPARE_ENUM_VALUES
3198 ves_icall_System_Enum_get_hashcode (MonoObject *this)
3200 gpointer data = (char *)this + sizeof (MonoObject);
3201 MonoType *basetype = mono_class_enum_basetype (this->vtable->klass);
3202 g_assert (basetype);
3204 switch (basetype->type) {
3206 return *((gint8*)data);
3208 return *((guint8*)data);
3209 case MONO_TYPE_CHAR:
3211 return *((guint16*)data);
3214 return *((gint16*)data);
3216 return *((guint32*)data);
3218 return *((gint32*)data);
3220 case MONO_TYPE_I8: {
3221 gint64 value = *((gint64*)data);
3222 return (gint)(value & 0xffffffff) ^ (int)(value >> 32);
3225 g_error ("Implement type 0x%02x in get_hashcode", basetype->type);
3231 ves_icall_get_enum_info (MonoReflectionType *type, MonoEnumInfo *info)
3233 MonoDomain *domain = mono_object_domain (type);
3234 MonoClass *enumc = mono_class_from_mono_type (type->type);
3235 guint j = 0, nvalues, crow;
3237 MonoClassField *field;
3239 MONO_ARCH_SAVE_REGS;
3241 mono_class_init_or_throw (enumc);
3243 MONO_STRUCT_SETREF (info, utype, mono_type_get_object (domain, mono_class_enum_basetype (enumc)));
3244 nvalues = mono_class_num_fields (enumc) ? mono_class_num_fields (enumc) - 1 : 0;
3245 MONO_STRUCT_SETREF (info, names, mono_array_new (domain, mono_defaults.string_class, nvalues));
3246 MONO_STRUCT_SETREF (info, values, mono_array_new (domain, enumc, nvalues));
3250 while ((field = mono_class_get_fields (enumc, &iter))) {
3253 MonoTypeEnum def_type;
3255 if (!(field->type->attrs & FIELD_ATTRIBUTE_STATIC))
3257 if (strcmp ("value__", mono_field_get_name (field)) == 0)
3259 if (mono_field_is_deleted (field))
3261 mono_array_setref (info->names, j, mono_string_new (domain, mono_field_get_name (field)));
3263 p = mono_class_get_field_default_value (field, &def_type);
3264 len = mono_metadata_decode_blob_size (p, &p);
3265 switch (mono_class_enum_basetype (enumc)->type) {
3268 mono_array_set (info->values, gchar, j, *p);
3270 case MONO_TYPE_CHAR:
3273 mono_array_set (info->values, gint16, j, read16 (p));
3277 mono_array_set (info->values, gint32, j, read32 (p));
3281 mono_array_set (info->values, gint64, j, read64 (p));
3284 g_error ("Implement type 0x%02x in get_enum_info", mono_class_enum_basetype (enumc)->type);
3291 BFLAGS_IgnoreCase = 1,
3292 BFLAGS_DeclaredOnly = 2,
3293 BFLAGS_Instance = 4,
3295 BFLAGS_Public = 0x10,
3296 BFLAGS_NonPublic = 0x20,
3297 BFLAGS_FlattenHierarchy = 0x40,
3298 BFLAGS_InvokeMethod = 0x100,
3299 BFLAGS_CreateInstance = 0x200,
3300 BFLAGS_GetField = 0x400,
3301 BFLAGS_SetField = 0x800,
3302 BFLAGS_GetProperty = 0x1000,
3303 BFLAGS_SetProperty = 0x2000,
3304 BFLAGS_ExactBinding = 0x10000,
3305 BFLAGS_SuppressChangeType = 0x20000,
3306 BFLAGS_OptionalParamBinding = 0x40000
3309 ICALL_EXPORT MonoReflectionField *
3310 ves_icall_Type_GetField (MonoReflectionType *type, MonoString *name, guint32 bflags)
3313 MonoClass *startklass, *klass;
3315 MonoClassField *field;
3318 int (*compare_func) (const char *s1, const char *s2) = NULL;
3319 domain = ((MonoObject *)type)->vtable->domain;
3320 klass = startklass = mono_class_from_mono_type (type->type);
3323 mono_raise_exception (mono_get_exception_argument_null ("name"));
3324 if (type->type->byref)
3327 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3330 if (klass->exception_type != MONO_EXCEPTION_NONE)
3331 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3334 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3335 guint32 flags = mono_field_get_flags (field);
3338 if (mono_field_is_deleted_with_flags (field, flags))
3340 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3341 if (bflags & BFLAGS_Public)
3343 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3344 if (bflags & BFLAGS_NonPublic) {
3351 if (flags & FIELD_ATTRIBUTE_STATIC) {
3352 if (bflags & BFLAGS_Static)
3353 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3356 if (bflags & BFLAGS_Instance)
3363 utf8_name = mono_string_to_utf8 (name);
3365 if (compare_func (mono_field_get_name (field), utf8_name)) {
3371 return mono_field_get_object (domain, klass, field);
3373 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3379 ICALL_EXPORT MonoArray*
3380 ves_icall_Type_GetFields_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3383 MonoClass *startklass, *klass, *refklass;
3388 MonoClassField *field;
3389 MonoPtrArray tmp_array;
3391 MONO_ARCH_SAVE_REGS;
3393 domain = ((MonoObject *)type)->vtable->domain;
3394 if (type->type->byref)
3395 return mono_array_new (domain, mono_defaults.field_info_class, 0);
3396 klass = startklass = mono_class_from_mono_type (type->type);
3397 refklass = mono_class_from_mono_type (reftype->type);
3399 mono_ptr_array_init (tmp_array, 2);
3402 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3403 mono_ptr_array_destroy (tmp_array);
3404 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3408 while ((field = mono_class_get_fields_lazy (klass, &iter))) {
3409 guint32 flags = mono_field_get_flags (field);
3411 if (mono_field_is_deleted_with_flags (field, flags))
3413 if ((flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) == FIELD_ATTRIBUTE_PUBLIC) {
3414 if (bflags & BFLAGS_Public)
3416 } else if ((klass == startklass) || (flags & FIELD_ATTRIBUTE_FIELD_ACCESS_MASK) != FIELD_ATTRIBUTE_PRIVATE) {
3417 if (bflags & BFLAGS_NonPublic) {
3424 if (flags & FIELD_ATTRIBUTE_STATIC) {
3425 if (bflags & BFLAGS_Static)
3426 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3429 if (bflags & BFLAGS_Instance)
3435 member = (MonoObject*)mono_field_get_object (domain, refklass, field);
3436 mono_ptr_array_append (tmp_array, member);
3438 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3441 res = mono_array_new_cached (domain, mono_defaults.field_info_class, mono_ptr_array_size (tmp_array));
3443 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3444 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3446 mono_ptr_array_destroy (tmp_array);
3452 method_nonpublic (MonoMethod* method, gboolean start_klass)
3454 switch (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) {
3455 case METHOD_ATTRIBUTE_ASSEM:
3456 return (start_klass || mono_defaults.generic_ilist_class);
3457 case METHOD_ATTRIBUTE_PRIVATE:
3459 case METHOD_ATTRIBUTE_PUBLIC:
3467 mono_class_get_methods_by_name (MonoClass *klass, const char *name, guint32 bflags, gboolean ignore_case, gboolean allow_ctors, MonoException **ex)
3470 MonoClass *startklass;
3473 int len, match, nslots;
3474 /*FIXME, use MonoBitSet*/
3475 guint32 method_slots_default [8];
3476 guint32 *method_slots = NULL;
3477 int (*compare_func) (const char *s1, const char *s2) = NULL;
3479 array = g_ptr_array_new ();
3485 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3487 /* An optimization for calls made from Delegate:CreateDelegate () */
3488 if (klass->delegate && name && !strcmp (name, "Invoke") && (bflags == (BFLAGS_Public | BFLAGS_Static | BFLAGS_Instance))) {
3489 method = mono_get_delegate_invoke (klass);
3490 if (mono_loader_get_last_error ())
3493 g_ptr_array_add (array, method);
3497 mono_class_setup_vtable (klass);
3498 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3501 if (is_generic_parameter (&klass->byval_arg))
3502 nslots = mono_class_get_vtable_size (klass->parent);
3504 nslots = MONO_CLASS_IS_INTERFACE (klass) ? mono_class_num_methods (klass) : mono_class_get_vtable_size (klass);
3505 if (nslots >= sizeof (method_slots_default) * 8) {
3506 method_slots = g_new0 (guint32, nslots / 32 + 1);
3508 method_slots = method_slots_default;
3509 memset (method_slots, 0, sizeof (method_slots_default));
3512 mono_class_setup_vtable (klass);
3513 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3517 while ((method = mono_class_get_methods (klass, &iter))) {
3519 if (method->slot != -1) {
3520 g_assert (method->slot < nslots);
3521 if (method_slots [method->slot >> 5] & (1 << (method->slot & 0x1f)))
3523 if (!(method->flags & METHOD_ATTRIBUTE_NEW_SLOT))
3524 method_slots [method->slot >> 5] |= 1 << (method->slot & 0x1f);
3527 if (!allow_ctors && method->name [0] == '.' && (strcmp (method->name, ".ctor") == 0 || strcmp (method->name, ".cctor") == 0))
3529 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3530 if (bflags & BFLAGS_Public)
3532 } else if ((bflags & BFLAGS_NonPublic) && method_nonpublic (method, (klass == startklass))) {
3538 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3539 if (bflags & BFLAGS_Static)
3540 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3543 if (bflags & BFLAGS_Instance)
3551 if (compare_func (name, method->name))
3556 g_ptr_array_add (array, method);
3558 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3560 if (method_slots != method_slots_default)
3561 g_free (method_slots);
3566 if (method_slots != method_slots_default)
3567 g_free (method_slots);
3568 g_ptr_array_free (array, TRUE);
3570 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3571 *ex = mono_class_get_exception_for_failure (klass);
3573 *ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3574 mono_loader_clear_error ();
3579 ICALL_EXPORT MonoArray*
3580 ves_icall_Type_GetMethodsByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3582 static MonoClass *MethodInfo_array;
3585 MonoVTable *array_vtable;
3586 MonoException *ex = NULL;
3587 const char *mname = NULL;
3588 GPtrArray *method_array;
3589 MonoClass *klass, *refklass;
3592 if (!MethodInfo_array) {
3593 MonoClass *klass = mono_array_class_get (mono_defaults.method_info_class, 1);
3594 mono_memory_barrier ();
3595 MethodInfo_array = klass;
3598 klass = mono_class_from_mono_type (type->type);
3599 refklass = mono_class_from_mono_type (reftype->type);
3600 domain = ((MonoObject *)type)->vtable->domain;
3601 array_vtable = mono_class_vtable_full (domain, MethodInfo_array, TRUE);
3602 if (type->type->byref)
3603 return mono_array_new_specific (array_vtable, 0);
3606 mname = mono_string_to_utf8 (name);
3608 method_array = mono_class_get_methods_by_name (klass, mname, bflags, ignore_case, FALSE, &ex);
3609 g_free ((char*)mname);
3611 mono_raise_exception (ex);
3613 res = mono_array_new_specific (array_vtable, method_array->len);
3616 for (i = 0; i < method_array->len; ++i) {
3617 MonoMethod *method = g_ptr_array_index (method_array, i);
3618 mono_array_setref (res, i, mono_method_get_object (domain, method, refklass));
3621 g_ptr_array_free (method_array, TRUE);
3625 ICALL_EXPORT MonoArray*
3626 ves_icall_Type_GetConstructors_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3629 static MonoClass *System_Reflection_ConstructorInfo;
3630 MonoClass *startklass, *klass, *refklass;
3635 gpointer iter = NULL;
3636 MonoPtrArray tmp_array;
3638 MONO_ARCH_SAVE_REGS;
3640 mono_ptr_array_init (tmp_array, 4); /*FIXME, guestimating*/
3642 domain = ((MonoObject *)type)->vtable->domain;
3643 if (type->type->byref)
3644 return mono_array_new_cached (domain, mono_defaults.method_info_class, 0);
3645 klass = startklass = mono_class_from_mono_type (type->type);
3646 refklass = mono_class_from_mono_type (reftype->type);
3648 if (!System_Reflection_ConstructorInfo)
3649 System_Reflection_ConstructorInfo = mono_class_from_name (
3650 mono_defaults.corlib, "System.Reflection", "ConstructorInfo");
3653 while ((method = mono_class_get_methods (klass, &iter))) {
3655 if (strcmp (method->name, ".ctor") && strcmp (method->name, ".cctor"))
3657 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3658 if (bflags & BFLAGS_Public)
3661 if (bflags & BFLAGS_NonPublic)
3667 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3668 if (bflags & BFLAGS_Static)
3669 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3672 if (bflags & BFLAGS_Instance)
3678 member = (MonoObject*)mono_method_get_object (domain, method, refklass);
3680 mono_ptr_array_append (tmp_array, member);
3683 res = mono_array_new_cached (domain, System_Reflection_ConstructorInfo, mono_ptr_array_size (tmp_array));
3685 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3686 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3688 mono_ptr_array_destroy (tmp_array);
3694 property_hash (gconstpointer data)
3696 MonoProperty *prop = (MonoProperty*)data;
3698 return g_str_hash (prop->name);
3702 property_equal (MonoProperty *prop1, MonoProperty *prop2)
3704 // Properties are hide-by-name-and-signature
3705 if (!g_str_equal (prop1->name, prop2->name))
3708 if (prop1->get && prop2->get && !mono_metadata_signature_equal (mono_method_signature (prop1->get), mono_method_signature (prop2->get)))
3710 if (prop1->set && prop2->set && !mono_metadata_signature_equal (mono_method_signature (prop1->set), mono_method_signature (prop2->set)))
3716 property_accessor_nonpublic (MonoMethod* accessor, gboolean start_klass)
3721 return method_nonpublic (accessor, start_klass);
3724 ICALL_EXPORT MonoArray*
3725 ves_icall_Type_GetPropertiesByName (MonoReflectionType *type, MonoString *name, guint32 bflags, MonoBoolean ignore_case, MonoReflectionType *reftype)
3729 static MonoClass *System_Reflection_PropertyInfo;
3730 MonoClass *startklass, *klass;
3736 gchar *propname = NULL;
3737 int (*compare_func) (const char *s1, const char *s2) = NULL;
3739 GHashTable *properties = NULL;
3740 MonoPtrArray tmp_array;
3742 MONO_ARCH_SAVE_REGS;
3744 mono_ptr_array_init (tmp_array, 8); /*This the average for ASP.NET types*/
3746 if (!System_Reflection_PropertyInfo)
3747 System_Reflection_PropertyInfo = mono_class_from_name (
3748 mono_defaults.corlib, "System.Reflection", "PropertyInfo");
3750 domain = ((MonoObject *)type)->vtable->domain;
3751 if (type->type->byref)
3752 return mono_array_new_cached (domain, System_Reflection_PropertyInfo, 0);
3753 klass = startklass = mono_class_from_mono_type (type->type);
3756 propname = mono_string_to_utf8 (name);
3757 compare_func = (ignore_case) ? mono_utf8_strcasecmp : strcmp;
3760 properties = g_hash_table_new (property_hash, (GEqualFunc)property_equal);
3762 mono_class_setup_vtable (klass);
3763 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3767 while ((prop = mono_class_get_properties (klass, &iter))) {
3773 flags = method->flags;
3776 if ((prop->get && ((prop->get->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC)) ||
3777 (prop->set && ((prop->set->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC))) {
3778 if (bflags & BFLAGS_Public)
3780 } else if (bflags & BFLAGS_NonPublic) {
3781 if (property_accessor_nonpublic(prop->get, startklass == klass) ||
3782 property_accessor_nonpublic(prop->set, startklass == klass)) {
3789 if (flags & METHOD_ATTRIBUTE_STATIC) {
3790 if (bflags & BFLAGS_Static)
3791 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3794 if (bflags & BFLAGS_Instance)
3803 if (compare_func (propname, prop->name))
3807 if (g_hash_table_lookup (properties, prop))
3810 mono_ptr_array_append (tmp_array, mono_property_get_object (domain, startklass, prop));
3812 g_hash_table_insert (properties, prop, prop);
3814 if ((!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent)))
3817 g_hash_table_destroy (properties);
3820 res = mono_array_new_cached (domain, System_Reflection_PropertyInfo, mono_ptr_array_size (tmp_array));
3821 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
3822 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
3824 mono_ptr_array_destroy (tmp_array);
3830 g_hash_table_destroy (properties);
3833 mono_ptr_array_destroy (tmp_array);
3835 if (klass->exception_type != MONO_EXCEPTION_NONE) {
3836 ex = mono_class_get_exception_for_failure (klass);
3838 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
3839 mono_loader_clear_error ();
3841 mono_raise_exception (ex);
3845 ICALL_EXPORT MonoReflectionEvent *
3846 ves_icall_MonoType_GetEvent (MonoReflectionType *type, MonoString *name, guint32 bflags)
3849 MonoClass *klass, *startklass;
3854 int (*compare_func) (const char *s1, const char *s2);
3856 MONO_ARCH_SAVE_REGS;
3858 event_name = mono_string_to_utf8 (name);
3859 if (type->type->byref)
3861 klass = startklass = mono_class_from_mono_type (type->type);
3862 domain = mono_object_domain (type);
3864 mono_class_init_or_throw (klass);
3866 compare_func = (bflags & BFLAGS_IgnoreCase) ? mono_utf8_strcasecmp : strcmp;
3868 if (klass->exception_type != MONO_EXCEPTION_NONE)
3869 mono_raise_exception (mono_class_get_exception_for_failure (klass));
3872 while ((event = mono_class_get_events (klass, &iter))) {
3873 if (compare_func (event->name, event_name))
3876 method = event->add;
3878 method = event->remove;
3880 method = event->raise;
3882 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3883 if (!(bflags & BFLAGS_Public))
3886 if (!(bflags & BFLAGS_NonPublic))
3888 if ((klass != startklass) && (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PRIVATE)
3892 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3893 if (!(bflags & BFLAGS_Static))
3895 if (!(bflags & BFLAGS_FlattenHierarchy) && (klass != startklass))
3898 if (!(bflags & BFLAGS_Instance))
3902 if (!(bflags & BFLAGS_NonPublic))
3905 g_free (event_name);
3906 return mono_event_get_object (domain, startklass, event);
3909 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
3912 g_free (event_name);
3917 event_hash (gconstpointer data)
3919 MonoEvent *event = (MonoEvent*)data;
3921 return g_str_hash (event->name);
3925 event_equal (MonoEvent *event1, MonoEvent *event2)
3927 // Events are hide-by-name
3928 return g_str_equal (event1->name, event2->name);
3931 ICALL_EXPORT MonoArray*
3932 ves_icall_Type_GetEvents_internal (MonoReflectionType *type, guint32 bflags, MonoReflectionType *reftype)
3936 static MonoClass *System_Reflection_EventInfo;
3937 MonoClass *startklass, *klass;
3943 GHashTable *events = NULL;
3944 MonoPtrArray tmp_array;
3946 MONO_ARCH_SAVE_REGS;
3948 mono_ptr_array_init (tmp_array, 4);
3950 if (!System_Reflection_EventInfo)
3951 System_Reflection_EventInfo = mono_class_from_name (
3952 mono_defaults.corlib, "System.Reflection", "EventInfo");
3954 domain = mono_object_domain (type);
3955 if (type->type->byref)
3956 return mono_array_new_cached (domain, System_Reflection_EventInfo, 0);
3957 klass = startklass = mono_class_from_mono_type (type->type);
3959 events = g_hash_table_new (event_hash, (GEqualFunc)event_equal);
3961 mono_class_setup_vtable (klass);
3962 if (klass->exception_type != MONO_EXCEPTION_NONE || mono_loader_get_last_error ())
3966 while ((event = mono_class_get_events (klass, &iter))) {
3968 method = event->add;
3970 method = event->remove;
3972 method = event->raise;
3974 if ((method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) == METHOD_ATTRIBUTE_PUBLIC) {
3975 if (bflags & BFLAGS_Public)
3977 } else if ((klass == startklass) || (method->flags & METHOD_ATTRIBUTE_MEMBER_ACCESS_MASK) != METHOD_ATTRIBUTE_PRIVATE) {
3978 if (bflags & BFLAGS_NonPublic)
3983 if (bflags & BFLAGS_NonPublic)
3989 if (method->flags & METHOD_ATTRIBUTE_STATIC) {
3990 if (bflags & BFLAGS_Static)
3991 if ((bflags & BFLAGS_FlattenHierarchy) || (klass == startklass))
3994 if (bflags & BFLAGS_Instance)
3999 if (bflags & BFLAGS_Instance)
4004 if (g_hash_table_lookup (events, event))
4007 mono_ptr_array_append (tmp_array, mono_event_get_object (domain, startklass, event));
4009 g_hash_table_insert (events, event, event);
4011 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4014 g_hash_table_destroy (events);
4016 res = mono_array_new_cached (domain, System_Reflection_EventInfo, mono_ptr_array_size (tmp_array));
4018 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4019 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4021 mono_ptr_array_destroy (tmp_array);
4026 mono_ptr_array_destroy (tmp_array);
4027 if (klass->exception_type != MONO_EXCEPTION_NONE) {
4028 ex = mono_class_get_exception_for_failure (klass);
4030 ex = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4031 mono_loader_clear_error ();
4033 mono_raise_exception (ex);
4037 ICALL_EXPORT MonoReflectionType *
4038 ves_icall_Type_GetNestedType (MonoReflectionType *type, MonoString *name, guint32 bflags)
4046 MONO_ARCH_SAVE_REGS;
4049 mono_raise_exception (mono_get_exception_argument_null ("name"));
4051 domain = ((MonoObject *)type)->vtable->domain;
4052 if (type->type->byref)
4054 klass = mono_class_from_mono_type (type->type);
4056 str = mono_string_to_utf8 (name);
4059 if (klass->exception_type != MONO_EXCEPTION_NONE)
4060 mono_raise_exception (mono_class_get_exception_for_failure (klass));
4063 * If a nested type is generic, return its generic type definition.
4064 * Note that this means that the return value is essentially a
4065 * nested type of the generic type definition of @klass.
4067 * A note in MSDN claims that a generic type definition can have
4068 * nested types that aren't generic. In any case, the container of that
4069 * nested type would be the generic type definition.
4071 if (klass->generic_class)
4072 klass = klass->generic_class->container_class;
4075 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4077 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4078 if (bflags & BFLAGS_Public)
4081 if (bflags & BFLAGS_NonPublic)
4086 if (strcmp (nested->name, str) == 0){
4088 return mono_type_get_object (domain, &nested->byval_arg);
4091 if (!(bflags & BFLAGS_DeclaredOnly) && (klass = klass->parent))
4097 ICALL_EXPORT MonoArray*
4098 ves_icall_Type_GetNestedTypes (MonoReflectionType *type, guint32 bflags)
4107 MonoPtrArray tmp_array;
4109 MONO_ARCH_SAVE_REGS;
4111 domain = ((MonoObject *)type)->vtable->domain;
4112 if (type->type->byref)
4113 return mono_array_new (domain, mono_defaults.monotype_class, 0);
4114 klass = mono_class_from_mono_type (type->type);
4117 * If a nested type is generic, return its generic type definition.
4118 * Note that this means that the return value is essentially the set
4119 * of nested types of the generic type definition of @klass.
4121 * A note in MSDN claims that a generic type definition can have
4122 * nested types that aren't generic. In any case, the container of that
4123 * nested type would be the generic type definition.
4125 if (klass->generic_class)
4126 klass = klass->generic_class->container_class;
4128 mono_ptr_array_init (tmp_array, 1);
4130 while ((nested = mono_class_get_nested_types (klass, &iter))) {
4132 if ((nested->flags & TYPE_ATTRIBUTE_VISIBILITY_MASK) == TYPE_ATTRIBUTE_NESTED_PUBLIC) {
4133 if (bflags & BFLAGS_Public)
4136 if (bflags & BFLAGS_NonPublic)
4141 member = (MonoObject*)mono_type_get_object (domain, &nested->byval_arg);
4142 mono_ptr_array_append (tmp_array, member);
4145 res = mono_array_new_cached (domain, mono_defaults.monotype_class, mono_ptr_array_size (tmp_array));
4147 for (i = 0; i < mono_ptr_array_size (tmp_array); ++i)
4148 mono_array_setref (res, i, mono_ptr_array_get (tmp_array, i));
4150 mono_ptr_array_destroy (tmp_array);
4155 ICALL_EXPORT MonoReflectionType*
4156 ves_icall_System_Reflection_Assembly_InternalGetType (MonoReflectionAssembly *assembly, MonoReflectionModule *module, MonoString *name, MonoBoolean throwOnError, MonoBoolean ignoreCase)
4159 MonoType *type = NULL;
4160 MonoTypeNameParse info;
4161 gboolean type_resolve;
4163 MONO_ARCH_SAVE_REGS;
4165 /* On MS.NET, this does not fire a TypeResolve event */
4166 type_resolve = TRUE;
4167 str = mono_string_to_utf8 (name);
4168 /*g_print ("requested type %s in %s\n", str, assembly->assembly->aname.name);*/
4169 if (!mono_reflection_parse_type (str, &info)) {
4171 mono_reflection_free_type_info (&info);
4172 if (throwOnError) /* uhm: this is a parse error, though... */
4173 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4174 /*g_print ("failed parse\n");*/
4178 if (info.assembly.name) {
4180 mono_reflection_free_type_info (&info);
4182 /* 1.0 and 2.0 throw different exceptions */
4183 if (mono_defaults.generic_ilist_class)
4184 mono_raise_exception (mono_get_exception_argument (NULL, "Type names passed to Assembly.GetType() must not specify an assembly."));
4186 mono_raise_exception (mono_get_exception_type_load (name, NULL));
4191 if (module != NULL) {
4193 type = mono_reflection_get_type (module->image, &info, ignoreCase, &type_resolve);
4198 if (assembly_is_dynamic (assembly->assembly)) {
4199 /* Enumerate all modules */
4200 MonoReflectionAssemblyBuilder *abuilder = (MonoReflectionAssemblyBuilder*)assembly;
4204 if (abuilder->modules) {
4205 for (i = 0; i < mono_array_length (abuilder->modules); ++i) {
4206 MonoReflectionModuleBuilder *mb = mono_array_get (abuilder->modules, MonoReflectionModuleBuilder*, i);
4207 type = mono_reflection_get_type (&mb->dynamic_image->image, &info, ignoreCase, &type_resolve);
4213 if (!type && abuilder->loaded_modules) {
4214 for (i = 0; i < mono_array_length (abuilder->loaded_modules); ++i) {
4215 MonoReflectionModule *mod = mono_array_get (abuilder->loaded_modules, MonoReflectionModule*, i);
4216 type = mono_reflection_get_type (mod->image, &info, ignoreCase, &type_resolve);
4223 type = mono_reflection_get_type (assembly->assembly->image, &info, ignoreCase, &type_resolve);
4225 mono_reflection_free_type_info (&info);
4227 MonoException *e = NULL;
4230 e = mono_get_exception_type_load (name, NULL);
4232 if (mono_loader_get_last_error () && mono_defaults.generic_ilist_class)
4233 e = mono_loader_error_prepare_exception (mono_loader_get_last_error ());
4235 mono_loader_clear_error ();
4238 mono_raise_exception (e);
4241 } else if (mono_loader_get_last_error ()) {
4243 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
4244 mono_loader_clear_error ();
4247 if (type->type == MONO_TYPE_CLASS) {
4248 MonoClass *klass = mono_type_get_class (type);
4250 if (mono_security_enabled () && !klass->exception_type)
4251 /* Some security problems are detected during generic vtable construction */
4252 mono_class_setup_vtable (klass);
4254 /* need to report exceptions ? */
4255 if (throwOnError && klass->exception_type) {
4256 /* report SecurityException (or others) that occured when loading the assembly */
4257 MonoException *exc = mono_class_get_exception_for_failure (klass);
4258 mono_loader_clear_error ();
4259 mono_raise_exception (exc);
4260 } else if (mono_security_enabled () && klass->exception_type == MONO_EXCEPTION_SECURITY_INHERITANCEDEMAND) {
4265 /* g_print ("got it\n"); */
4266 return mono_type_get_object (mono_object_domain (assembly), type);
4270 replace_shadow_path (MonoDomain *domain, gchar *dirname, gchar **filename)
4273 gchar *shadow_ini_file;
4276 /* Check for shadow-copied assembly */
4277 if (mono_is_shadow_copy_enabled (domain, dirname)) {
4278 shadow_ini_file = g_build_filename (dirname, "__AssemblyInfo__.ini", NULL);
4280 if (!g_file_get_contents (shadow_ini_file, &content, &len, NULL) ||
4281 !g_file_test (content, G_FILE_TEST_IS_REGULAR)) {
4287 g_free (shadow_ini_file);
4288 if (content != NULL) {
4291 *filename = content;
4298 ICALL_EXPORT MonoString *
4299 ves_icall_System_Reflection_Assembly_get_code_base (MonoReflectionAssembly *assembly, MonoBoolean escaped)
4301 MonoDomain *domain = mono_object_domain (assembly);
4302 MonoAssembly *mass = assembly->assembly;
4303 MonoString *res = NULL;
4308 MONO_ARCH_SAVE_REGS;
4310 if (g_path_is_absolute (mass->image->name)) {
4311 absolute = g_strdup (mass->image->name);
4312 dirname = g_path_get_dirname (absolute);
4314 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
4315 dirname = g_strdup (mass->basedir);
4318 replace_shadow_path (domain, dirname, &absolute);
4323 for (i = strlen (absolute) - 1; i >= 0; i--)
4324 if (absolute [i] == '\\')
4329 uri = g_filename_to_uri (absolute, NULL, NULL);
4331 const char *prepend = "file://";
4333 if (*absolute == '/' && *(absolute + 1) == '/') {
4336 prepend = "file:///";
4339 uri = g_strconcat (prepend, absolute, NULL);
4343 res = mono_string_new (domain, uri);
4350 ICALL_EXPORT MonoBoolean
4351 ves_icall_System_Reflection_Assembly_get_global_assembly_cache (MonoReflectionAssembly *assembly)
4353 MonoAssembly *mass = assembly->assembly;
4355 MONO_ARCH_SAVE_REGS;
4357 return mass->in_gac;
4360 ICALL_EXPORT MonoReflectionAssembly*
4361 ves_icall_System_Reflection_Assembly_load_with_partial_name (MonoString *mname, MonoObject *evidence)
4365 MonoImageOpenStatus status;
4367 MONO_ARCH_SAVE_REGS;
4369 name = mono_string_to_utf8 (mname);
4370 res = mono_assembly_load_with_partial_name (name, &status);
4376 return mono_assembly_get_object (mono_domain_get (), res);
4379 ICALL_EXPORT MonoString *
4380 ves_icall_System_Reflection_Assembly_get_location (MonoReflectionAssembly *assembly)
4382 MonoDomain *domain = mono_object_domain (assembly);
4385 MONO_ARCH_SAVE_REGS;
4387 res = mono_string_new (domain, mono_image_get_filename (assembly->assembly->image));
4392 ICALL_EXPORT MonoBoolean
4393 ves_icall_System_Reflection_Assembly_get_ReflectionOnly (MonoReflectionAssembly *assembly)
4395 MONO_ARCH_SAVE_REGS;
4397 return assembly->assembly->ref_only;
4400 ICALL_EXPORT MonoString *
4401 ves_icall_System_Reflection_Assembly_InternalImageRuntimeVersion (MonoReflectionAssembly *assembly)
4403 MonoDomain *domain = mono_object_domain (assembly);
4405 MONO_ARCH_SAVE_REGS;
4407 return mono_string_new (domain, assembly->assembly->image->version);
4410 ICALL_EXPORT MonoReflectionMethod*
4411 ves_icall_System_Reflection_Assembly_get_EntryPoint (MonoReflectionAssembly *assembly)
4413 guint32 token = mono_image_get_entry_point (assembly->assembly->image);
4415 MONO_ARCH_SAVE_REGS;
4419 return mono_method_get_object (mono_object_domain (assembly), mono_get_method (assembly->assembly->image, token, NULL), NULL);
4422 ICALL_EXPORT MonoReflectionModule*
4423 ves_icall_System_Reflection_Assembly_GetManifestModuleInternal (MonoReflectionAssembly *assembly)
4425 return mono_module_get_object (mono_object_domain (assembly), assembly->assembly->image);
4428 ICALL_EXPORT MonoArray*
4429 ves_icall_System_Reflection_Assembly_GetManifestResourceNames (MonoReflectionAssembly *assembly)
4431 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4432 MonoArray *result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, table->rows);
4436 MONO_ARCH_SAVE_REGS;
4438 for (i = 0; i < table->rows; ++i) {
4439 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_MANIFEST_NAME));
4440 mono_array_setref (result, i, mono_string_new (mono_object_domain (assembly), val));
4446 create_version (MonoDomain *domain, guint32 major, guint32 minor, guint32 build, guint32 revision)
4448 static MonoClass *System_Version = NULL;
4449 static MonoMethod *create_version = NULL;
4453 if (!System_Version) {
4454 System_Version = mono_class_from_name (mono_defaults.corlib, "System", "Version");
4455 g_assert (System_Version);
4458 if (!create_version) {
4459 MonoMethodDesc *desc = mono_method_desc_new (":.ctor(int,int,int,int)", FALSE);
4460 create_version = mono_method_desc_search_in_class (desc, System_Version);
4461 g_assert (create_version);
4462 mono_method_desc_free (desc);
4468 args [3] = &revision;
4469 result = mono_object_new (domain, System_Version);
4470 mono_runtime_invoke (create_version, result, args, NULL);
4475 ICALL_EXPORT MonoArray*
4476 ves_icall_System_Reflection_Assembly_GetReferencedAssemblies (MonoReflectionAssembly *assembly)
4478 static MonoClass *System_Reflection_AssemblyName;
4480 MonoDomain *domain = mono_object_domain (assembly);
4482 static MonoMethod *create_culture = NULL;
4483 MonoImage *image = assembly->assembly->image;
4486 MONO_ARCH_SAVE_REGS;
4488 if (!System_Reflection_AssemblyName)
4489 System_Reflection_AssemblyName = mono_class_from_name (
4490 mono_defaults.corlib, "System.Reflection", "AssemblyName");
4492 t = &assembly->assembly->image->tables [MONO_TABLE_ASSEMBLYREF];
4495 result = mono_array_new (domain, System_Reflection_AssemblyName, count);
4497 if (count > 0 && !create_culture) {
4498 MonoMethodDesc *desc = mono_method_desc_new (
4499 "System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
4500 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
4501 g_assert (create_culture);
4502 mono_method_desc_free (desc);
4505 for (i = 0; i < count; i++) {
4506 MonoReflectionAssemblyName *aname;
4507 guint32 cols [MONO_ASSEMBLYREF_SIZE];
4509 mono_metadata_decode_row (t, i, cols, MONO_ASSEMBLYREF_SIZE);
4511 aname = (MonoReflectionAssemblyName *) mono_object_new (
4512 domain, System_Reflection_AssemblyName);
4514 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_NAME])));
4516 aname->major = cols [MONO_ASSEMBLYREF_MAJOR_VERSION];
4517 aname->minor = cols [MONO_ASSEMBLYREF_MINOR_VERSION];
4518 aname->build = cols [MONO_ASSEMBLYREF_BUILD_NUMBER];
4519 aname->revision = cols [MONO_ASSEMBLYREF_REV_NUMBER];
4520 aname->flags = cols [MONO_ASSEMBLYREF_FLAGS];
4521 aname->versioncompat = 1; /* SameMachine (default) */
4522 aname->hashalg = ASSEMBLY_HASH_SHA1; /* SHA1 (default) */
4523 MONO_OBJECT_SETREF (aname, version, create_version (domain, aname->major, aname->minor, aname->build, aname->revision));
4525 if (create_culture) {
4527 MonoBoolean assembly_ref = 1;
4528 args [0] = mono_string_new (domain, mono_metadata_string_heap (image, cols [MONO_ASSEMBLYREF_CULTURE]));
4529 args [1] = &assembly_ref;
4530 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
4533 if (cols [MONO_ASSEMBLYREF_PUBLIC_KEY]) {
4534 const gchar *pkey_ptr = mono_metadata_blob_heap (image, cols [MONO_ASSEMBLYREF_PUBLIC_KEY]);
4535 guint32 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
4537 if ((cols [MONO_ASSEMBLYREF_FLAGS] & ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG)) {
4538 /* public key token isn't copied - the class library will
4539 automatically generate it from the public key if required */
4540 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4541 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
4543 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
4544 memcpy (mono_array_addr (aname->keyToken, guint8, 0), pkey_ptr, pkey_len);
4547 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
4550 /* note: this function doesn't return the codebase on purpose (i.e. it can
4551 be used under partial trust as path information isn't present). */
4553 mono_array_setref (result, i, aname);
4558 /* move this in some file in mono/util/ */
4560 g_concat_dir_and_file (const char *dir, const char *file)
4562 g_return_val_if_fail (dir != NULL, NULL);
4563 g_return_val_if_fail (file != NULL, NULL);
4566 * If the directory name doesn't have a / on the end, we need
4567 * to add one so we get a proper path to the file
4569 if (dir [strlen(dir) - 1] != G_DIR_SEPARATOR)
4570 return g_strconcat (dir, G_DIR_SEPARATOR_S, file, NULL);
4572 return g_strconcat (dir, file, NULL);
4576 ves_icall_System_Reflection_Assembly_GetManifestResourceInternal (MonoReflectionAssembly *assembly, MonoString *name, gint32 *size, MonoReflectionModule **ref_module)
4578 char *n = mono_string_to_utf8 (name);
4579 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4581 guint32 cols [MONO_MANIFEST_SIZE];
4582 guint32 impl, file_idx;
4586 MONO_ARCH_SAVE_REGS;
4588 for (i = 0; i < table->rows; ++i) {
4589 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4590 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4591 if (strcmp (val, n) == 0)
4595 if (i == table->rows)
4598 impl = cols [MONO_MANIFEST_IMPLEMENTATION];
4601 * this code should only be called after obtaining the
4602 * ResourceInfo and handling the other cases.
4604 g_assert ((impl & MONO_IMPLEMENTATION_MASK) == MONO_IMPLEMENTATION_FILE);
4605 file_idx = impl >> MONO_IMPLEMENTATION_BITS;
4607 module = mono_image_load_file_for_image (assembly->assembly->image, file_idx);
4612 module = assembly->assembly->image;
4614 mono_gc_wbarrier_generic_store (ref_module, (MonoObject*) mono_module_get_object (mono_domain_get (), module));
4616 return (void*)mono_image_get_resource (module, cols [MONO_MANIFEST_OFFSET], (guint32*)size);
4619 ICALL_EXPORT gboolean
4620 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoManifestResourceInfo *info)
4622 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_MANIFESTRESOURCE];
4624 guint32 cols [MONO_MANIFEST_SIZE];
4625 guint32 file_cols [MONO_FILE_SIZE];
4629 MONO_ARCH_SAVE_REGS;
4631 n = mono_string_to_utf8 (name);
4632 for (i = 0; i < table->rows; ++i) {
4633 mono_metadata_decode_row (table, i, cols, MONO_MANIFEST_SIZE);
4634 val = mono_metadata_string_heap (assembly->assembly->image, cols [MONO_MANIFEST_NAME]);
4635 if (strcmp (val, n) == 0)
4639 if (i == table->rows)
4642 if (!cols [MONO_MANIFEST_IMPLEMENTATION]) {
4643 info->location = RESOURCE_LOCATION_EMBEDDED | RESOURCE_LOCATION_IN_MANIFEST;
4646 switch (cols [MONO_MANIFEST_IMPLEMENTATION] & MONO_IMPLEMENTATION_MASK) {
4647 case MONO_IMPLEMENTATION_FILE:
4648 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4649 table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4650 mono_metadata_decode_row (table, i - 1, file_cols, MONO_FILE_SIZE);
4651 val = mono_metadata_string_heap (assembly->assembly->image, file_cols [MONO_FILE_NAME]);
4652 MONO_OBJECT_SETREF (info, filename, mono_string_new (mono_object_domain (assembly), val));
4653 if (file_cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4656 info->location = RESOURCE_LOCATION_EMBEDDED;
4659 case MONO_IMPLEMENTATION_ASSEMBLYREF:
4660 i = cols [MONO_MANIFEST_IMPLEMENTATION] >> MONO_IMPLEMENTATION_BITS;
4661 mono_assembly_load_reference (assembly->assembly->image, i - 1);
4662 if (assembly->assembly->image->references [i - 1] == (gpointer)-1) {
4663 char *msg = g_strdup_printf ("Assembly %d referenced from assembly %s not found ", i - 1, assembly->assembly->image->name);
4664 MonoException *ex = mono_get_exception_file_not_found2 (msg, NULL);
4666 mono_raise_exception (ex);
4668 MONO_OBJECT_SETREF (info, assembly, mono_assembly_get_object (mono_domain_get (), assembly->assembly->image->references [i - 1]));
4670 /* Obtain info recursively */
4671 ves_icall_System_Reflection_Assembly_GetManifestResourceInfoInternal (info->assembly, name, info);
4672 info->location |= RESOURCE_LOCATION_ANOTHER_ASSEMBLY;
4675 case MONO_IMPLEMENTATION_EXP_TYPE:
4676 g_assert_not_reached ();
4684 ICALL_EXPORT MonoObject*
4685 ves_icall_System_Reflection_Assembly_GetFilesInternal (MonoReflectionAssembly *assembly, MonoString *name, MonoBoolean resource_modules)
4687 MonoTableInfo *table = &assembly->assembly->image->tables [MONO_TABLE_FILE];
4688 MonoArray *result = NULL;
4693 MONO_ARCH_SAVE_REGS;
4695 /* check hash if needed */
4697 n = mono_string_to_utf8 (name);
4698 for (i = 0; i < table->rows; ++i) {
4699 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4700 if (strcmp (val, n) == 0) {
4703 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4704 fn = mono_string_new (mono_object_domain (assembly), n);
4706 return (MonoObject*)fn;
4714 for (i = 0; i < table->rows; ++i) {
4715 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA))
4719 result = mono_array_new (mono_object_domain (assembly), mono_defaults.string_class, count);
4722 for (i = 0; i < table->rows; ++i) {
4723 if (resource_modules || !(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
4724 val = mono_metadata_string_heap (assembly->assembly->image, mono_metadata_decode_row_col (table, i, MONO_FILE_NAME));
4725 n = g_concat_dir_and_file (assembly->assembly->basedir, val);
4726 mono_array_setref (result, count, mono_string_new (mono_object_domain (assembly), n));
4731 return (MonoObject*)result;
4734 ICALL_EXPORT MonoArray*
4735 ves_icall_System_Reflection_Assembly_GetModulesInternal (MonoReflectionAssembly *assembly)
4737 MonoDomain *domain = mono_domain_get();
4740 int i, j, file_count = 0;
4741 MonoImage **modules;
4742 guint32 module_count, real_module_count;
4743 MonoTableInfo *table;
4744 guint32 cols [MONO_FILE_SIZE];
4745 MonoImage *image = assembly->assembly->image;
4747 g_assert (image != NULL);
4748 g_assert (!assembly_is_dynamic (assembly->assembly));
4750 table = &image->tables [MONO_TABLE_FILE];
4751 file_count = table->rows;
4753 modules = image->modules;
4754 module_count = image->module_count;
4756 real_module_count = 0;
4757 for (i = 0; i < module_count; ++i)
4759 real_module_count ++;
4761 klass = mono_class_from_name (mono_defaults.corlib, "System.Reflection", "Module");
4762 res = mono_array_new (domain, klass, 1 + real_module_count + file_count);
4764 mono_array_setref (res, 0, mono_module_get_object (domain, image));
4766 for (i = 0; i < module_count; ++i)
4768 mono_array_setref (res, j, mono_module_get_object (domain, modules[i]));
4772 for (i = 0; i < file_count; ++i, ++j) {
4773 mono_metadata_decode_row (table, i, cols, MONO_FILE_SIZE);
4774 if (cols [MONO_FILE_FLAGS] && FILE_CONTAINS_NO_METADATA)
4775 mono_array_setref (res, j, mono_module_file_get_object (domain, image, i));
4777 MonoImage *m = mono_image_load_file_for_image (image, i + 1);
4779 MonoString *fname = mono_string_new (mono_domain_get (), mono_metadata_string_heap (image, cols [MONO_FILE_NAME]));
4780 mono_raise_exception (mono_get_exception_file_not_found2 (NULL, fname));
4782 mono_array_setref (res, j, mono_module_get_object (domain, m));
4789 ICALL_EXPORT MonoReflectionMethod*
4790 ves_icall_GetCurrentMethod (void)
4792 MonoMethod *m = mono_method_get_last_managed ();
4794 while (m->is_inflated)
4795 m = ((MonoMethodInflated*)m)->declaring;
4797 return mono_method_get_object (mono_domain_get (), m, NULL);
4802 mono_method_get_equivalent_method (MonoMethod *method, MonoClass *klass)
4805 if (method->is_inflated && ((MonoMethodInflated*)method)->context.method_inst) {
4806 MonoMethodInflated *inflated = (MonoMethodInflated*)method;
4807 //method is inflated, we should inflate it on the other class
4808 MonoGenericContext ctx;
4809 ctx.method_inst = inflated->context.method_inst;
4810 ctx.class_inst = inflated->context.class_inst;
4811 if (klass->generic_class)
4812 ctx.class_inst = klass->generic_class->context.class_inst;
4813 else if (klass->generic_container)
4814 ctx.class_inst = klass->generic_container->context.class_inst;
4815 return mono_class_inflate_generic_method_full (inflated->declaring, klass, &ctx);
4818 mono_class_setup_methods (method->klass);
4819 if (method->klass->exception_type)
4821 for (i = 0; i < method->klass->method.count; ++i) {
4822 if (method->klass->methods [i] == method) {
4827 mono_class_setup_methods (klass);
4828 if (klass->exception_type)
4830 g_assert (offset >= 0 && offset < klass->method.count);
4831 return klass->methods [offset];
4834 ICALL_EXPORT MonoReflectionMethod*
4835 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternalType (MonoMethod *method, MonoType *type)
4839 klass = mono_class_from_mono_type (type);
4840 if (mono_class_get_generic_type_definition (method->klass) != mono_class_get_generic_type_definition (klass))
4842 if (method->klass != klass) {
4843 method = mono_method_get_equivalent_method (method, klass);
4848 klass = method->klass;
4849 return mono_method_get_object (mono_domain_get (), method, klass);
4852 ICALL_EXPORT MonoReflectionMethod*
4853 ves_icall_System_Reflection_MethodBase_GetMethodFromHandleInternal (MonoMethod *method)
4855 return mono_method_get_object (mono_domain_get (), method, NULL);
4858 ICALL_EXPORT MonoReflectionMethodBody*
4859 ves_icall_System_Reflection_MethodBase_GetMethodBodyInternal (MonoMethod *method)
4861 return mono_method_body_get_object (mono_domain_get (), method);
4864 ICALL_EXPORT MonoReflectionAssembly*
4865 ves_icall_System_Reflection_Assembly_GetExecutingAssembly (void)
4867 MonoMethod *dest = NULL;
4869 MONO_ARCH_SAVE_REGS;
4871 mono_stack_walk_no_il (get_executing, &dest);
4873 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4877 ICALL_EXPORT MonoReflectionAssembly*
4878 ves_icall_System_Reflection_Assembly_GetEntryAssembly (void)
4880 MonoDomain* domain = mono_domain_get ();
4882 MONO_ARCH_SAVE_REGS;
4884 if (!domain->entry_assembly)
4887 return mono_assembly_get_object (domain, domain->entry_assembly);
4890 ICALL_EXPORT MonoReflectionAssembly*
4891 ves_icall_System_Reflection_Assembly_GetCallingAssembly (void)
4896 MONO_ARCH_SAVE_REGS;
4899 mono_stack_walk_no_il (get_executing, &dest);
4901 mono_stack_walk_no_il (get_caller, &dest);
4904 return mono_assembly_get_object (mono_domain_get (), dest->klass->image->assembly);
4907 ICALL_EXPORT MonoString *
4908 ves_icall_System_MonoType_getFullName (MonoReflectionType *object, gboolean full_name,
4909 gboolean assembly_qualified)
4911 MonoDomain *domain = mono_object_domain (object);
4912 MonoTypeNameFormat format;
4917 format = assembly_qualified ?
4918 MONO_TYPE_NAME_FORMAT_ASSEMBLY_QUALIFIED :
4919 MONO_TYPE_NAME_FORMAT_FULL_NAME;
4921 format = MONO_TYPE_NAME_FORMAT_REFLECTION;
4923 name = mono_type_get_name_full (object->type, format);
4927 if (full_name && (object->type->type == MONO_TYPE_VAR || object->type->type == MONO_TYPE_MVAR)) {
4932 res = mono_string_new (domain, name);
4939 vell_icall_MonoType_get_core_clr_security_level (MonoReflectionType *this)
4941 MonoClass *klass = mono_class_from_mono_type (this->type);
4942 mono_class_init_or_throw (klass);
4943 return mono_security_core_clr_class_level (klass);
4947 fill_reflection_assembly_name (MonoDomain *domain, MonoReflectionAssemblyName *aname, MonoAssemblyName *name, const char *absolute, gboolean by_default_version, gboolean default_publickey, gboolean default_token)
4949 static MonoMethod *create_culture = NULL;
4952 const char *pkey_ptr;
4954 MonoBoolean assembly_ref = 0;
4956 MONO_ARCH_SAVE_REGS;
4958 MONO_OBJECT_SETREF (aname, name, mono_string_new (domain, name->name));
4959 aname->major = name->major;
4960 aname->minor = name->minor;
4961 aname->build = name->build;
4962 aname->flags = name->flags;
4963 aname->revision = name->revision;
4964 aname->hashalg = name->hash_alg;
4965 aname->versioncompat = 1; /* SameMachine (default) */
4966 aname->processor_architecture = name->arch;
4968 if (by_default_version)
4969 MONO_OBJECT_SETREF (aname, version, create_version (domain, name->major, name->minor, name->build, name->revision));
4972 if (absolute != NULL && *absolute != '\0') {
4973 const gchar *prepend = "file://";
4976 codebase = g_strdup (absolute);
4981 for (i = strlen (codebase) - 1; i >= 0; i--)
4982 if (codebase [i] == '\\')
4985 if (*codebase == '/' && *(codebase + 1) == '/') {
4988 prepend = "file:///";
4992 result = g_strconcat (prepend, codebase, NULL);
4998 MONO_OBJECT_SETREF (aname, codebase, mono_string_new (domain, codebase));
5002 if (!create_culture) {
5003 MonoMethodDesc *desc = mono_method_desc_new ("System.Globalization.CultureInfo:CreateCulture(string,bool)", TRUE);
5004 create_culture = mono_method_desc_search_in_image (desc, mono_defaults.corlib);
5005 g_assert (create_culture);
5006 mono_method_desc_free (desc);
5009 if (name->culture) {
5010 args [0] = mono_string_new (domain, name->culture);
5011 args [1] = &assembly_ref;
5012 MONO_OBJECT_SETREF (aname, cultureInfo, mono_runtime_invoke (create_culture, NULL, args, NULL));
5015 if (name->public_key) {
5016 pkey_ptr = (char*)name->public_key;
5017 pkey_len = mono_metadata_decode_blob_size (pkey_ptr, &pkey_ptr);
5019 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, pkey_len));
5020 memcpy (mono_array_addr (aname->publicKey, guint8, 0), pkey_ptr, pkey_len);
5021 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5022 } else if (default_publickey) {
5023 MONO_OBJECT_SETREF (aname, publicKey, mono_array_new (domain, mono_defaults.byte_class, 0));
5024 aname->flags |= ASSEMBLYREF_FULL_PUBLIC_KEY_FLAG;
5027 /* MonoAssemblyName keeps the public key token as an hexadecimal string */
5028 if (name->public_key_token [0]) {
5032 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 8));
5033 p = mono_array_addr (aname->keyToken, char, 0);
5035 for (i = 0, j = 0; i < 8; i++) {
5036 *p = g_ascii_xdigit_value (name->public_key_token [j++]) << 4;
5037 *p |= g_ascii_xdigit_value (name->public_key_token [j++]);
5040 } else if (default_token) {
5041 MONO_OBJECT_SETREF (aname, keyToken, mono_array_new (domain, mono_defaults.byte_class, 0));
5045 ICALL_EXPORT MonoString *
5046 ves_icall_System_Reflection_Assembly_get_fullName (MonoReflectionAssembly *assembly)
5048 MonoDomain *domain = mono_object_domain (assembly);
5049 MonoAssembly *mass = assembly->assembly;
5053 name = mono_stringify_assembly_name (&mass->aname);
5054 res = mono_string_new (domain, name);
5061 ves_icall_System_Reflection_Assembly_FillName (MonoReflectionAssembly *assembly, MonoReflectionAssemblyName *aname)
5064 MonoAssembly *mass = assembly->assembly;
5066 MONO_ARCH_SAVE_REGS;
5068 if (g_path_is_absolute (mass->image->name)) {
5069 fill_reflection_assembly_name (mono_object_domain (assembly),
5070 aname, &mass->aname, mass->image->name, TRUE,
5074 absolute = g_build_filename (mass->basedir, mass->image->name, NULL);
5076 fill_reflection_assembly_name (mono_object_domain (assembly),
5077 aname, &mass->aname, absolute, TRUE, TRUE,
5084 ves_icall_System_Reflection_Assembly_InternalGetAssemblyName (MonoString *fname, MonoReflectionAssemblyName *aname)
5087 MonoImageOpenStatus status = MONO_IMAGE_OK;
5090 MonoAssemblyName name;
5093 MONO_ARCH_SAVE_REGS;
5095 filename = mono_string_to_utf8 (fname);
5097 dirname = g_path_get_dirname (filename);
5098 replace_shadow_path (mono_domain_get (), dirname, &filename);
5101 image = mono_image_open (filename, &status);
5107 if (status == MONO_IMAGE_IMAGE_INVALID)
5108 exc = mono_get_exception_bad_image_format2 (NULL, fname);
5110 exc = mono_get_exception_file_not_found2 (NULL, fname);
5111 mono_raise_exception (exc);
5114 res = mono_assembly_fill_assembly_name (image, &name);
5116 mono_image_close (image);
5118 mono_raise_exception (mono_get_exception_argument ("assemblyFile", "The file does not contain a manifest"));
5121 fill_reflection_assembly_name (mono_domain_get (), aname, &name, filename,
5125 mono_image_close (image);
5128 ICALL_EXPORT MonoBoolean
5129 ves_icall_System_Reflection_Assembly_LoadPermissions (MonoReflectionAssembly *assembly,
5130 char **minimum, guint32 *minLength, char **optional, guint32 *optLength, char **refused, guint32 *refLength)
5132 MonoBoolean result = FALSE;
5133 MonoDeclSecurityEntry entry;
5135 /* SecurityAction.RequestMinimum */
5136 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQMIN, &entry)) {
5137 *minimum = entry.blob;
5138 *minLength = entry.size;
5141 /* SecurityAction.RequestOptional */
5142 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQOPT, &entry)) {
5143 *optional = entry.blob;
5144 *optLength = entry.size;
5147 /* SecurityAction.RequestRefuse */
5148 if (mono_declsec_get_assembly_action (assembly->assembly, SECURITY_ACTION_REQREFUSE, &entry)) {
5149 *refused = entry.blob;
5150 *refLength = entry.size;
5158 mono_module_get_types (MonoDomain *domain, MonoImage *image, MonoArray **exceptions, MonoBoolean exportedOnly)
5162 MonoTableInfo *tdef = &image->tables [MONO_TABLE_TYPEDEF];
5164 guint32 attrs, visibility;
5166 /* we start the count from 1 because we skip the special type <Module> */
5169 for (i = 1; i < tdef->rows; ++i) {
5170 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5171 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5172 if (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)
5176 count = tdef->rows - 1;
5178 res = mono_array_new (domain, mono_defaults.monotype_class, count);
5179 *exceptions = mono_array_new (domain, mono_defaults.exception_class, count);
5181 for (i = 1; i < tdef->rows; ++i) {
5182 attrs = mono_metadata_decode_row_col (tdef, i, MONO_TYPEDEF_FLAGS);
5183 visibility = attrs & TYPE_ATTRIBUTE_VISIBILITY_MASK;
5184 if (!exportedOnly || (visibility == TYPE_ATTRIBUTE_PUBLIC || visibility == TYPE_ATTRIBUTE_NESTED_PUBLIC)) {
5186 klass = mono_class_get_checked (image, (i + 1) | MONO_TOKEN_TYPE_DEF, &error);
5187 g_assert (!mono_loader_get_last_error ()); /* Plug any leaks */
5190 mono_array_setref (res, count, mono_type_get_object (domain, &klass->byval_arg));
5192 MonoException *ex = mono_error_convert_to_exception (&error);
5193 mono_array_setref (*exceptions, count, ex);
5202 ICALL_EXPORT MonoArray*
5203 ves_icall_System_Reflection_Assembly_GetTypes (MonoReflectionAssembly *assembly, MonoBoolean exportedOnly)
5205 MonoArray *res = NULL;
5206 MonoArray *exceptions = NULL;
5207 MonoImage *image = NULL;
5208 MonoTableInfo *table = NULL;
5211 int i, len, ex_count;
5213 MONO_ARCH_SAVE_REGS;
5215 domain = mono_object_domain (assembly);
5217 g_assert (!assembly_is_dynamic (assembly->assembly));
5218 image = assembly->assembly->image;
5219 table = &image->tables [MONO_TABLE_FILE];
5220 res = mono_module_get_types (domain, image, &exceptions, exportedOnly);
5222 /* Append data from all modules in the assembly */
5223 for (i = 0; i < table->rows; ++i) {
5224 if (!(mono_metadata_decode_row_col (table, i, MONO_FILE_FLAGS) & FILE_CONTAINS_NO_METADATA)) {
5225 MonoImage *loaded_image = mono_assembly_load_module (image->assembly, i + 1);
5228 MonoArray *res2 = mono_module_get_types (domain, loaded_image, &ex2, exportedOnly);
5229 /* Append the new types to the end of the array */
5230 if (mono_array_length (res2) > 0) {
5232 MonoArray *res3, *ex3;
5234 len1 = mono_array_length (res);
5235 len2 = mono_array_length (res2);
5237 res3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5238 mono_array_memcpy_refs (res3, 0, res, 0, len1);
5239 mono_array_memcpy_refs (res3, len1, res2, 0, len2);
5242 ex3 = mono_array_new (domain, mono_defaults.monotype_class, len1 + len2);
5243 mono_array_memcpy_refs (ex3, 0, exceptions, 0, len1);
5244 mono_array_memcpy_refs (ex3, len1, ex2, 0, len2);
5251 /* the ReflectionTypeLoadException must have all the types (Types property),
5252 * NULL replacing types which throws an exception. The LoaderException must
5253 * contain all exceptions for NULL items.
5256 len = mono_array_length (res);
5259 for (i = 0; i < len; i++) {
5260 MonoReflectionType *t = mono_array_get (res, gpointer, i);
5264 klass = mono_type_get_class (t->type);
5265 if ((klass != NULL) && klass->exception_type) {
5266 /* keep the class in the list */
5267 list = g_list_append (list, klass);
5268 /* and replace Type with NULL */
5269 mono_array_setref (res, i, NULL);
5276 if (list || ex_count) {
5278 MonoException *exc = NULL;
5279 MonoArray *exl = NULL;
5280 int j, length = g_list_length (list) + ex_count;
5282 mono_loader_clear_error ();
5284 exl = mono_array_new (domain, mono_defaults.exception_class, length);
5285 /* Types for which mono_class_get_checked () succeeded */
5286 for (i = 0, tmp = list; tmp; i++, tmp = tmp->next) {
5287 MonoException *exc = mono_class_get_exception_for_failure (tmp->data);
5288 mono_array_setref (exl, i, exc);
5290 /* Types for which it don't */
5291 for (j = 0; j < mono_array_length (exceptions); ++j) {
5292 MonoException *exc = mono_array_get (exceptions, MonoException*, j);
5294 g_assert (i < length);
5295 mono_array_setref (exl, i, exc);
5302 exc = mono_get_exception_reflection_type_load (res, exl);
5303 mono_loader_clear_error ();
5304 mono_raise_exception (exc);
5310 ICALL_EXPORT gboolean
5311 ves_icall_System_Reflection_AssemblyName_ParseName (MonoReflectionAssemblyName *name, MonoString *assname)
5313 MonoAssemblyName aname;
5314 MonoDomain *domain = mono_object_domain (name);
5316 gboolean is_version_defined;
5317 gboolean is_token_defined;
5319 aname.public_key = NULL;
5320 val = mono_string_to_utf8 (assname);
5321 if (!mono_assembly_name_parse_full (val, &aname, TRUE, &is_version_defined, &is_token_defined)) {
5322 g_free ((guint8*) aname.public_key);
5327 fill_reflection_assembly_name (domain, name, &aname, "", is_version_defined,
5328 FALSE, is_token_defined);
5330 mono_assembly_name_free (&aname);
5331 g_free ((guint8*) aname.public_key);
5337 ICALL_EXPORT MonoReflectionType*
5338 ves_icall_System_Reflection_Module_GetGlobalType (MonoReflectionModule *module)
5341 MonoDomain *domain = mono_object_domain (module);
5344 MONO_ARCH_SAVE_REGS;
5346 g_assert (module->image);
5348 if (image_is_dynamic (module->image) && ((MonoDynamicImage*)(module->image))->initial_image)
5349 /* These images do not have a global type */
5352 klass = mono_class_get_checked (module->image, 1 | MONO_TOKEN_TYPE_DEF, &error);
5353 mono_error_raise_exception (&error);
5354 return mono_type_get_object (domain, &klass->byval_arg);
5358 ves_icall_System_Reflection_Module_Close (MonoReflectionModule *module)
5360 /*if (module->image)
5361 mono_image_close (module->image);*/
5364 ICALL_EXPORT MonoString*
5365 ves_icall_System_Reflection_Module_GetGuidInternal (MonoReflectionModule *module)
5367 MonoDomain *domain = mono_object_domain (module);
5369 MONO_ARCH_SAVE_REGS;
5371 g_assert (module->image);
5372 return mono_string_new (domain, module->image->guid);
5375 ICALL_EXPORT gpointer
5376 ves_icall_System_Reflection_Module_GetHINSTANCE (MonoReflectionModule *module)
5379 if (module->image && module->image->is_module_handle)
5380 return module->image->raw_data;
5383 return (gpointer) (-1);
5387 ves_icall_System_Reflection_Module_GetPEKind (MonoImage *image, gint32 *pe_kind, gint32 *machine)
5389 if (image_is_dynamic (image)) {
5390 MonoDynamicImage *dyn = (MonoDynamicImage*)image;
5391 *pe_kind = dyn->pe_kind;
5392 *machine = dyn->machine;
5395 *pe_kind = ((MonoCLIImageInfo*)(image->image_info))->cli_cli_header.ch_flags & 0x3;
5396 *machine = ((MonoCLIImageInfo*)(image->image_info))->cli_header.coff.coff_machine;
5401 ves_icall_System_Reflection_Module_GetMDStreamVersion (MonoImage *image)
5403 return (image->md_version_major << 16) | (image->md_version_minor);
5406 ICALL_EXPORT MonoArray*
5407 ves_icall_System_Reflection_Module_InternalGetTypes (MonoReflectionModule *module)
5409 MonoArray *exceptions;
5412 MONO_ARCH_SAVE_REGS;
5415 return mono_array_new (mono_object_domain (module), mono_defaults.monotype_class, 0);
5417 MonoArray *res = mono_module_get_types (mono_object_domain (module), module->image, &exceptions, FALSE);
5418 for (i = 0; i < mono_array_length (exceptions); ++i) {
5419 MonoException *ex = mono_array_get (exceptions, MonoException *, i);
5421 mono_raise_exception (ex);
5428 mono_memberref_is_method (MonoImage *image, guint32 token)
5430 if (!image_is_dynamic (image)) {
5431 guint32 cols [MONO_MEMBERREF_SIZE];
5433 mono_metadata_decode_row (&image->tables [MONO_TABLE_MEMBERREF], mono_metadata_token_index (token) - 1, cols, MONO_MEMBERREF_SIZE);
5434 sig = mono_metadata_blob_heap (image, cols [MONO_MEMBERREF_SIGNATURE]);
5435 mono_metadata_decode_blob_size (sig, &sig);
5436 return (*sig != 0x6);
5438 MonoClass *handle_class;
5440 if (!mono_lookup_dynamic_token_class (image, token, FALSE, &handle_class, NULL))
5443 return mono_defaults.methodhandle_class == handle_class;
5448 init_generic_context_from_args (MonoGenericContext *context, MonoArray *type_args, MonoArray *method_args)
5451 context->class_inst = mono_metadata_get_generic_inst (mono_array_length (type_args),
5452 mono_array_addr (type_args, MonoType*, 0));
5454 context->class_inst = NULL;
5456 context->method_inst = mono_metadata_get_generic_inst (mono_array_length (method_args),
5457 mono_array_addr (method_args, MonoType*, 0));
5459 context->method_inst = NULL;
5462 ICALL_EXPORT MonoType*
5463 ves_icall_System_Reflection_Module_ResolveTypeToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5466 int table = mono_metadata_token_table (token);
5467 int index = mono_metadata_token_index (token);
5468 MonoGenericContext context;
5471 *resolve_error = ResolveTokenError_Other;
5473 /* Validate token */
5474 if ((table != MONO_TABLE_TYPEDEF) && (table != MONO_TABLE_TYPEREF) &&
5475 (table != MONO_TABLE_TYPESPEC)) {
5476 *resolve_error = ResolveTokenError_BadTable;
5480 if (image_is_dynamic (image)) {
5481 if ((table == MONO_TABLE_TYPEDEF) || (table == MONO_TABLE_TYPEREF)) {
5482 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5483 return klass ? &klass->byval_arg : NULL;
5486 init_generic_context_from_args (&context, type_args, method_args);
5487 klass = mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5488 return klass ? &klass->byval_arg : NULL;
5491 if ((index <= 0) || (index > image->tables [table].rows)) {
5492 *resolve_error = ResolveTokenError_OutOfRange;
5496 init_generic_context_from_args (&context, type_args, method_args);
5497 klass = mono_class_get_checked (image, token, &error);
5499 klass = mono_class_inflate_generic_class_checked (klass, &context, &error);
5500 mono_error_raise_exception (&error);
5503 return &klass->byval_arg;
5508 ICALL_EXPORT MonoMethod*
5509 ves_icall_System_Reflection_Module_ResolveMethodToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5511 int table = mono_metadata_token_table (token);
5512 int index = mono_metadata_token_index (token);
5513 MonoGenericContext context;
5516 *error = ResolveTokenError_Other;
5518 /* Validate token */
5519 if ((table != MONO_TABLE_METHOD) && (table != MONO_TABLE_METHODSPEC) &&
5520 (table != MONO_TABLE_MEMBERREF)) {
5521 *error = ResolveTokenError_BadTable;
5525 if (image_is_dynamic (image)) {
5526 if (table == MONO_TABLE_METHOD)
5527 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5529 if ((table == MONO_TABLE_MEMBERREF) && !(mono_memberref_is_method (image, token))) {
5530 *error = ResolveTokenError_BadTable;
5534 init_generic_context_from_args (&context, type_args, method_args);
5535 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5538 if ((index <= 0) || (index > image->tables [table].rows)) {
5539 *error = ResolveTokenError_OutOfRange;
5542 if ((table == MONO_TABLE_MEMBERREF) && (!mono_memberref_is_method (image, token))) {
5543 *error = ResolveTokenError_BadTable;
5547 init_generic_context_from_args (&context, type_args, method_args);
5548 method = mono_get_method_full (image, token, NULL, &context);
5550 if (mono_loader_get_last_error ())
5551 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
5556 ICALL_EXPORT MonoString*
5557 ves_icall_System_Reflection_Module_ResolveStringToken (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5559 int index = mono_metadata_token_index (token);
5561 *error = ResolveTokenError_Other;
5563 /* Validate token */
5564 if (mono_metadata_token_code (token) != MONO_TOKEN_STRING) {
5565 *error = ResolveTokenError_BadTable;
5569 if (image_is_dynamic (image))
5570 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5572 if ((index <= 0) || (index >= image->heap_us.size)) {
5573 *error = ResolveTokenError_OutOfRange;
5577 /* FIXME: What to do if the index points into the middle of a string ? */
5579 return mono_ldstr (mono_domain_get (), image, index);
5582 ICALL_EXPORT MonoClassField*
5583 ves_icall_System_Reflection_Module_ResolveFieldToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *resolve_error)
5587 int table = mono_metadata_token_table (token);
5588 int index = mono_metadata_token_index (token);
5589 MonoGenericContext context;
5590 MonoClassField *field;
5592 *resolve_error = ResolveTokenError_Other;
5594 /* Validate token */
5595 if ((table != MONO_TABLE_FIELD) && (table != MONO_TABLE_MEMBERREF)) {
5596 *resolve_error = ResolveTokenError_BadTable;
5600 if (image_is_dynamic (image)) {
5601 if (table == MONO_TABLE_FIELD)
5602 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, NULL);
5604 if (mono_memberref_is_method (image, token)) {
5605 *resolve_error = ResolveTokenError_BadTable;
5609 init_generic_context_from_args (&context, type_args, method_args);
5610 return mono_lookup_dynamic_token_class (image, token, FALSE, NULL, &context);
5613 if ((index <= 0) || (index > image->tables [table].rows)) {
5614 *resolve_error = ResolveTokenError_OutOfRange;
5617 if ((table == MONO_TABLE_MEMBERREF) && (mono_memberref_is_method (image, token))) {
5618 *resolve_error = ResolveTokenError_BadTable;
5622 init_generic_context_from_args (&context, type_args, method_args);
5623 field = mono_field_from_token_checked (image, token, &klass, &context, &error);
5624 mono_error_raise_exception (&error);
5630 ICALL_EXPORT MonoObject*
5631 ves_icall_System_Reflection_Module_ResolveMemberToken (MonoImage *image, guint32 token, MonoArray *type_args, MonoArray *method_args, MonoResolveTokenError *error)
5633 int table = mono_metadata_token_table (token);
5635 *error = ResolveTokenError_Other;
5638 case MONO_TABLE_TYPEDEF:
5639 case MONO_TABLE_TYPEREF:
5640 case MONO_TABLE_TYPESPEC: {
5641 MonoType *t = ves_icall_System_Reflection_Module_ResolveTypeToken (image, token, type_args, method_args, error);
5643 return (MonoObject*)mono_type_get_object (mono_domain_get (), t);
5647 case MONO_TABLE_METHOD:
5648 case MONO_TABLE_METHODSPEC: {
5649 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5651 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5655 case MONO_TABLE_FIELD: {
5656 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5658 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5662 case MONO_TABLE_MEMBERREF:
5663 if (mono_memberref_is_method (image, token)) {
5664 MonoMethod *m = ves_icall_System_Reflection_Module_ResolveMethodToken (image, token, type_args, method_args, error);
5666 return (MonoObject*)mono_method_get_object (mono_domain_get (), m, m->klass);
5671 MonoClassField *f = ves_icall_System_Reflection_Module_ResolveFieldToken (image, token, type_args, method_args, error);
5673 return (MonoObject*)mono_field_get_object (mono_domain_get (), f->parent, f);
5680 *error = ResolveTokenError_BadTable;
5686 ICALL_EXPORT MonoArray*
5687 ves_icall_System_Reflection_Module_ResolveSignature (MonoImage *image, guint32 token, MonoResolveTokenError *error)
5689 int table = mono_metadata_token_table (token);
5690 int idx = mono_metadata_token_index (token);
5691 MonoTableInfo *tables = image->tables;
5696 *error = ResolveTokenError_OutOfRange;
5698 /* FIXME: Support other tables ? */
5699 if (table != MONO_TABLE_STANDALONESIG)
5702 if (image_is_dynamic (image))
5705 if ((idx == 0) || (idx > tables [MONO_TABLE_STANDALONESIG].rows))
5708 sig = mono_metadata_decode_row_col (&tables [MONO_TABLE_STANDALONESIG], idx - 1, 0);
5710 ptr = mono_metadata_blob_heap (image, sig);
5711 len = mono_metadata_decode_blob_size (ptr, &ptr);
5713 res = mono_array_new (mono_domain_get (), mono_defaults.byte_class, len);
5714 memcpy (mono_array_addr (res, guint8, 0), ptr, len);
5718 ICALL_EXPORT MonoReflectionType*
5719 ves_icall_ModuleBuilder_create_modified_type (MonoReflectionTypeBuilder *tb, MonoString *smodifiers)
5722 int isbyref = 0, rank;
5723 char *str = mono_string_to_utf8 (smodifiers);
5726 MONO_ARCH_SAVE_REGS;
5728 klass = mono_class_from_mono_type (tb->type.type);
5730 /* logic taken from mono_reflection_parse_type(): keep in sync */
5734 if (isbyref) { /* only one level allowed by the spec */
5741 return mono_type_get_object (mono_object_domain (tb), &klass->this_arg);
5744 klass = mono_ptr_class_get (&klass->byval_arg);
5745 mono_class_init (klass);
5756 else if (*p != '*') { /* '*' means unknown lower bound */
5767 klass = mono_array_class_get (klass, rank);
5768 mono_class_init (klass);
5775 return mono_type_get_object (mono_object_domain (tb), &klass->byval_arg);
5778 ICALL_EXPORT MonoBoolean
5779 ves_icall_Type_IsArrayImpl (MonoReflectionType *t)
5784 MONO_ARCH_SAVE_REGS;
5787 res = !type->byref && (type->type == MONO_TYPE_ARRAY || type->type == MONO_TYPE_SZARRAY);
5793 check_for_invalid_type (MonoClass *klass)
5797 if (klass->byval_arg.type != MONO_TYPE_TYPEDBYREF)
5800 name = mono_type_get_full_name (klass);
5801 str = mono_string_new (mono_domain_get (), name);
5803 mono_raise_exception ((MonoException*)mono_get_exception_type_load (str, NULL));
5806 ICALL_EXPORT MonoReflectionType *
5807 ves_icall_Type_make_array_type (MonoReflectionType *type, int rank)
5809 MonoClass *klass, *aklass;
5811 MONO_ARCH_SAVE_REGS;
5813 klass = mono_class_from_mono_type (type->type);
5814 check_for_invalid_type (klass);
5816 if (rank == 0) //single dimentional array
5817 aklass = mono_array_class_get (klass, 1);
5819 aklass = mono_bounded_array_class_get (klass, rank, TRUE);
5821 return mono_type_get_object (mono_object_domain (type), &aklass->byval_arg);
5824 ICALL_EXPORT MonoReflectionType *
5825 ves_icall_Type_make_byref_type (MonoReflectionType *type)
5829 MONO_ARCH_SAVE_REGS;
5831 klass = mono_class_from_mono_type (type->type);
5832 mono_class_init_or_throw (klass);
5833 check_for_invalid_type (klass);
5835 return mono_type_get_object (mono_object_domain (type), &klass->this_arg);
5838 ICALL_EXPORT MonoReflectionType *
5839 ves_icall_Type_MakePointerType (MonoReflectionType *type)
5841 MonoClass *klass, *pklass;
5843 klass = mono_class_from_mono_type (type->type);
5844 mono_class_init_or_throw (klass);
5845 check_for_invalid_type (klass);
5847 pklass = mono_ptr_class_get (type->type);
5849 return mono_type_get_object (mono_object_domain (type), &pklass->byval_arg);
5852 ICALL_EXPORT MonoObject *
5853 ves_icall_System_Delegate_CreateDelegate_internal (MonoReflectionType *type, MonoObject *target,
5854 MonoReflectionMethod *info, MonoBoolean throwOnBindFailure)
5856 MonoClass *delegate_class = mono_class_from_mono_type (type->type);
5857 MonoObject *delegate;
5859 MonoMethod *method = info->method;
5861 MONO_ARCH_SAVE_REGS;
5863 mono_class_init_or_throw (delegate_class);
5865 mono_assert (delegate_class->parent == mono_defaults.multicastdelegate_class);
5867 if (mono_security_core_clr_enabled ()) {
5868 if (!mono_security_core_clr_ensure_delegate_creation (method, throwOnBindFailure))
5872 delegate = mono_object_new (mono_object_domain (type), delegate_class);
5874 if (method_is_dynamic (method)) {
5875 /* Creating a trampoline would leak memory */
5876 func = mono_compile_method (method);
5878 if (target && method->flags & METHOD_ATTRIBUTE_VIRTUAL && method->klass != mono_object_class (target))
5879 method = mono_object_get_virtual_method (target, method);
5880 func = mono_create_ftnptr (mono_domain_get (),
5881 mono_runtime_create_jump_trampoline (mono_domain_get (), method, TRUE));
5884 mono_delegate_ctor_with_method (delegate, target, func, method);
5890 ves_icall_System_Delegate_SetMulticastInvoke (MonoDelegate *this)
5892 /* Reset the invoke impl to the default one */
5893 this->invoke_impl = mono_runtime_create_delegate_trampoline (this->object.vtable->klass);
5897 * Magic number to convert a time which is relative to
5898 * Jan 1, 1970 into a value which is relative to Jan 1, 0001.
5900 #define EPOCH_ADJUST ((guint64)62135596800LL)
5903 * Magic number to convert FILETIME base Jan 1, 1601 to DateTime - base Jan, 1, 0001
5905 #define FILETIME_ADJUST ((guint64)504911232000000000LL)
5908 /* convert a SYSTEMTIME which is of the form "last thursday in october" to a real date */
5910 convert_to_absolute_date(SYSTEMTIME *date)
5912 #define IS_LEAP(y) ((y % 4) == 0 && ((y % 100) != 0 || (y % 400) == 0))
5913 static int days_in_month[] = { 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5914 static int leap_days_in_month[] = { 31, 29, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31};
5915 /* from the calendar FAQ */
5916 int a = (14 - date->wMonth) / 12;
5917 int y = date->wYear - a;
5918 int m = date->wMonth + 12 * a - 2;
5919 int d = (1 + y + y/4 - y/100 + y/400 + (31*m)/12) % 7;
5921 /* d is now the day of the week for the first of the month (0 == Sunday) */
5923 int day_of_week = date->wDayOfWeek;
5925 /* set day_in_month to the first day in the month which falls on day_of_week */
5926 int day_in_month = 1 + (day_of_week - d);
5927 if (day_in_month <= 0)
5930 /* wDay is 1 for first weekday in month, 2 for 2nd ... 5 means last - so work that out allowing for days in the month */
5931 date->wDay = day_in_month + (date->wDay - 1) * 7;
5932 if (date->wDay > (IS_LEAP(date->wYear) ? leap_days_in_month[date->wMonth - 1] : days_in_month[date->wMonth - 1]))
5939 * Return's the offset from GMT of a local time.
5941 * tm is a local time
5942 * t is the same local time as seconds.
5945 gmt_offset(struct tm *tm, time_t t)
5947 #if defined (HAVE_TM_GMTOFF)
5948 return tm->tm_gmtoff;
5953 g.tm_isdst = tm->tm_isdst;
5955 return (int)difftime(t, t2);
5960 * This is heavily based on zdump.c from glibc 2.2.
5962 * * data[0]: start of daylight saving time (in DateTime ticks).
5963 * * data[1]: end of daylight saving time (in DateTime ticks).
5964 * * data[2]: utcoffset (in TimeSpan ticks).
5965 * * data[3]: additional offset when daylight saving (in TimeSpan ticks).
5966 * * name[0]: name of this timezone when not daylight saving.
5967 * * name[1]: name of this timezone when daylight saving.
5969 * FIXME: This only works with "standard" Unix dates (years between 1900 and 2100) while
5970 * the class library allows years between 1 and 9999.
5972 * Returns true on success and zero on failure.
5974 ICALL_EXPORT guint32
5975 ves_icall_System_CurrentSystemTimeZone_GetTimeZoneData (guint32 year, MonoArray **data, MonoArray **names)
5978 MonoDomain *domain = mono_domain_get ();
5979 struct tm start, tt;
5982 long int gmtoff, gmtoff_after, gmtoff_st, gmtoff_ds;
5983 int day, transitioned;
5986 gmtoff_st = gmtoff_ds = transitioned = 0;
5988 MONO_ARCH_SAVE_REGS;
5990 MONO_CHECK_ARG_NULL (data);
5991 MONO_CHECK_ARG_NULL (names);
5993 mono_gc_wbarrier_generic_store (data, (MonoObject*) mono_array_new (domain, mono_defaults.int64_class, 4));
5994 mono_gc_wbarrier_generic_store (names, (MonoObject*) mono_array_new (domain, mono_defaults.string_class, 2));
5997 * no info is better than crashing: we'll need our own tz data
5998 * to make this work properly, anyway. The range is probably
5999 * reduced to 1970 .. 2037 because that is what mktime is
6000 * guaranteed to support (we get into an infinite loop
6004 memset (&start, 0, sizeof (start));
6007 start.tm_year = year-1900;
6009 t = mktime (&start);
6011 if ((year < 1970) || (year > 2037) || (t == -1)) {
6013 tt = *localtime (&t);
6014 strftime (tzone, sizeof (tzone), "%Z", &tt);
6015 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6016 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6020 gmtoff = gmt_offset (&start, t);
6022 /* For each day of the year, calculate the tm_gmtoff. */
6023 for (day = 0; day < 365 && transitioned < 2; day++) {
6026 tt = *localtime (&t);
6028 gmtoff_after = gmt_offset(&tt, t);
6030 /* Daylight saving starts or ends here. */
6031 if (gmtoff_after != gmtoff) {
6035 /* Try to find the exact hour when daylight saving starts/ends. */
6039 tt1 = *localtime (&t1);
6040 } while (gmt_offset (&tt1, t1) != gmtoff);
6042 /* Try to find the exact minute when daylight saving starts/ends. */
6045 tt1 = *localtime (&t1);
6046 } while (gmt_offset (&tt1, t1) == gmtoff);
6048 strftime (tzone, sizeof (tzone), "%Z", &tt);
6050 /* Write data, if we're already in daylight saving, we're done. */
6052 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6053 mono_array_set ((*data), gint64, 0, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6054 if (gmtoff_ds == 0) {
6056 gmtoff_ds = gmtoff_after;
6063 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6064 mono_array_set ((*data), gint64, 1, ((gint64)t1 + EPOCH_ADJUST) * 10000000L);
6065 if (gmtoff_ds == 0) {
6066 gmtoff_st = gmtoff_after;
6072 /* This is only set once when we enter daylight saving. */
6074 mono_array_set ((*data), gint64, 2, (gint64)gmtoff_st * 10000000L);
6075 mono_array_set ((*data), gint64, 3, (gint64)(gmtoff_ds - gmtoff_st) * 10000000L);
6077 gmtoff = gmt_offset (&tt, t);
6081 if (transitioned < 2) {
6082 strftime (tzone, sizeof (tzone), "%Z", &tt);
6083 mono_array_setref ((*names), 0, mono_string_new (domain, tzone));
6084 mono_array_setref ((*names), 1, mono_string_new (domain, tzone));
6085 mono_array_set ((*data), gint64, 0, 0);
6086 mono_array_set ((*data), gint64, 1, 0);
6087 mono_array_set ((*data), gint64, 2, (gint64) gmtoff * 10000000L);
6088 mono_array_set ((*data), gint64, 3, 0);
6093 MonoDomain *domain = mono_domain_get ();
6094 TIME_ZONE_INFORMATION tz_info;
6099 tz_id = GetTimeZoneInformation (&tz_info);
6100 if (tz_id == TIME_ZONE_ID_INVALID)
6103 MONO_CHECK_ARG_NULL (data);
6104 MONO_CHECK_ARG_NULL (names);
6106 mono_gc_wbarrier_generic_store (data, mono_array_new (domain, mono_defaults.int64_class, 4));
6107 mono_gc_wbarrier_generic_store (names, mono_array_new (domain, mono_defaults.string_class, 2));
6109 for (i = 0; i < 32; ++i)
6110 if (!tz_info.DaylightName [i])
6112 mono_array_setref ((*names), 1, mono_string_new_utf16 (domain, tz_info.DaylightName, i));
6113 for (i = 0; i < 32; ++i)
6114 if (!tz_info.StandardName [i])
6116 mono_array_setref ((*names), 0, mono_string_new_utf16 (domain, tz_info.StandardName, i));
6118 if ((year <= 1601) || (year > 30827)) {
6120 * According to MSDN, the MS time functions can't handle dates outside
6126 /* even if the timezone has no daylight savings it may have Bias (e.g. GMT+13 it seems) */
6127 if (tz_id != TIME_ZONE_ID_UNKNOWN) {
6128 tz_info.StandardDate.wYear = year;
6129 convert_to_absolute_date(&tz_info.StandardDate);
6130 err = SystemTimeToFileTime (&tz_info.StandardDate, &ft);
6135 mono_array_set ((*data), gint64, 1, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6136 tz_info.DaylightDate.wYear = year;
6137 convert_to_absolute_date(&tz_info.DaylightDate);
6138 err = SystemTimeToFileTime (&tz_info.DaylightDate, &ft);
6143 mono_array_set ((*data), gint64, 0, FILETIME_ADJUST + (((guint64)ft.dwHighDateTime<<32) | ft.dwLowDateTime));
6145 mono_array_set ((*data), gint64, 2, (tz_info.Bias + tz_info.StandardBias) * -600000000LL);
6146 mono_array_set ((*data), gint64, 3, (tz_info.DaylightBias - tz_info.StandardBias) * -600000000LL);
6154 static inline gint32
6155 mono_array_get_byte_length (MonoArray *array)
6161 klass = array->obj.vtable->klass;
6163 if (array->bounds == NULL)
6164 length = array->max_length;
6167 for (i = 0; i < klass->rank; ++ i)
6168 length *= array->bounds [i].length;
6171 switch (klass->element_class->byval_arg.type) {
6174 case MONO_TYPE_BOOLEAN:
6178 case MONO_TYPE_CHAR:
6186 return length * sizeof (gpointer);
6197 ves_icall_System_Buffer_ByteLengthInternal (MonoArray *array)
6199 MONO_ARCH_SAVE_REGS;
6201 return mono_array_get_byte_length (array);
6205 ves_icall_System_Buffer_GetByteInternal (MonoArray *array, gint32 idx)
6207 MONO_ARCH_SAVE_REGS;
6209 return mono_array_get (array, gint8, idx);
6213 ves_icall_System_Buffer_SetByteInternal (MonoArray *array, gint32 idx, gint8 value)
6215 MONO_ARCH_SAVE_REGS;
6217 mono_array_set (array, gint8, idx, value);
6220 ICALL_EXPORT MonoBoolean
6221 ves_icall_System_Buffer_BlockCopyInternal (MonoArray *src, gint32 src_offset, MonoArray *dest, gint32 dest_offset, gint32 count)
6223 guint8 *src_buf, *dest_buf;
6225 MONO_ARCH_SAVE_REGS;
6227 /* This is called directly from the class libraries without going through the managed wrapper */
6228 MONO_CHECK_ARG_NULL (src);
6229 MONO_CHECK_ARG_NULL (dest);
6231 /* watch out for integer overflow */
6232 if ((src_offset > mono_array_get_byte_length (src) - count) || (dest_offset > mono_array_get_byte_length (dest) - count))
6235 src_buf = (guint8 *)src->vector + src_offset;
6236 dest_buf = (guint8 *)dest->vector + dest_offset;
6239 memcpy (dest_buf, src_buf, count);
6241 memmove (dest_buf, src_buf, count); /* Source and dest are the same array */
6246 #ifndef DISABLE_REMOTING
6247 ICALL_EXPORT MonoObject *
6248 ves_icall_Remoting_RealProxy_GetTransparentProxy (MonoObject *this, MonoString *class_name)
6250 MonoDomain *domain = mono_object_domain (this);
6252 MonoRealProxy *rp = ((MonoRealProxy *)this);
6253 MonoTransparentProxy *tp;
6257 MONO_ARCH_SAVE_REGS;
6259 res = mono_object_new (domain, mono_defaults.transparent_proxy_class);
6260 tp = (MonoTransparentProxy*) res;
6262 MONO_OBJECT_SETREF (tp, rp, rp);
6263 type = ((MonoReflectionType *)rp->class_to_proxy)->type;
6264 klass = mono_class_from_mono_type (type);
6266 tp->custom_type_info = (mono_object_isinst (this, mono_defaults.iremotingtypeinfo_class) != NULL);
6267 tp->remote_class = mono_remote_class (domain, class_name, klass);
6269 res->vtable = mono_remote_class_vtable (domain, tp->remote_class, rp);
6273 ICALL_EXPORT MonoReflectionType *
6274 ves_icall_Remoting_RealProxy_InternalGetProxyType (MonoTransparentProxy *tp)
6276 return mono_type_get_object (mono_object_domain (tp), &tp->remote_class->proxy_class->byval_arg);
6280 /* System.Environment */
6283 ves_icall_System_Environment_get_UserName (void)
6285 MONO_ARCH_SAVE_REGS;
6287 /* using glib is more portable */
6288 return mono_string_new (mono_domain_get (), g_get_user_name ());
6292 ICALL_EXPORT MonoString *
6293 ves_icall_System_Environment_get_MachineName (void)
6295 #if defined (HOST_WIN32)
6300 len = MAX_COMPUTERNAME_LENGTH + 1;
6301 buf = g_new (gunichar2, len);
6304 if (GetComputerName (buf, (PDWORD) &len))
6305 result = mono_string_new_utf16 (mono_domain_get (), buf, len);
6309 #elif !defined(DISABLE_SOCKETS)
6313 if (gethostname (buf, sizeof (buf)) == 0)
6314 result = mono_string_new (mono_domain_get (), buf);
6320 return mono_string_new (mono_domain_get (), "mono");
6325 ves_icall_System_Environment_get_Platform (void)
6327 #if defined (TARGET_WIN32)
6330 #elif defined(__MACH__)
6333 // Notice that the value is hidden from user code, and only exposed
6334 // to mscorlib. This is due to Mono's Unix/MacOS code predating the
6335 // define and making assumptions based on Unix/128/4 values before there
6336 // was a MacOS define. Lots of code would assume that not-Unix meant
6337 // Windows, but in this case, it would be OSX.
6346 ICALL_EXPORT MonoString *
6347 ves_icall_System_Environment_get_NewLine (void)
6349 MONO_ARCH_SAVE_REGS;
6351 #if defined (HOST_WIN32)
6352 return mono_string_new (mono_domain_get (), "\r\n");
6354 return mono_string_new (mono_domain_get (), "\n");
6358 ICALL_EXPORT MonoString *
6359 ves_icall_System_Environment_GetEnvironmentVariable (MonoString *name)
6364 MONO_ARCH_SAVE_REGS;
6369 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6370 value = g_getenv (utf8_name);
6377 return mono_string_new (mono_domain_get (), value);
6381 * There is no standard way to get at environ.
6384 #ifndef __MINGW32_VERSION
6385 #if defined(__APPLE__) && !defined (__arm__)
6386 /* Apple defines this in crt_externs.h but doesn't provide that header for
6387 * arm-apple-darwin9. We'll manually define the symbol on Apple as it does
6388 * in fact exist on all implementations (so far)
6390 gchar ***_NSGetEnviron(void);
6391 #define environ (*_NSGetEnviron())
6399 ICALL_EXPORT MonoArray *
6400 ves_icall_System_Environment_GetEnvironmentVariableNames (void)
6411 env_strings = GetEnvironmentStrings();
6414 env_string = env_strings;
6415 while (*env_string != '\0') {
6416 /* weird case that MS seems to skip */
6417 if (*env_string != '=')
6419 while (*env_string != '\0')
6425 domain = mono_domain_get ();
6426 names = mono_array_new (domain, mono_defaults.string_class, n);
6430 env_string = env_strings;
6431 while (*env_string != '\0') {
6432 /* weird case that MS seems to skip */
6433 if (*env_string != '=') {
6434 equal_str = wcschr(env_string, '=');
6435 g_assert(equal_str);
6436 str = mono_string_new_utf16 (domain, env_string, equal_str-env_string);
6437 mono_array_setref (names, n, str);
6440 while (*env_string != '\0')
6445 FreeEnvironmentStrings (env_strings);
6457 MONO_ARCH_SAVE_REGS;
6460 for (e = environ; *e != 0; ++ e)
6463 domain = mono_domain_get ();
6464 names = mono_array_new (domain, mono_defaults.string_class, n);
6467 for (e = environ; *e != 0; ++ e) {
6468 parts = g_strsplit (*e, "=", 2);
6470 str = mono_string_new (domain, *parts);
6471 mono_array_setref (names, n, str);
6484 * If your platform lacks setenv/unsetenv, you must upgrade your glib.
6486 #if !GLIB_CHECK_VERSION(2,4,0)
6487 #define g_setenv(a,b,c) setenv(a,b,c)
6488 #define g_unsetenv(a) unsetenv(a)
6492 ves_icall_System_Environment_InternalSetEnvironmentVariable (MonoString *name, MonoString *value)
6495 gunichar2 *utf16_name, *utf16_value;
6497 gchar *utf8_name, *utf8_value;
6501 MONO_ARCH_SAVE_REGS;
6504 utf16_name = mono_string_to_utf16 (name);
6505 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6506 SetEnvironmentVariable (utf16_name, NULL);
6507 g_free (utf16_name);
6511 utf16_value = mono_string_to_utf16 (value);
6513 SetEnvironmentVariable (utf16_name, utf16_value);
6515 g_free (utf16_name);
6516 g_free (utf16_value);
6518 utf8_name = mono_string_to_utf8 (name); /* FIXME: this should be ascii */
6520 if ((value == NULL) || (mono_string_length (value) == 0) || (mono_string_chars (value)[0] == 0)) {
6521 g_unsetenv (utf8_name);
6526 utf8_value = mono_string_to_utf8_checked (value, &error);
6527 if (!mono_error_ok (&error)) {
6529 mono_error_raise_exception (&error);
6531 g_setenv (utf8_name, utf8_value, TRUE);
6534 g_free (utf8_value);
6539 ves_icall_System_Environment_Exit (int result)
6541 MONO_ARCH_SAVE_REGS;
6543 mono_environment_exitcode_set (result);
6545 /* FIXME: There are some cleanup hangs that should be worked out, but
6546 * if the program is going to exit, everything will be cleaned up when
6547 * NaCl exits anyway.
6549 #ifndef __native_client__
6550 if (!mono_runtime_try_shutdown ())
6551 mono_thread_exit ();
6553 /* Suspend all managed threads since the runtime is going away */
6554 mono_thread_suspend_all_other_threads ();
6556 mono_runtime_quit ();
6559 /* we may need to do some cleanup here... */
6563 ICALL_EXPORT MonoString*
6564 ves_icall_System_Environment_GetGacPath (void)
6566 return mono_string_new (mono_domain_get (), mono_assembly_getrootdir ());
6569 ICALL_EXPORT MonoString*
6570 ves_icall_System_Environment_GetWindowsFolderPath (int folder)
6572 #if defined (HOST_WIN32)
6573 #ifndef CSIDL_FLAG_CREATE
6574 #define CSIDL_FLAG_CREATE 0x8000
6577 WCHAR path [MAX_PATH];
6578 /* Create directory if no existing */
6579 if (SUCCEEDED (SHGetFolderPathW (NULL, folder | CSIDL_FLAG_CREATE, NULL, 0, path))) {
6583 return mono_string_new_utf16 (mono_domain_get (), path, len);
6586 g_warning ("ves_icall_System_Environment_GetWindowsFolderPath should only be called on Windows!");
6588 return mono_string_new (mono_domain_get (), "");
6591 ICALL_EXPORT MonoArray *
6592 ves_icall_System_Environment_GetLogicalDrives (void)
6594 gunichar2 buf [256], *ptr, *dname;
6596 guint initial_size = 127, size = 128;
6599 MonoString *drivestr;
6600 MonoDomain *domain = mono_domain_get ();
6603 MONO_ARCH_SAVE_REGS;
6608 while (size > initial_size) {
6609 size = (guint) GetLogicalDriveStrings (initial_size, ptr);
6610 if (size > initial_size) {
6613 ptr = g_malloc0 ((size + 1) * sizeof (gunichar2));
6614 initial_size = size;
6628 result = mono_array_new (domain, mono_defaults.string_class, ndrives);
6633 while (*u16) { u16++; len ++; }
6634 drivestr = mono_string_new_utf16 (domain, dname, len);
6635 mono_array_setref (result, ndrives++, drivestr);
6645 ICALL_EXPORT MonoString *
6646 ves_icall_System_IO_DriveInfo_GetDriveFormat (MonoString *path)
6648 gunichar2 volume_name [MAX_PATH + 1];
6650 if (GetVolumeInformation (mono_string_chars (path), NULL, 0, NULL, NULL, NULL, volume_name, MAX_PATH + 1) == FALSE)
6652 return mono_string_from_utf16 (volume_name);
6655 ICALL_EXPORT MonoString *
6656 ves_icall_System_Environment_InternalGetHome (void)
6658 MONO_ARCH_SAVE_REGS;
6660 return mono_string_new (mono_domain_get (), g_get_home_dir ());
6663 static const char *encodings [] = {
6665 "ascii", "us_ascii", "us", "ansi_x3.4_1968",
6666 "ansi_x3.4_1986", "cp367", "csascii", "ibm367",
6667 "iso_ir_6", "iso646_us", "iso_646.irv:1991",
6669 "utf_7", "csunicode11utf7", "unicode_1_1_utf_7",
6670 "unicode_2_0_utf_7", "x_unicode_1_1_utf_7",
6671 "x_unicode_2_0_utf_7",
6673 "utf_8", "unicode_1_1_utf_8", "unicode_2_0_utf_8",
6674 "x_unicode_1_1_utf_8", "x_unicode_2_0_utf_8",
6676 "utf_16", "UTF_16LE", "ucs_2", "unicode",
6679 "unicodefffe", "utf_16be",
6686 * Returns the internal codepage, if the value of "int_code_page" is
6687 * 1 at entry, and we can not compute a suitable code page number,
6688 * returns the code page as a string
6690 ICALL_EXPORT MonoString*
6691 ves_icall_System_Text_Encoding_InternalCodePage (gint32 *int_code_page)
6696 char *codepage = NULL;
6698 int want_name = *int_code_page;
6701 *int_code_page = -1;
6702 MONO_ARCH_SAVE_REGS;
6704 g_get_charset (&cset);
6705 c = codepage = strdup (cset);
6706 for (c = codepage; *c; c++){
6707 if (isascii (*c) && isalpha (*c))
6712 /* g_print ("charset: %s\n", cset); */
6714 /* handle some common aliases */
6717 for (i = 0; p != 0; ){
6718 if ((gssize) p < 7){
6720 p = encodings [++i];
6723 if (strcmp (p, codepage) == 0){
6724 *int_code_page = code;
6727 p = encodings [++i];
6730 if (strstr (codepage, "utf_8") != NULL)
6731 *int_code_page |= 0x10000000;
6734 if (want_name && *int_code_page == -1)
6735 return mono_string_new (mono_domain_get (), cset);
6740 ICALL_EXPORT MonoBoolean
6741 ves_icall_System_Environment_get_HasShutdownStarted (void)
6743 if (mono_runtime_is_shutting_down ())
6746 if (mono_domain_is_unloading (mono_domain_get ()))
6753 ves_icall_System_Environment_BroadcastSettingChange (void)
6756 SendMessageTimeout (HWND_BROADCAST, WM_SETTINGCHANGE, (WPARAM)NULL, (LPARAM)L"Environment", SMTO_ABORTIFHUNG, 2000, 0);
6761 ves_icall_MonoMethodMessage_InitMessage (MonoMethodMessage *this,
6762 MonoReflectionMethod *method,
6763 MonoArray *out_args)
6765 MONO_ARCH_SAVE_REGS;
6767 mono_message_init (mono_object_domain (this), this, method, out_args);
6770 #ifndef DISABLE_REMOTING
6771 ICALL_EXPORT MonoBoolean
6772 ves_icall_IsTransparentProxy (MonoObject *proxy)
6774 MONO_ARCH_SAVE_REGS;
6779 if (proxy->vtable->klass == mono_defaults.transparent_proxy_class)
6785 ICALL_EXPORT MonoReflectionMethod *
6786 ves_icall_Remoting_RemotingServices_GetVirtualMethod (
6787 MonoReflectionType *rtype, MonoReflectionMethod *rmethod)
6791 MonoMethod **vtable;
6792 MonoMethod *res = NULL;
6794 MONO_CHECK_ARG_NULL (rtype);
6795 MONO_CHECK_ARG_NULL (rmethod);
6797 method = rmethod->method;
6798 klass = mono_class_from_mono_type (rtype->type);
6799 mono_class_init_or_throw (klass);
6801 if (MONO_CLASS_IS_INTERFACE (klass))
6804 if (method->flags & METHOD_ATTRIBUTE_STATIC)
6807 if ((method->flags & METHOD_ATTRIBUTE_FINAL) || !(method->flags & METHOD_ATTRIBUTE_VIRTUAL)) {
6808 if (klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE))
6814 mono_class_setup_vtable (klass);
6815 vtable = klass->vtable;
6817 if (method->klass->flags & TYPE_ATTRIBUTE_INTERFACE) {
6818 gboolean variance_used = FALSE;
6819 /*MS fails with variant interfaces but it's the right thing to do anyway.*/
6820 int offs = mono_class_interface_offset_with_variance (klass, method->klass, &variance_used);
6822 res = vtable [offs + method->slot];
6824 if (!(klass == method->klass || mono_class_is_subclass_of (klass, method->klass, FALSE)))
6827 if (method->slot != -1)
6828 res = vtable [method->slot];
6834 return mono_method_get_object (mono_domain_get (), res, NULL);
6838 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6843 MONO_ARCH_SAVE_REGS;
6845 klass = mono_class_from_mono_type (type->type);
6846 vtable = mono_class_vtable_full (mono_domain_get (), klass, TRUE);
6848 mono_vtable_set_is_remote (vtable, enable);
6851 #else /* DISABLE_REMOTING */
6854 ves_icall_System_Runtime_Activation_ActivationServices_EnableProxyActivation (MonoReflectionType *type, MonoBoolean enable)
6856 g_assert_not_reached ();
6861 ICALL_EXPORT MonoObject *
6862 ves_icall_System_Runtime_Activation_ActivationServices_AllocateUninitializedClassInstance (MonoReflectionType *type)
6867 MONO_ARCH_SAVE_REGS;
6869 domain = mono_object_domain (type);
6870 klass = mono_class_from_mono_type (type->type);
6871 mono_class_init_or_throw (klass);
6873 if (MONO_CLASS_IS_INTERFACE (klass) || (klass->flags & TYPE_ATTRIBUTE_ABSTRACT))
6874 mono_raise_exception (mono_get_exception_argument ("type", "Type cannot be instantiated"));
6876 if (klass->rank >= 1) {
6877 g_assert (klass->rank == 1);
6878 return (MonoObject *) mono_array_new (domain, klass->element_class, 0);
6880 /* Bypass remoting object creation check */
6881 return mono_object_new_alloc_specific (mono_class_vtable_full (domain, klass, TRUE));
6885 ICALL_EXPORT MonoString *
6886 ves_icall_System_IO_get_temp_path (void)
6888 MONO_ARCH_SAVE_REGS;
6890 return mono_string_new (mono_domain_get (), g_get_tmp_dir ());
6893 #ifndef PLATFORM_NO_DRIVEINFO
6894 ICALL_EXPORT MonoBoolean
6895 ves_icall_System_IO_DriveInfo_GetDiskFreeSpace (MonoString *path_name, guint64 *free_bytes_avail,
6896 guint64 *total_number_of_bytes, guint64 *total_number_of_free_bytes,
6900 ULARGE_INTEGER wapi_free_bytes_avail;
6901 ULARGE_INTEGER wapi_total_number_of_bytes;
6902 ULARGE_INTEGER wapi_total_number_of_free_bytes;
6904 MONO_ARCH_SAVE_REGS;
6906 *error = ERROR_SUCCESS;
6907 result = GetDiskFreeSpaceEx (mono_string_chars (path_name), &wapi_free_bytes_avail, &wapi_total_number_of_bytes,
6908 &wapi_total_number_of_free_bytes);
6911 *free_bytes_avail = wapi_free_bytes_avail.QuadPart;
6912 *total_number_of_bytes = wapi_total_number_of_bytes.QuadPart;
6913 *total_number_of_free_bytes = wapi_total_number_of_free_bytes.QuadPart;
6915 *free_bytes_avail = 0;
6916 *total_number_of_bytes = 0;
6917 *total_number_of_free_bytes = 0;
6918 *error = GetLastError ();
6924 ICALL_EXPORT guint32
6925 ves_icall_System_IO_DriveInfo_GetDriveType (MonoString *root_path_name)
6927 MONO_ARCH_SAVE_REGS;
6929 return GetDriveType (mono_string_chars (root_path_name));
6933 ICALL_EXPORT gpointer
6934 ves_icall_RuntimeMethod_GetFunctionPointer (MonoMethod *method)
6936 MONO_ARCH_SAVE_REGS;
6938 return mono_compile_method (method);
6941 ICALL_EXPORT MonoString *
6942 ves_icall_System_Configuration_DefaultConfig_get_machine_config_path (void)
6947 MONO_ARCH_SAVE_REGS;
6949 path = g_build_path (G_DIR_SEPARATOR_S, mono_get_config_dir (), "mono", mono_get_runtime_info ()->framework_version, "machine.config", NULL);
6951 #if defined (HOST_WIN32)
6952 /* Avoid mixing '/' and '\\' */
6955 for (i = strlen (path) - 1; i >= 0; i--)
6956 if (path [i] == '/')
6960 mcpath = mono_string_new (mono_domain_get (), path);
6967 get_bundled_app_config (void)
6969 const gchar *app_config;
6972 gchar *config_file_name, *config_file_path;
6976 MONO_ARCH_SAVE_REGS;
6978 domain = mono_domain_get ();
6979 file = domain->setup->configuration_file;
6983 // Retrieve config file and remove the extension
6984 config_file_name = mono_string_to_utf8 (file);
6985 config_file_path = mono_portability_find_file (config_file_name, TRUE);
6986 if (!config_file_path)
6987 config_file_path = config_file_name;
6988 len = strlen (config_file_path) - strlen (".config");
6989 module = g_malloc0 (len + 1);
6990 memcpy (module, config_file_path, len);
6991 // Get the config file from the module name
6992 app_config = mono_config_string_for_assembly_file (module);
6995 if (config_file_name != config_file_path)
6996 g_free (config_file_name);
6997 g_free (config_file_path);
7002 return mono_string_new (mono_domain_get (), app_config);
7006 get_bundled_machine_config (void)
7008 const gchar *machine_config;
7010 MONO_ARCH_SAVE_REGS;
7012 machine_config = mono_get_machine_config ();
7014 if (!machine_config)
7017 return mono_string_new (mono_domain_get (), machine_config);
7020 ICALL_EXPORT MonoString *
7021 ves_icall_System_Web_Util_ICalls_get_machine_install_dir (void)
7026 MONO_ARCH_SAVE_REGS;
7028 path = g_path_get_dirname (mono_get_config_dir ());
7030 #if defined (HOST_WIN32)
7031 /* Avoid mixing '/' and '\\' */
7034 for (i = strlen (path) - 1; i >= 0; i--)
7035 if (path [i] == '/')
7039 ipath = mono_string_new (mono_domain_get (), path);
7045 ICALL_EXPORT gboolean
7046 ves_icall_get_resources_ptr (MonoReflectionAssembly *assembly, gpointer *result, gint32 *size)
7048 MonoPEResourceDataEntry *entry;
7051 MONO_ARCH_SAVE_REGS;
7053 if (!assembly || !result || !size)
7058 image = assembly->assembly->image;
7059 entry = mono_image_lookup_resource (image, MONO_PE_RESOURCE_ID_ASPNET_STRING, 0, NULL);
7063 *result = mono_image_rva_map (image, entry->rde_data_offset);
7068 *size = entry->rde_size;
7073 ICALL_EXPORT MonoBoolean
7074 ves_icall_System_Diagnostics_Debugger_IsAttached_internal (void)
7076 return mono_is_debugger_attached ();
7079 ICALL_EXPORT MonoBoolean
7080 ves_icall_System_Diagnostics_Debugger_IsLogging (void)
7082 if (mono_get_runtime_callbacks ()->debug_log_is_enabled)
7083 return mono_get_runtime_callbacks ()->debug_log_is_enabled ();
7089 ves_icall_System_Diagnostics_Debugger_Log (int level, MonoString *category, MonoString *message)
7091 if (mono_get_runtime_callbacks ()->debug_log)
7092 mono_get_runtime_callbacks ()->debug_log (level, category, message);
7096 ves_icall_System_Diagnostics_DefaultTraceListener_WriteWindowsDebugString (MonoString *message)
7098 #if defined (HOST_WIN32)
7099 OutputDebugString (mono_string_chars (message));
7101 g_warning ("WriteWindowsDebugString called and HOST_WIN32 not defined!\n");
7105 /* Only used for value types */
7106 ICALL_EXPORT MonoObject *
7107 ves_icall_System_Activator_CreateInstanceInternal (MonoReflectionType *type)
7112 MONO_ARCH_SAVE_REGS;
7114 domain = mono_object_domain (type);
7115 klass = mono_class_from_mono_type (type->type);
7116 mono_class_init_or_throw (klass);
7118 if (mono_class_is_nullable (klass))
7119 /* No arguments -> null */
7122 return mono_object_new (domain, klass);
7125 ICALL_EXPORT MonoReflectionMethod *
7126 ves_icall_MonoMethod_get_base_method (MonoReflectionMethod *m, gboolean definition)
7128 MonoClass *klass, *parent;
7129 MonoMethod *method = m->method;
7130 MonoMethod *result = NULL;
7133 MONO_ARCH_SAVE_REGS;
7135 if (method->klass == NULL)
7138 if (!(method->flags & METHOD_ATTRIBUTE_VIRTUAL) ||
7139 MONO_CLASS_IS_INTERFACE (method->klass) ||
7140 method->flags & METHOD_ATTRIBUTE_NEW_SLOT)
7143 slot = mono_method_get_vtable_slot (method);
7147 klass = method->klass;
7148 if (klass->generic_class)
7149 klass = klass->generic_class->container_class;
7152 /* At the end of the loop, klass points to the eldest class that has this virtual function slot. */
7153 for (parent = klass->parent; parent != NULL; parent = parent->parent) {
7154 mono_class_setup_vtable (parent);
7155 if (parent->vtable_size <= slot)
7160 klass = klass->parent;
7165 if (klass == method->klass)
7168 /*This is possible if definition == FALSE.
7169 * Do it here to be really sure we don't read invalid memory.
7171 if (slot >= klass->vtable_size)
7174 mono_class_setup_vtable (klass);
7176 result = klass->vtable [slot];
7177 if (result == NULL) {
7178 /* It is an abstract method */
7179 gpointer iter = NULL;
7180 while ((result = mono_class_get_methods (klass, &iter)))
7181 if (result->slot == slot)
7188 return mono_method_get_object (mono_domain_get (), result, NULL);
7191 ICALL_EXPORT MonoString*
7192 ves_icall_MonoMethod_get_name (MonoReflectionMethod *m)
7194 MonoMethod *method = m->method;
7196 MONO_OBJECT_SETREF (m, name, mono_string_new (mono_object_domain (m), method->name));
7201 mono_ArgIterator_Setup (MonoArgIterator *iter, char* argsp, char* start)
7203 MONO_ARCH_SAVE_REGS;
7205 iter->sig = *(MonoMethodSignature**)argsp;
7207 g_assert (iter->sig->sentinelpos <= iter->sig->param_count);
7208 g_assert (iter->sig->call_convention == MONO_CALL_VARARG);
7211 /* FIXME: it's not documented what start is exactly... */
7215 iter->args = argsp + sizeof (gpointer);
7217 iter->num_args = iter->sig->param_count - iter->sig->sentinelpos;
7219 /* g_print ("sig %p, param_count: %d, sent: %d\n", iter->sig, iter->sig->param_count, iter->sig->sentinelpos); */
7222 ICALL_EXPORT MonoTypedRef
7223 mono_ArgIterator_IntGetNextArg (MonoArgIterator *iter)
7225 guint32 i, arg_size;
7228 MONO_ARCH_SAVE_REGS;
7230 i = iter->sig->sentinelpos + iter->next_arg;
7232 g_assert (i < iter->sig->param_count);
7234 res.type = iter->sig->params [i];
7235 res.klass = mono_class_from_mono_type (res.type);
7236 arg_size = mono_type_stack_size (res.type, &align);
7237 #if defined(__arm__) || defined(__mips__)
7238 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7240 res.value = iter->args;
7241 #if defined(__native_client__) && SIZEOF_REGISTER == 8
7242 /* Values are stored as 8 byte register sized objects, but 'value'
7243 * is dereferenced as a pointer in other routines.
7245 res.value = (char*)res.value + 4;
7247 #if G_BYTE_ORDER != G_LITTLE_ENDIAN
7248 if (arg_size <= sizeof (gpointer)) {
7250 int padding = arg_size - mono_type_size (res.type, &dummy);
7251 res.value = (guint8*)res.value + padding;
7254 iter->args = (char*)iter->args + arg_size;
7257 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7262 ICALL_EXPORT MonoTypedRef
7263 mono_ArgIterator_IntGetNextArgT (MonoArgIterator *iter, MonoType *type)
7265 guint32 i, arg_size;
7268 MONO_ARCH_SAVE_REGS;
7270 i = iter->sig->sentinelpos + iter->next_arg;
7272 g_assert (i < iter->sig->param_count);
7274 while (i < iter->sig->param_count) {
7275 if (!mono_metadata_type_equal (type, iter->sig->params [i]))
7277 res.type = iter->sig->params [i];
7278 res.klass = mono_class_from_mono_type (res.type);
7279 /* FIXME: endianess issue... */
7280 arg_size = mono_type_stack_size (res.type, &align);
7281 #if defined(__arm__) || defined(__mips__)
7282 iter->args = (guint8*)(((gsize)iter->args + (align) - 1) & ~(align - 1));
7284 res.value = iter->args;
7285 iter->args = (char*)iter->args + arg_size;
7287 /* g_print ("returning arg %d, type 0x%02x of size %d at %p\n", i, res.type->type, arg_size, res.value); */
7290 /* g_print ("arg type 0x%02x not found\n", res.type->type); */
7298 ICALL_EXPORT MonoType*
7299 mono_ArgIterator_IntGetNextArgType (MonoArgIterator *iter)
7302 MONO_ARCH_SAVE_REGS;
7304 i = iter->sig->sentinelpos + iter->next_arg;
7306 g_assert (i < iter->sig->param_count);
7308 return iter->sig->params [i];
7311 ICALL_EXPORT MonoObject*
7312 mono_TypedReference_ToObject (MonoTypedRef tref)
7314 MONO_ARCH_SAVE_REGS;
7316 if (MONO_TYPE_IS_REFERENCE (tref.type)) {
7317 MonoObject** objp = tref.value;
7321 return mono_value_box (mono_domain_get (), tref.klass, tref.value);
7324 ICALL_EXPORT MonoObject*
7325 mono_TypedReference_ToObjectInternal (MonoType *type, gpointer value, MonoClass *klass)
7327 MONO_ARCH_SAVE_REGS;
7329 if (MONO_TYPE_IS_REFERENCE (type)) {
7330 MonoObject** objp = value;
7334 return mono_value_box (mono_domain_get (), klass, value);
7338 prelink_method (MonoMethod *method)
7340 const char *exc_class, *exc_arg;
7341 if (!(method->flags & METHOD_ATTRIBUTE_PINVOKE_IMPL))
7343 mono_lookup_pinvoke_call (method, &exc_class, &exc_arg);
7345 mono_raise_exception(
7346 mono_exception_from_name_msg (mono_defaults.corlib, "System", exc_class, exc_arg ) );
7348 /* create the wrapper, too? */
7352 ves_icall_System_Runtime_InteropServices_Marshal_Prelink (MonoReflectionMethod *method)
7354 MONO_ARCH_SAVE_REGS;
7355 prelink_method (method->method);
7359 ves_icall_System_Runtime_InteropServices_Marshal_PrelinkAll (MonoReflectionType *type)
7361 MonoClass *klass = mono_class_from_mono_type (type->type);
7363 gpointer iter = NULL;
7364 MONO_ARCH_SAVE_REGS;
7366 mono_class_init_or_throw (klass);
7368 while ((m = mono_class_get_methods (klass, &iter)))
7372 /* These parameters are "readonly" in corlib/System/NumberFormatter.cs */
7374 ves_icall_System_NumberFormatter_GetFormatterTables (guint64 const **mantissas,
7375 gint32 const **exponents,
7376 gunichar2 const **digitLowerTable,
7377 gunichar2 const **digitUpperTable,
7378 gint64 const **tenPowersList,
7379 gint32 const **decHexDigits)
7381 *mantissas = Formatter_MantissaBitsTable;
7382 *exponents = Formatter_TensExponentTable;
7383 *digitLowerTable = Formatter_DigitLowerTable;
7384 *digitUpperTable = Formatter_DigitUpperTable;
7385 *tenPowersList = Formatter_TenPowersList;
7386 *decHexDigits = Formatter_DecHexDigits;
7390 get_category_data (int version,
7391 guint8 const **category_data,
7392 guint16 const **category_astral_index)
7394 *category_astral_index = NULL;
7396 #ifndef DISABLE_NET_4_0
7398 *category_data = CategoryData_v4;
7399 #ifndef DISABLE_ASTRAL
7400 *category_astral_index = CategoryData_v4_astral_index;
7406 *category_data = CategoryData_v2;
7407 #ifndef DISABLE_ASTRAL
7408 *category_astral_index = CategoryData_v2_astral_index;
7412 /* These parameters are "readonly" in corlib/System/Char.cs */
7414 ves_icall_System_Char_GetDataTablePointers (int category_data_version,
7415 guint8 const **category_data,
7416 guint16 const **category_astral_index,
7417 guint8 const **numeric_data,
7418 gdouble const **numeric_data_values,
7419 guint16 const **to_lower_data_low,
7420 guint16 const **to_lower_data_high,
7421 guint16 const **to_upper_data_low,
7422 guint16 const **to_upper_data_high)
7424 get_category_data (category_data_version, category_data, category_astral_index);
7425 *numeric_data = NumericData;
7426 *numeric_data_values = NumericDataValues;
7427 *to_lower_data_low = ToLowerDataLow;
7428 *to_lower_data_high = ToLowerDataHigh;
7429 *to_upper_data_low = ToUpperDataLow;
7430 *to_upper_data_high = ToUpperDataHigh;
7434 * We return NULL for no modifiers so the corlib code can return Type.EmptyTypes
7435 * and avoid useless allocations.
7440 type_array_from_modifiers (MonoImage *image, MonoType *type, int optional)
7444 for (i = 0; i < type->num_mods; ++i) {
7445 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required))
7450 res = mono_array_new (mono_domain_get (), mono_defaults.systemtype_class, count);
7452 for (i = 0; i < type->num_mods; ++i) {
7453 if ((optional && !type->modifiers [i].required) || (!optional && type->modifiers [i].required)) {
7455 MonoClass *klass = mono_class_get_checked (image, type->modifiers [i].token, &error);
7456 mono_error_raise_exception (&error); /* this is safe, no cleanup needed on callers */
7457 mono_array_setref (res, count, mono_type_get_object (mono_domain_get (), &klass->byval_arg));
7464 ICALL_EXPORT MonoArray*
7465 param_info_get_type_modifiers (MonoReflectionParameter *param, MonoBoolean optional)
7467 MonoType *type = param->ClassImpl->type;
7468 MonoClass *member_class = mono_object_class (param->MemberImpl);
7469 MonoMethod *method = NULL;
7472 MonoMethodSignature *sig;
7474 if (mono_class_is_reflection_method_or_constructor (member_class)) {
7475 MonoReflectionMethod *rmethod = (MonoReflectionMethod*)param->MemberImpl;
7476 method = rmethod->method;
7477 } else if (member_class->image == mono_defaults.corlib && !strcmp ("MonoProperty", member_class->name)) {
7478 MonoReflectionProperty *prop = (MonoReflectionProperty *)param->MemberImpl;
7479 if (!(method = prop->property->get))
7480 method = prop->property->set;
7483 char *type_name = mono_type_get_full_name (member_class);
7484 char *msg = g_strdup_printf ("Custom modifiers on a ParamInfo with member %s are not supported", type_name);
7485 MonoException *ex = mono_get_exception_not_supported (msg);
7488 mono_raise_exception (ex);
7491 image = method->klass->image;
7492 pos = param->PositionImpl;
7493 sig = mono_method_signature (method);
7497 type = sig->params [pos];
7499 return type_array_from_modifiers (image, type, optional);
7503 get_property_type (MonoProperty *prop)
7505 MonoMethodSignature *sig;
7507 sig = mono_method_signature (prop->get);
7509 } else if (prop->set) {
7510 sig = mono_method_signature (prop->set);
7511 return sig->params [sig->param_count - 1];
7516 ICALL_EXPORT MonoArray*
7517 property_info_get_type_modifiers (MonoReflectionProperty *property, MonoBoolean optional)
7519 MonoType *type = get_property_type (property->property);
7520 MonoImage *image = property->klass->image;
7524 return type_array_from_modifiers (image, type, optional);
7528 *Construct a MonoType suited to be used to decode a constant blob object.
7530 * @type is the target type which will be constructed
7531 * @blob_type is the blob type, for example, that comes from the constant table
7532 * @real_type is the expected constructed type.
7535 mono_type_from_blob_type (MonoType *type, MonoTypeEnum blob_type, MonoType *real_type)
7537 type->type = blob_type;
7538 type->data.klass = NULL;
7539 if (blob_type == MONO_TYPE_CLASS)
7540 type->data.klass = mono_defaults.object_class;
7541 else if (real_type->type == MONO_TYPE_VALUETYPE && real_type->data.klass->enumtype) {
7542 /* For enums, we need to use the base type */
7543 type->type = MONO_TYPE_VALUETYPE;
7544 type->data.klass = mono_class_from_mono_type (real_type);
7546 type->data.klass = mono_class_from_mono_type (real_type);
7549 ICALL_EXPORT MonoObject*
7550 property_info_get_default_value (MonoReflectionProperty *property)
7553 MonoProperty *prop = property->property;
7554 MonoType *type = get_property_type (prop);
7555 MonoDomain *domain = mono_object_domain (property);
7556 MonoTypeEnum def_type;
7557 const char *def_value;
7560 mono_class_init (prop->parent);
7562 if (!(prop->attrs & PROPERTY_ATTRIBUTE_HAS_DEFAULT))
7563 mono_raise_exception (mono_get_exception_invalid_operation (NULL));
7565 def_value = mono_class_get_property_default_value (prop, &def_type);
7567 mono_type_from_blob_type (&blob_type, def_type, type);
7568 o = mono_get_object_from_blob (domain, &blob_type, def_value);
7573 ICALL_EXPORT MonoBoolean
7574 custom_attrs_defined_internal (MonoObject *obj, MonoReflectionType *attr_type)
7576 MonoClass *attr_class = mono_class_from_mono_type (attr_type->type);
7577 MonoCustomAttrInfo *cinfo;
7580 mono_class_init_or_throw (attr_class);
7582 cinfo = mono_reflection_get_custom_attrs_info (obj);
7585 found = mono_custom_attrs_has_attr (cinfo, attr_class);
7587 mono_custom_attrs_free (cinfo);
7591 ICALL_EXPORT MonoArray*
7592 custom_attrs_get_by_type (MonoObject *obj, MonoReflectionType *attr_type)
7594 MonoClass *attr_class = attr_type ? mono_class_from_mono_type (attr_type->type) : NULL;
7599 mono_class_init_or_throw (attr_class);
7601 res = mono_reflection_get_custom_attrs_by_type (obj, attr_class, &error);
7602 mono_error_raise_exception (&error);
7604 if (mono_loader_get_last_error ()) {
7605 mono_raise_exception (mono_loader_error_prepare_exception (mono_loader_get_last_error ()));
7606 g_assert_not_reached ();
7614 ICALL_EXPORT MonoString*
7615 ves_icall_Mono_Runtime_GetDisplayName (void)
7618 MonoString *display_name;
7620 info = mono_get_runtime_callbacks ()->get_runtime_build_info ();
7621 display_name = mono_string_new (mono_domain_get (), info);
7623 return display_name;
7626 ICALL_EXPORT MonoString*
7627 ves_icall_System_ComponentModel_Win32Exception_W32ErrorMessage (guint32 code)
7629 MonoString *message;
7633 ret = FormatMessage (FORMAT_MESSAGE_FROM_SYSTEM |
7634 FORMAT_MESSAGE_IGNORE_INSERTS, NULL, code, 0,
7637 message = mono_string_new (mono_domain_get (), "Error looking up error string");
7639 message = mono_string_new_utf16 (mono_domain_get (), buf, ret);
7647 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7648 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128,
7649 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 128, 62, 128, 128, 128, 63,
7650 52, 53, 54, 55, 56, 57, 58, 59, 60, 61, 128, 128, 128, 0, 128, 128,
7651 128, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14,
7652 15, 16, 17, 18, 19, 20, 21, 22, 23, 24, 25, 128, 128, 128, 128, 128,
7653 128, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35, 36, 37, 38, 39, 40,
7654 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51
7658 base64_to_byte_array (gunichar2 *start, gint ilength, MonoBoolean allowWhitespaceOnly)
7663 gunichar2 last, prev_last, prev2_last;
7670 int havePadding = 0;
7672 last = prev_last = 0, prev2_last = 0;
7673 for (i = 0; i < ilength; i++) {
7675 if (c >= sizeof (dbase64)) {
7676 exc = mono_exception_from_name_msg (mono_get_corlib (),
7677 "System", "FormatException",
7678 "Invalid character found.");
7679 mono_raise_exception (exc);
7680 } else if (isspace (c)) {
7682 } else if (havePadding && c != '=') {
7683 exc = mono_exception_from_name_msg (mono_get_corlib (),
7684 "System", "FormatException",
7685 "Invalid character found.");
7686 mono_raise_exception (exc);
7688 if (c == '=') havePadding = 1;
7689 prev2_last = prev_last;
7695 olength = ilength - ignored;
7697 if (allowWhitespaceOnly && olength == 0) {
7698 return mono_array_new (mono_domain_get (), mono_defaults.byte_class, 0);
7701 if ((olength & 3) != 0 || olength <= 0) {
7702 exc = mono_exception_from_name_msg (mono_get_corlib (), "System",
7703 "FormatException", "Invalid length.");
7704 mono_raise_exception (exc);
7707 if (prev2_last == '=') {
7708 exc = mono_exception_from_name_msg (mono_get_corlib (), "System", "FormatException", "Invalid format.");
7709 mono_raise_exception (exc);
7712 olength = (olength * 3) / 4;
7716 if (prev_last == '=')
7719 result = mono_array_new (mono_domain_get (), mono_defaults.byte_class, olength);
7720 res_ptr = mono_array_addr (result, guchar, 0);
7721 for (i = 0; i < ilength; ) {
7724 for (k = 0; k < 4 && i < ilength;) {
7730 if (((b [k] = dbase64 [c]) & 0x80) != 0) {
7731 exc = mono_exception_from_name_msg (mono_get_corlib (),
7732 "System", "FormatException",
7733 "Invalid character found.");
7734 mono_raise_exception (exc);
7739 *res_ptr++ = (b [0] << 2) | (b [1] >> 4);
7741 *res_ptr++ = (b [1] << 4) | (b [2] >> 2);
7743 *res_ptr++ = (b [2] << 6) | b [3];
7745 while (i < ilength && isspace (start [i]))
7752 ICALL_EXPORT MonoArray *
7753 InternalFromBase64String (MonoString *str, MonoBoolean allowWhitespaceOnly)
7755 MONO_ARCH_SAVE_REGS;
7757 return base64_to_byte_array (mono_string_chars (str),
7758 mono_string_length (str), allowWhitespaceOnly);
7761 ICALL_EXPORT MonoArray *
7762 InternalFromBase64CharArray (MonoArray *input, gint offset, gint length)
7764 MONO_ARCH_SAVE_REGS;
7766 return base64_to_byte_array (mono_array_addr (input, gunichar2, offset),
7770 #ifndef DISABLE_ICALL_TABLES
7772 #define ICALL_TYPE(id,name,first)
7773 #define ICALL(id,name,func) Icall_ ## id,
7776 #include "metadata/icall-def.h"
7782 #define ICALL_TYPE(id,name,first) Icall_type_ ## id,
7783 #define ICALL(id,name,func)
7785 #include "metadata/icall-def.h"
7791 #define ICALL_TYPE(id,name,firstic) {(Icall_ ## firstic)},
7792 #define ICALL(id,name,func)
7794 guint16 first_icall;
7797 static const IcallTypeDesc
7798 icall_type_descs [] = {
7799 #include "metadata/icall-def.h"
7803 #define icall_desc_num_icalls(desc) ((desc) [1].first_icall - (desc) [0].first_icall)
7806 #define ICALL_TYPE(id,name,first)
7809 #ifdef HAVE_ARRAY_ELEM_INIT
7810 #define MSGSTRFIELD(line) MSGSTRFIELD1(line)
7811 #define MSGSTRFIELD1(line) str##line
7813 static const struct msgstrtn_t {
7814 #define ICALL(id,name,func)
7816 #define ICALL_TYPE(id,name,first) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7817 #include "metadata/icall-def.h"
7819 } icall_type_names_str = {
7820 #define ICALL_TYPE(id,name,first) (name),
7821 #include "metadata/icall-def.h"
7824 static const guint16 icall_type_names_idx [] = {
7825 #define ICALL_TYPE(id,name,first) [Icall_type_ ## id] = offsetof (struct msgstrtn_t, MSGSTRFIELD(__LINE__)),
7826 #include "metadata/icall-def.h"
7829 #define icall_type_name_get(id) ((const char*)&icall_type_names_str + icall_type_names_idx [(id)])
7831 static const struct msgstr_t {
7833 #define ICALL_TYPE(id,name,first)
7834 #define ICALL(id,name,func) char MSGSTRFIELD(__LINE__) [sizeof (name)];
7835 #include "metadata/icall-def.h"
7837 } icall_names_str = {
7838 #define ICALL(id,name,func) (name),
7839 #include "metadata/icall-def.h"
7842 static const guint16 icall_names_idx [] = {
7843 #define ICALL(id,name,func) [Icall_ ## id] = offsetof (struct msgstr_t, MSGSTRFIELD(__LINE__)),
7844 #include "metadata/icall-def.h"
7847 #define icall_name_get(id) ((const char*)&icall_names_str + icall_names_idx [(id)])
7853 #define ICALL_TYPE(id,name,first) name,
7854 #define ICALL(id,name,func)
7855 static const char* const
7856 icall_type_names [] = {
7857 #include "metadata/icall-def.h"
7861 #define icall_type_name_get(id) (icall_type_names [(id)])
7865 #define ICALL_TYPE(id,name,first)
7866 #define ICALL(id,name,func) name,
7867 static const char* const
7869 #include "metadata/icall-def.h"
7872 #define icall_name_get(id) icall_names [(id)]
7874 #endif /* !HAVE_ARRAY_ELEM_INIT */
7878 #define ICALL_TYPE(id,name,first)
7879 #define ICALL(id,name,func) func,
7880 static const gconstpointer
7881 icall_functions [] = {
7882 #include "metadata/icall-def.h"
7886 #ifdef ENABLE_ICALL_SYMBOL_MAP
7889 #define ICALL_TYPE(id,name,first)
7890 #define ICALL(id,name,func) #func,
7891 static const gconstpointer
7892 icall_symbols [] = {
7893 #include "metadata/icall-def.h"
7898 #endif /* DISABLE_ICALL_TABLES */
7900 static mono_mutex_t icall_mutex;
7901 static GHashTable *icall_hash = NULL;
7902 static GHashTable *jit_icall_hash_name = NULL;
7903 static GHashTable *jit_icall_hash_addr = NULL;
7906 mono_icall_init (void)
7908 #ifndef DISABLE_ICALL_TABLES
7911 /* check that tables are sorted: disable in release */
7914 const char *prev_class = NULL;
7915 const char *prev_method;
7917 for (i = 0; i < Icall_type_num; ++i) {
7918 const IcallTypeDesc *desc;
7921 if (prev_class && strcmp (prev_class, icall_type_name_get (i)) >= 0)
7922 g_print ("class %s should come before class %s\n", icall_type_name_get (i), prev_class);
7923 prev_class = icall_type_name_get (i);
7924 desc = &icall_type_descs [i];
7925 num_icalls = icall_desc_num_icalls (desc);
7926 /*g_print ("class %s has %d icalls starting at %d\n", prev_class, num_icalls, desc->first_icall);*/
7927 for (j = 0; j < num_icalls; ++j) {
7928 const char *methodn = icall_name_get (desc->first_icall + j);
7929 if (prev_method && strcmp (prev_method, methodn) >= 0)
7930 g_print ("method %s should come before method %s\n", methodn, prev_method);
7931 prev_method = methodn;
7937 icall_hash = g_hash_table_new_full (g_str_hash, g_str_equal, g_free, NULL);
7938 mono_mutex_init (&icall_mutex);
7942 mono_icall_lock (void)
7944 mono_locks_mutex_acquire (&icall_mutex, IcallLock);
7948 mono_icall_unlock (void)
7950 mono_locks_mutex_release (&icall_mutex, IcallLock);
7954 mono_icall_cleanup (void)
7956 g_hash_table_destroy (icall_hash);
7957 g_hash_table_destroy (jit_icall_hash_name);
7958 g_hash_table_destroy (jit_icall_hash_addr);
7959 mono_mutex_destroy (&icall_mutex);
7963 mono_add_internal_call (const char *name, gconstpointer method)
7967 g_hash_table_insert (icall_hash, g_strdup (name), (gpointer) method);
7969 mono_icall_unlock ();
7972 #ifndef DISABLE_ICALL_TABLES
7974 #ifdef HAVE_ARRAY_ELEM_INIT
7976 compare_method_imap (const void *key, const void *elem)
7978 const char* method_name = (const char*)&icall_names_str + (*(guint16*)elem);
7979 return strcmp (key, method_name);
7983 find_method_icall (const IcallTypeDesc *imap, const char *name)
7985 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);
7988 return (gpointer)icall_functions [(nameslot - &icall_names_idx [0])];
7992 compare_class_imap (const void *key, const void *elem)
7994 const char* class_name = (const char*)&icall_type_names_str + (*(guint16*)elem);
7995 return strcmp (key, class_name);
7998 static const IcallTypeDesc*
7999 find_class_icalls (const char *name)
8001 const guint16 *nameslot = mono_binary_search (name, icall_type_names_idx, Icall_type_num, sizeof (icall_type_names_idx [0]), compare_class_imap);
8004 return &icall_type_descs [nameslot - &icall_type_names_idx [0]];
8007 #else /* HAVE_ARRAY_ELEM_INIT */
8010 compare_method_imap (const void *key, const void *elem)
8012 const char** method_name = (const char**)elem;
8013 return strcmp (key, *method_name);
8017 find_method_icall (const IcallTypeDesc *imap, const char *name)
8019 const char **nameslot = mono_binary_search (name, icall_names + imap->first_icall, icall_desc_num_icalls (imap), sizeof (icall_names [0]), compare_method_imap);
8022 return (gpointer)icall_functions [(nameslot - icall_names)];
8026 compare_class_imap (const void *key, const void *elem)
8028 const char** class_name = (const char**)elem;
8029 return strcmp (key, *class_name);
8032 static const IcallTypeDesc*
8033 find_class_icalls (const char *name)
8035 const char **nameslot = mono_binary_search (name, icall_type_names, Icall_type_num, sizeof (icall_type_names [0]), compare_class_imap);
8038 return &icall_type_descs [nameslot - icall_type_names];
8041 #endif /* HAVE_ARRAY_ELEM_INIT */
8043 #endif /* DISABLE_ICALL_TABLES */
8046 * we should probably export this as an helper (handle nested types).
8047 * Returns the number of chars written in buf.
8050 concat_class_name (char *buf, int bufsize, MonoClass *klass)
8052 int nspacelen, cnamelen;
8053 nspacelen = strlen (klass->name_space);
8054 cnamelen = strlen (klass->name);
8055 if (nspacelen + cnamelen + 2 > bufsize)
8058 memcpy (buf, klass->name_space, nspacelen);
8059 buf [nspacelen ++] = '.';
8061 memcpy (buf + nspacelen, klass->name, cnamelen);
8062 buf [nspacelen + cnamelen] = 0;
8063 return nspacelen + cnamelen;
8066 #ifdef DISABLE_ICALL_TABLES
8068 no_icall_table (void)
8070 g_assert_not_reached ();
8075 mono_lookup_internal_call (MonoMethod *method)
8080 int typelen = 0, mlen, siglen;
8082 #ifndef DISABLE_ICALL_TABLES
8083 const IcallTypeDesc *imap = NULL;
8086 g_assert (method != NULL);
8088 if (method->is_inflated)
8089 method = ((MonoMethodInflated *) method)->declaring;
8091 if (method->klass->nested_in) {
8092 int pos = concat_class_name (mname, sizeof (mname)-2, method->klass->nested_in);
8096 mname [pos++] = '/';
8099 typelen = concat_class_name (mname+pos, sizeof (mname)-pos-1, method->klass);
8105 typelen = concat_class_name (mname, sizeof (mname), method->klass);
8110 #ifndef DISABLE_ICALL_TABLES
8111 imap = find_class_icalls (mname);
8114 mname [typelen] = ':';
8115 mname [typelen + 1] = ':';
8117 mlen = strlen (method->name);
8118 memcpy (mname + typelen + 2, method->name, mlen);
8119 sigstart = mname + typelen + 2 + mlen;
8122 tmpsig = mono_signature_get_desc (mono_method_signature (method), TRUE);
8123 siglen = strlen (tmpsig);
8124 if (typelen + mlen + siglen + 6 > sizeof (mname))
8127 memcpy (sigstart + 1, tmpsig, siglen);
8128 sigstart [siglen + 1] = ')';
8129 sigstart [siglen + 2] = 0;
8134 res = g_hash_table_lookup (icall_hash, mname);
8136 mono_icall_unlock ();;
8139 /* try without signature */
8141 res = g_hash_table_lookup (icall_hash, mname);
8143 mono_icall_unlock ();
8147 #ifdef DISABLE_ICALL_TABLES
8148 mono_icall_unlock ();
8149 /* Fail only when the result is actually used */
8150 /* mono_marshal_get_native_wrapper () depends on this */
8151 if (method->klass == mono_defaults.string_class && !strcmp (method->name, ".ctor"))
8152 return ves_icall_System_String_ctor_RedirectToCreateString;
8154 return no_icall_table;
8156 /* it wasn't found in the static call tables */
8158 mono_icall_unlock ();
8161 res = find_method_icall (imap, sigstart - mlen);
8163 mono_icall_unlock ();
8166 /* try _with_ signature */
8168 res = find_method_icall (imap, sigstart - mlen);
8170 mono_icall_unlock ();
8174 g_warning ("cant resolve internal call to \"%s\" (tested without signature also)", mname);
8175 g_print ("\nYour mono runtime and class libraries are out of sync.\n");
8176 g_print ("The out of sync library is: %s\n", method->klass->image->name);
8177 g_print ("\nWhen you update one from svn you need to update, compile and install\nthe other too.\n");
8178 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");
8179 g_print ("If you see other errors or faults after this message they are probably related\n");
8180 g_print ("and you need to fix your mono install first.\n");
8182 mono_icall_unlock ();
8188 #ifdef ENABLE_ICALL_SYMBOL_MAP
8190 func_cmp (gconstpointer key, gconstpointer p)
8192 return (gsize)key - (gsize)*(gsize*)p;
8197 * mono_lookup_icall_symbol:
8199 * Given the icall METHOD, returns its C symbol.
8202 mono_lookup_icall_symbol (MonoMethod *m)
8204 #ifdef DISABLE_ICALL_TABLES
8205 g_assert_not_reached ();
8208 #ifdef ENABLE_ICALL_SYMBOL_MAP
8212 static gconstpointer *functions_sorted;
8213 static const char**symbols_sorted;
8214 static gboolean inited;
8219 functions_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8220 memcpy (functions_sorted, icall_functions, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8221 symbols_sorted = g_malloc (G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8222 memcpy (symbols_sorted, icall_symbols, G_N_ELEMENTS (icall_functions) * sizeof (gpointer));
8223 /* Bubble sort the two arrays */
8227 for (i = 0; i < G_N_ELEMENTS (icall_functions) - 1; ++i) {
8228 if (functions_sorted [i] > functions_sorted [i + 1]) {
8231 tmp = functions_sorted [i];
8232 functions_sorted [i] = functions_sorted [i + 1];
8233 functions_sorted [i + 1] = tmp;
8234 tmp = symbols_sorted [i];
8235 symbols_sorted [i] = symbols_sorted [i + 1];
8236 symbols_sorted [i + 1] = tmp;
8243 func = mono_lookup_internal_call (m);
8246 slot = mono_binary_search (func, functions_sorted, G_N_ELEMENTS (icall_functions), sizeof (gpointer), func_cmp);
8250 return symbols_sorted [(gpointer*)slot - (gpointer*)functions_sorted];
8252 fprintf (stderr, "icall symbol maps not enabled, pass --enable-icall-symbol-map to configure.\n");
8253 g_assert_not_reached ();
8260 type_from_typename (char *typename)
8262 MonoClass *klass = NULL; /* assignment to shut GCC warning up */
8264 if (!strcmp (typename, "int"))
8265 klass = mono_defaults.int_class;
8266 else if (!strcmp (typename, "ptr"))
8267 klass = mono_defaults.int_class;
8268 else if (!strcmp (typename, "void"))
8269 klass = mono_defaults.void_class;
8270 else if (!strcmp (typename, "int32"))
8271 klass = mono_defaults.int32_class;
8272 else if (!strcmp (typename, "uint32"))
8273 klass = mono_defaults.uint32_class;
8274 else if (!strcmp (typename, "int8"))
8275 klass = mono_defaults.sbyte_class;
8276 else if (!strcmp (typename, "uint8"))
8277 klass = mono_defaults.byte_class;
8278 else if (!strcmp (typename, "int16"))
8279 klass = mono_defaults.int16_class;
8280 else if (!strcmp (typename, "uint16"))
8281 klass = mono_defaults.uint16_class;
8282 else if (!strcmp (typename, "long"))
8283 klass = mono_defaults.int64_class;
8284 else if (!strcmp (typename, "ulong"))
8285 klass = mono_defaults.uint64_class;
8286 else if (!strcmp (typename, "float"))
8287 klass = mono_defaults.single_class;
8288 else if (!strcmp (typename, "double"))
8289 klass = mono_defaults.double_class;
8290 else if (!strcmp (typename, "object"))
8291 klass = mono_defaults.object_class;
8292 else if (!strcmp (typename, "obj"))
8293 klass = mono_defaults.object_class;
8294 else if (!strcmp (typename, "string"))
8295 klass = mono_defaults.string_class;
8296 else if (!strcmp (typename, "bool"))
8297 klass = mono_defaults.boolean_class;
8298 else if (!strcmp (typename, "boolean"))
8299 klass = mono_defaults.boolean_class;
8301 g_error ("%s", typename);
8302 g_assert_not_reached ();
8304 return &klass->byval_arg;
8308 * LOCKING: Take the corlib image lock.
8310 MonoMethodSignature*
8311 mono_create_icall_signature (const char *sigstr)
8316 MonoMethodSignature *res, *res2;
8317 MonoImage *corlib = mono_defaults.corlib;
8319 mono_image_lock (corlib);
8320 res = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8321 mono_image_unlock (corlib);
8326 parts = g_strsplit (sigstr, " ", 256);
8335 res = mono_metadata_signature_alloc (corlib, len - 1);
8340 * Under windows, the default pinvoke calling convention is STDCALL but
8343 res->call_convention = MONO_CALL_C;
8346 res->ret = type_from_typename (parts [0]);
8347 for (i = 1; i < len; ++i) {
8348 res->params [i - 1] = type_from_typename (parts [i]);
8353 mono_image_lock (corlib);
8354 res2 = g_hash_table_lookup (corlib->helper_signatures, sigstr);
8356 res = res2; /*Value is allocated in the image pool*/
8358 g_hash_table_insert (corlib->helper_signatures, (gpointer)sigstr, res);
8359 mono_image_unlock (corlib);
8365 mono_find_jit_icall_by_name (const char *name)
8367 MonoJitICallInfo *info;
8368 g_assert (jit_icall_hash_name);
8371 info = g_hash_table_lookup (jit_icall_hash_name, name);
8372 mono_icall_unlock ();
8377 mono_find_jit_icall_by_addr (gconstpointer addr)
8379 MonoJitICallInfo *info;
8380 g_assert (jit_icall_hash_addr);
8383 info = g_hash_table_lookup (jit_icall_hash_addr, (gpointer)addr);
8384 mono_icall_unlock ();
8390 * mono_get_jit_icall_info:
8392 * Return the hashtable mapping JIT icall names to MonoJitICallInfo structures. The
8393 * caller should access it while holding the icall lock.
8396 mono_get_jit_icall_info (void)
8398 return jit_icall_hash_name;
8402 * mono_lookup_jit_icall_symbol:
8404 * Given the jit icall NAME, returns its C symbol if possible, or NULL.
8407 mono_lookup_jit_icall_symbol (const char *name)
8409 MonoJitICallInfo *info;
8410 const char *res = NULL;
8413 info = g_hash_table_lookup (jit_icall_hash_name, name);
8415 res = info->c_symbol;
8416 mono_icall_unlock ();
8421 mono_register_jit_icall_wrapper (MonoJitICallInfo *info, gconstpointer wrapper)
8424 g_hash_table_insert (jit_icall_hash_addr, (gpointer)wrapper, info);
8425 mono_icall_unlock ();
8429 mono_register_jit_icall_full (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save, const char *c_symbol)
8431 MonoJitICallInfo *info;
8438 if (!jit_icall_hash_name) {
8439 jit_icall_hash_name = g_hash_table_new_full (g_str_hash, g_str_equal, NULL, g_free);
8440 jit_icall_hash_addr = g_hash_table_new (NULL, NULL);
8443 if (g_hash_table_lookup (jit_icall_hash_name, name)) {
8444 g_warning ("jit icall already defined \"%s\"\n", name);
8445 g_assert_not_reached ();
8448 info = g_new0 (MonoJitICallInfo, 1);
8453 info->c_symbol = c_symbol;
8456 info->wrapper = func;
8458 info->wrapper = NULL;
8461 g_hash_table_insert (jit_icall_hash_name, (gpointer)info->name, info);
8462 g_hash_table_insert (jit_icall_hash_addr, (gpointer)func, info);
8464 mono_icall_unlock ();
8469 mono_register_jit_icall (gconstpointer func, const char *name, MonoMethodSignature *sig, gboolean is_save)
8471 return mono_register_jit_icall_full (func, name, sig, is_save, NULL);